2019 红帽杯 Re WP

0x01 xx

测试文件:https://www.lanzous.com/i7dyqhc

1.准备

获取信息

  • 64位文件

2.IDA打开

使用Findcrypt脚本可以看到

结合文件名是xx,因此猜测代码用到了xxtea加密方法

3.流程总结

因此,总的流程为:

  1. 判断输入的字符串的每个字符是否包含在"qwertyuiopasdfghjklzxcvbnm1234567890"中
  2. 取输入字符串的前4位字符,即"flag",扩展为16位,作为xxtea加密的秘钥key
  3. 将输入的字符串使用key加密,加密后的字符保存在字符数组v18,共24位字符
  4. 打乱v18数组,保存到v19数组中
  5. 将24位字符,每3位为一组,每一组异或值(具体看代码),得到新的加密字符串
  6. 将新的加密字符串与已经存在的字符串比较,相同即获得胜利

因此,只需要逆向变换,就能得到flag

使用动态调试,可以获取到已经存在的字符串

enc = 'CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA'

4.脚本解密

Python带了xxtea的包,不过我用的时候,一直提示我“ValueError: Need a 16-byte key.”,用rjust或者'\x00'*16补足了16位也不管用。

所以用了另外一种方法,借用了下面xxtea的文章:

参考文章:https://blog.csdn.net/weixin_41474364/article/details/84314674 

# 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 dec4

5.get flag!

flag{CXX_and_++tea}

待更新... ...

猜你喜欢

转载自www.cnblogs.com/Mayfly-nymph/p/11869959.html