FindFlag
FindFlag
初步运行程序,程序要求用户输入flag,经过加密之后与程序内部的密文进行比较。程序并未设置flag长度,我一开始以为必须32位,我也不记得从哪看出来的32位,掉坑里了。
防护机制
程序存在动态调试的检测,如果检测进程是在动态调试,会退出程序。
但是,用于 比对的密文从静态分析中只能获取前一段,无法全部获取,这也要求我们使用动态调试。
调试绕过方式
使用OD打开程序,找到程序进入调试程序的地方,修改返回值,使其不能直接结束进程将EAX的值修改为0。
修改跳转地址0x0040131F为0x0040131A,使其直接进入主程序。
进入主程序。
加密算法分析
加密算法分为两部分,第一部分的加密方式较为复杂,需要动态一步步分析;第二部分是将第一步加密的结果与字符串Limpid-Dream
进行异或。
重现加密算法:
def encry(flag_test):
i = 0
sd=''
while True:
if i >= len(flag_test):
break
else:
s1 = ord(flag_test[i]) >> 2
sd += table[s1]
s2 = (ord(flag_test[i]) & 0x03) << 4
# print hex(s2)
if i+1 >= len(flag_test):
break
else:
s3 = (ord(flag_test[i+1]) >> 4) | s2
sd+= table[s3]
s4 = (ord(flag_test[i+1]) & 0x0f) << 2
# print hex(s4)
if i+2 >= len(flag_test):
sd += table[s4]
sd+='='
else:
s6 = ((ord(flag_test[i+2]) >> 6) | s4)
sd+= table[s6]
s7 = (ord(flag_test[i+2]) & 0x3f)
sd+= table[s7]
i = i+3
return sd
总的来说就是,将代加密的字符串分为四个一组,进行加密。table是0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/
。
加密结束后,将加密后的数据逆向的与Limpid-Dream
,然后再与栈中的密文想比较。
解密脚本
table = '0123456789QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm+/'
enc = '!K&!:'
v33 = 'Limpid-Dream'
v1 = 0
table2 = 'HefBHzofEMEjRPGzT3qdEP8hR3AlRhVcE34gEhUkRrj='
flag_test = 'flag{12345678901234567890123456}'
enc = [0x3a, 0x21, 0x4b, 0x26, 0x21, 0x0a, 0x1d, 0x2b,
0x18, 0x3D, 0x20, 0x06, 0x26, 0x14, 0x6c, 0x02,
0x2e, 0x3e, 0x07,0x13, 0x1e, 0x08, 0x33, 0x27,
0x25, 0x14, 0x78, 0x1e, 0x3d, 0x43, 0x38, 0x19
,0x0b, 0x29, 0x28, 0x14, 0x20, 0x23, 0x47, 0x07, 0x2c,
0x18, 0x2c, 0x11, 0x09, 0x05, 0x59, 0x0e, 0x37,
0x00, 0x7f,0x26, 0x3d, 0x20, 0x54, 0x04, 0x4c]
def encry(flag_test):
i = 0
sd=''
while True:
if i >= len(flag_test):
break
else:
s1 = ord(flag_test[i]) >> 2
sd += table[s1]
s2 = (ord(flag_test[i]) & 0x03) << 4
# print hex(s2)
if i+1 >= len(flag_test):
break
else:
s3 = (ord(flag_test[i+1]) >> 4) | s2
sd+= table[s3]
s4 = (ord(flag_test[i+1]) & 0x0f) << 2
# print hex(s4)
if i+2 >= len(flag_test):
sd += table[s4]
sd+='='
else:
s6 = ((ord(flag_test[i+2]) >> 6) | s4)
sd+= table[s6]
s7 = (ord(flag_test[i+2]) & 0x3f)
sd+= table[s7]
i = i+3
return sd
def encry2(flag_test2):
sd = ''
s1 = ord(flag_test2[0]) >> 2
sd += table[s1]
s2 = (ord(flag_test2[0]) & 0x03) << 4
s3 = (ord(flag_test2[1]) >> 4) | s2
sd+= table[s3]
s4 = (ord(flag_test2[1]) & 0x0f) << 2
if len(flag_test2)<=2:
sd += table[s4]
sd+='='
else:
s6 = ((ord(flag_test2[2]) >> 6) | s4)
sd+= table[s6]
s7 = (ord(flag_test2[2]) & 0x3f)
sd+= table[s7]
return sd
def test(str2):
for i in range(32,126):
for j in range(32, 126):
for k in range(32,126):
if encry2(chr(i)+chr(j)+chr(k))==str2:
return chr(i)+chr(j)+chr(k)
if __name__ == '__main__':
s2 = []
for i in range(0, len(enc)):
s2.append(v33[i % len(v33)])
s2 = s2[::-1]
t = ''
for i in range(len(enc)):
t += chr(ord(s2[i]) ^ enc[i])
print t
enc_flag = t
flag = ''
for g in range(4,len(enc_flag), 4):
flag += test(enc_flag[g-4:g])
print flag
print encry('flag{a959951b-76ca-4784-add7-93583251ca92}')
flag:flag{a959951b-76ca-4784-add7-93583251ca92}
点击下载程序