第一届长城杯信息安全铁人三项赛初赛
LoginToMe #
main 函数核心逻辑,s 为长度 20 的字符串
if ( *(unsigned __int16 *)s * *(unsigned __int16 *)&s[2] == 342772773
&& *(unsigned __int16 *)s + *(unsigned __int16 *)&s[2] == 39526
&& *(_DWORD *)&s[4] - *(_DWORD *)&s[8] == 1005712381
&& *(unsigned __int16 *)&s[4] + *(unsigned __int16 *)&s[6] == 56269
&& *(unsigned __int16 *)&s[8] - *(unsigned __int16 *)&s[10] == 15092
&& s[4] * s[8] == 10710
&& s[6] * s[10] == 12051
&& s[7] + s[11] == 172
&& *(unsigned __int16 *)&s[12] * *(unsigned __int16 *)&s[14] == 171593250
&& *(unsigned __int16 *)&s[12] + *(unsigned __int16 *)&s[14] == 26219
&& *(unsigned __int16 *)&s[16] * *(unsigned __int16 *)&s[18] == 376306868
&& *(unsigned __int16 *)&s[16] + *(unsigned __int16 *)&s[18] == 0x9D95 )
{
puts("check ok~!");
}
实际上就是解方程,可以直接用 z3 去解,拼接 flag 时要注意 z3 使用的是大端
这题是有特别多解的,可以再套一个多解脚本
from z3 import *
flag_bytes = [BitVec("x%d" % i, 8) for i in range(20)]
s = Solver()
for i in range(4 * 5):
s.add(flag_bytes[i] < 127)
s.add(flag_bytes[i] > 32)
flag_words = [Concat(flag_bytes[i+1], flag_bytes[i]) for i in range(0, 20, 2)]
flag_dwords = [Concat(flag_bytes[i+3], flag_bytes[i+2], flag_bytes[i+1], flag_bytes[i]) for i in range(0, 20, 4)]
conds = [
flag_words[0] * flag_words[1] == 342772773,
flag_words[0] + flag_words[1] == 39526,
flag_dwords[1] - flag_dwords[2] == 1005712381,
flag_words[2] + flag_words[3] == 56269,
flag_words[4] - flag_words[5] == 15092,
flag_bytes[4] * flag_bytes[8] == 10710,
flag_bytes[6] * flag_bytes[10] == 12051,
flag_bytes[7] + flag_bytes[11] == 172,
flag_words[6] * flag_words[7] == 171593250,
flag_words[6] + flag_words[7] == 26219,
flag_words[8] * flag_words[9] == 376306868,
flag_words[8] + flag_words[9] == 40341
]
s.add(conds)
result=s.check()
while result==z3.sat:
m=s.model()
flag = ''.join(chr(m.eval(x).as_long()) for x in flag_bytes)
print(flag)
# exclude the previous result by 'AND' a 'NOT'
# 'NOT AND' is implemented by 'OR NEQ'
extra=[var()!=m[var] for var in m]
s.add(z3.Or(extra))
result=s.check()
#125hfggtisu8219549ad
#125hfggtisu82195ad49
#125hfggtisu89521ad49
#125hfggtisu8952149ad
#...
babypy #
Cython 原生 DLL,test1.py 提示有三个导出函数 encrypt_AES_CBC, changtable 和 myBase64Encode
在 IDA 里定位这几个字符串,找在 .data 节的引用,就可以找到函数表
框架都是一样的,应该是做一些参数检查,然后再调用真正的函数
很容易就可以找到真正的函数,因为三个函数只有这一处是不一样的
先看最简单的 changtable,实际上就是 s=s[31:64]+s[:31]
在 .rdata 节可以找到 base64 的初始码表和两个 bytes 常量,32 位的那个显然是 key,16 位的是 iv
from base64 import b64decode as b64d, b64encode as b64e
from Crypto.Cipher import AES
b64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
change = lambda x: x[31:64] + x[0:31]
new_b64_table = change(b64_table)
encoded = 'hFHKBrfErYqSzpLZ/WD35J9+xNEt0uEZs/cNJeT7onH='
trans = str.maketrans(new_b64_table, b64_table)
encoded = encoded.translate(trans)
ct = b64d(encoded)
print(ct)
iv = b'\x00\x01\\{\x8c\xaa\xdf\xbc\xe9,OF\xa4\xda\x1e\xc6'
key = b'GU,\x8b\x0cSI\xe1\x92\x08\x97\xa3\xd0\xa1X-\xc3\x11\xd6U\xef\xca\xf9#g\x7f\xae\xd3x\xe2n\xd5'
aes = AES.new(key, AES.MODE_CBC, iv=iv)
pt = aes.decrypt(ct)
print(pt)
#flag{pYth0n_1ts_S0_CO0L}
square #
脱一个梆梆加固壳
WIP