[2019红帽杯]xx
步骤
-
PE文件,查壳儿,64位程序,无壳儿,c++写的
-
64位ida载入,用FindCrypt工具发现程序里存在TEA系列加密,然后根据题目xx,这题应该是xxTEA
-
main函数太长,分开看
这边有个坑,一开始没注意到,折腾了好久。用户读入的数据存储的也叫Code,给v6赋值的参数也叫code,这边需要区分一下。为了区分,用户输入的我用大写C,另一个是小写c
-
梳理一下程序流:
首先判断输入的字符串的每个字符是否包含在"qwertyuiopasdfghjklzxcvbnm1234567890"中
之后取出输入字符串的前4位字符,即"flag",扩展为16位,作为xxtea加密的秘钥key
接着将输入的字符串使用key加密,加密后的字符保存在字符数组v18,共24位字符
然后打乱v18数组,保存到v19数组中
最后将24位字符,每3位为一组,每一组迭代异或,得到新的加密字符串
我们只要让新的加密字符串与已经存在的字符串相同即获得胜利
理清楚了,开始逆运算吧
有xxtea库的可以直接使用
exp来源
import xxtea
text = "1111111111111111111"
key = "flag"
#encrypt_data = xxtea.encrypt(text, key)
encrypt_data = 'bca5ce40f4b2b2e7a9129d12ae10c85b3dd7061ddc70f8dc'.decode('hex')
decrypt_data = xxtea.decrypt(encrypt_data, key)
print decrypt_data
我的xxtea不懂为什么装了不好用,我就换了个方法
exp来源
# encoding: utf-8
import struct
_DELTA = 0x9E3779B9
def _long2str(v, w):
n = (len(v) - 1) << 2
if w:
m = v[-1]
if (m < n - 3) or (m > n): return ''
n = m
s = struct.pack('<%iL' % len(v), *v)
return s[0:n] if w else s
def _str2long(s, w):
n = len(s)
m = (4 - (n & 3) & 3) + n
s = s.ljust(m, "\0")
v = list(struct.unpack('<%iL' % (m >> 2), s))
if w: v.append(n)
return v
def encrypt(str, key):
if str == '': return str
v = _str2long(str, True)
k = _str2long(key.ljust(16, "\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
sum = 0
q = 6 + 52 // (n + 1)
while q > 0:
sum = (sum + _DELTA) & 0xffffffff
e = sum >> 2 & 3
for p in xrange(n):
y = v[p + 1]
v[p] = (v[p] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
z = v[p]
y = v[0]
v[n] = (v[n] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[n & 3 ^ e] ^ z))) & 0xffffffff
z = v[n]
q -= 1
return _long2str(v, False)
def decrypt(str, key):
if str == '': return str
v = _str2long(str, False)
k = _str2long(key.ljust(16, "\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
q = 6 + 52 // (n + 1)
sum = (q * _DELTA) & 0xffffffff
while (sum != 0):
e = sum >> 2 & 3
for p in xrange(n, 0, -1):
z = v[p - 1]
v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
y = v[p]
z = v[n]
v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
y = v[0]
sum = (sum - _DELTA) & 0xffffffff
return _long2str(v, True)
def xor(x ,y):
return ord(x) ^ ord(y)
# 转换为16进制
arr = 'CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA'.decode('hex')
dec = ''
# 因为加密时是正向加密,会用到加密之后的字符,因此解密需要逆向解密
for i in range(7,-1,-1):
res = ''
# 每3个为一组
for j in range(3):
temp = ord(arr[i*3+j])
# 需要异或的值,例如第i组的值就是,arr[i*3+j]^(arr[n] for n in range(i))
for m in range(i):
temp ^= ord(arr[m])
res += chr(temp)
dec = res + dec
# 原来的v18到v19数组是被打乱排序了的
num = [2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
enc = [0] * 24
# key需要是16位
key = 'flag'+'\x00'*12
for i in range(24):
enc[num[i]] = dec[i]
dec2 = ''.join(enc)
dec3 = decrypt(dec2, key)
print dec3