LCTF2018 wp by whitzard

做的基本都是rev/misc,欢迎交流qq:859630472

Reverse

拿去签到吧朋友

放出来的第一道reverse,说是签到This is the simplest reverse problem,实际上却比较恶心…
首先题目有反调sub_401323,把ida等字符串替换掉即可。
然后可以看到sub_401451sub_401E79做了异或,不过异或完了函数也还是不对,于是先看main函数逻辑:

scanf("%s");
  if ( strlen(&input) != 36 )
  {
    print("error\n", (unsigned int)&input);
    exit(0);
  }
  root = 0;
  for ( i = 0; i < strlen(&input); ++i )
  {
    root = (int *)tree_insert((node *)root, flag_64[i - 64]);
    ++v10;
  }
  idx = 0;
  pre_order_traversal((node *)root);
  Size = strlen(Str);
  memset(Str, 0, Size);
  check1(travser_val);
  idx = 0;
  post_order_traversal((node *)root);
  check2();
  print("congratulation.\n", v5);

其中几个函数都是二叉树的操作,先把input插到二叉查找树里,然后做一个先序遍历,对得到的序列做一个check,然后再做一个后序遍历,再做另一个check,树节点最好标个结构体:

00000000 node            struc ; (sizeof=0x10, mappedto_14)
00000000 val             dd ?
00000004 num             dd ?
00000008 left            dd ?
0000000C right           dd ?
00000010 node            ends

check1里用了一种加密算法加密了先序遍历序列sub_4018f0,然后做了一个矩阵乘法sub_40195a

可以先把矩阵乘法还原,求个逆,乘回去即可,得到的就是加密后的序列:

119.0000   175.0000   221.0000   238.0000    92.0000   171.0000
203.0000   163.0000    98.0000    99.0000    92.0000    93.0000
147.0000    24.0000    11.0000   251.0000   201.0000    23.0000
70.0000    71.0000   185.0000    29.0000   118.0000   142.0000
182.0000   227.0000   245.0000   199.0000   172.0000   100.0000
52.0000   121.0000     8.0000   142.0000    69.0000   249.0000

(注意最终比较函数sub_40142a里还有最后四个byte)

这个加密算法是DES,但是比赛时没有搜到,于是自己写的解密,过程非常痛苦:(扩展后的密钥key.bin是从内存dump出来的)

m=[119, 175, 221, 238, 92, 171,
203, 163, 98, 99, 92, 93,
147, 24, 11, 251, 201, 23,
70, 71, 185, 29, 118, 142,
182, 227, 245, 199, 172, 100,
52, 121, 8, 142, 69, 249,
0x73,0x3c,0xf5,0x7c]

key=map(ord,open('key.bin','rb').read() )

def itob(i):
    return bin(i).replace('0b','').rjust(8, '0')

fin_bits = map(lambda x:ord(x)-ord('0'), ''.join(map(itob,m)) )

def switch_rev(bits, swt, len):
    ret = [0]*len
    for i in range(len):
        if ret[swt[i]-1 ] != 0 and ret[swt[i]-1 ] != bits[i]:
            print 'err'+i
        ret[swt[i]-1 ] = bits[i]
    return ret

def switch(bits, swt, len):
    ret = [0]*len
    for i in range(len):
        ret[i] = bits[swt[i]-1]
    return ret

def bit_xor(a, b, len):
    ret = [0]*len
    for i in range(len):
        if a[i] != b[i]:
            ret[i] = 1
    return ret

def gen_from_map(s):
    ret=''
    for j in range(8):
        l = s[j*6 : (j+1)*6]
        idx = 32*l[0]+16*l[5]+64*j+8*l[1]+4*l[2]+2*l[3]+l[4]
        ret += bin(big_map[idx]).replace('0b','').rjust(4, '0')
    return map(lambda x:ord(x)-ord('0'),ret)

def e(a, i):
    key_bits = key[i*48 : (i+1)*48]
    b = switch(a, swt_key0, 48)
    b = bit_xor(b, key_bits, 48)
    b = gen_from_map(b)
    b = switch(b, swt_key1, 32)
    return b

swt_1=[0x28, 0x08, 0x30, 0x10, 0x38, 0x18, 0x40, 0x20, 0x27, 0x07, 0x2F, 0x0F, 0x37, 0x17, 0x3F, 0x1F, 0x26, 0x06, 0x2E, 0x0E, 0x36, 0x16, 0x3E, 0x1E, 0x25, 0x05, 0x2D, 0x0D, 0x35, 0x15, 0x3D, 0x1D, 0x24, 0x04, 0x2C, 0x0C, 0x34, 0x14, 0x3C, 0x1C, 0x23, 0x03, 0x2B, 0x0B, 0x33, 0x13, 0x3B, 0x1B, 0x22, 0x02, 0x2A, 0x0A, 0x32, 0x12, 0x3A, 0x1A, 0x21, 0x01, 0x29, 0x09, 0x31, 0x11, 0x39, 0x19]
swt_0=[0x3A, 0x32, 0x2A, 0x22, 0x1A, 0x12, 0x0A, 0x02, 0x3C, 0x34, 0x2C, 0x24, 0x1C, 0x14, 0x0C, 0x04, 0x3E, 0x36, 0x2E, 0x26, 0x1E, 0x16, 0x0E, 0x06, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x39, 0x31, 0x29, 0x21, 0x19, 0x11, 0x09, 0x01, 0x3B, 0x33, 0x2B, 0x23, 0x1B, 0x13, 0x0B, 0x03, 0x3D, 0x35, 0x2D, 0x25, 0x1D, 0x15, 0x0D, 0x05, 0x3F, 0x37, 0x2F, 0x27, 0x1F, 0x17, 0x0F, 0x07]
swt_key0=[0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x01]
swt_key1=[0x10, 0x07, 0x14, 0x15, 0x1D, 0x0C, 0x1C, 0x11, 0x01, 0x0F, 0x17, 0x1A, 0x05, 0x12, 0x1F, 0x0A, 0x02, 0x08, 0x18, 0x0E, 0x20, 0x1B, 0x03, 0x09, 0x13, 0x0D, 0x1E, 0x06, 0x16, 0x0B, 0x04, 0x19]
big_map=[0x0E, 0x04, 0x0D, 0x01, 0x02, 0x0F, 0x0B, 0x08, 0x03, 0x0A, 0x06, 0x0C, 0x05, 0x09, 0x00, 0x07, 0x00, 0x0F, 0x07, 0x04, 0x0E, 0x02, 0x0D, 0x01, 0x0A, 0x06, 0x0C, 0x0B, 0x09, 0x05, 0x03, 0x08, 0x04, 0x01, 0x0E, 0x08, 0x0D, 0x06, 0x02, 0x0B, 0x0F, 0x0C, 0x09, 0x07, 0x03, 0x0A, 0x05, 0x00, 0x0F, 0x0C, 0x08, 0x02, 0x04, 0x09, 0x01, 0x07, 0x05, 0x0B, 0x03, 0x0E, 0x0A, 0x00, 0x06, 0x0D, 0x0F, 0x01, 0x08, 0x0E, 0x06, 0x0B, 0x03, 0x04, 0x09, 0x07, 0x02, 0x0D, 0x0C, 0x00, 0x05, 0x0A, 0x03, 0x0D, 0x04, 0x07, 0x0F, 0x02, 0x08, 0x0E, 0x0C, 0x00, 0x01, 0x0A, 0x06, 0x09, 0x0B, 0x05, 0x00, 0x0E, 0x07, 0x0B, 0x0A, 0x04, 0x0D, 0x01, 0x05, 0x08, 0x0C, 0x06, 0x09, 0x03, 0x02, 0x0F, 0x0D, 0x08, 0x0A, 0x01, 0x03, 0x0F, 0x04, 0x02, 0x0B, 0x06, 0x07, 0x0C, 0x00, 0x05, 0x0E, 0x09, 0x0A, 0x00, 0x09, 0x0E, 0x06, 0x03, 0x0F, 0x05, 0x01, 0x0D, 0x0C, 0x07, 0x0B, 0x04, 0x02, 0x08, 0x0D, 0x07, 0x00, 0x09, 0x03, 0x04, 0x06, 0x0A, 0x02, 0x08, 0x05, 0x0E, 0x0C, 0x0B, 0x0F, 0x01, 0x0D, 0x06, 0x04, 0x09, 0x08, 0x0F, 0x03, 0x00, 0x0B, 0x01, 0x02, 0x0C, 0x05, 0x0A, 0x0E, 0x07, 0x01, 0x0A, 0x0D, 0x00, 0x06, 0x09, 0x08, 0x07, 0x04, 0x0F, 0x0E, 0x03, 0x0B, 0x05, 0x02, 0x0C, 0x07, 0x0D, 0x0E, 0x03, 0x00, 0x06, 0x09, 0x0A, 0x01, 0x02, 0x08, 0x05, 0x0B, 0x0C, 0x04, 0x0F, 0x0D, 0x08, 0x0B, 0x05, 0x06, 0x0F, 0x00, 0x03, 0x04, 0x07, 0x02, 0x0C, 0x01, 0x0A, 0x0E, 0x09, 0x0A, 0x06, 0x09, 0x00, 0x0C, 0x0B, 0x07, 0x0D, 0x0F, 0x01, 0x03, 0x0E, 0x05, 0x02, 0x08, 0x04, 0x03, 0x0F, 0x00, 0x06, 0x0A, 0x01, 0x0D, 0x08, 0x09, 0x04, 0x05, 0x0B, 0x0C, 0x07, 0x02, 0x0E, 0x02, 0x0C, 0x04, 0x01, 0x07, 0x0A, 0x0B, 0x06, 0x08, 0x05, 0x03, 0x0F, 0x0D, 0x00, 0x0E, 0x09, 0x0E, 0x0B, 0x02, 0x0C, 0x04, 0x07, 0x0D, 0x01, 0x05, 0x00, 0x0F, 0x0A, 0x03, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01, 0x0B, 0x0A, 0x0D, 0x07, 0x08, 0x0F, 0x09, 0x0C, 0x05, 0x06, 0x03, 0x00, 0x0E, 0x0B, 0x08, 0x0C, 0x07, 0x01, 0x0E, 0x02, 0x0D, 0x06, 0x0F, 0x00, 0x09, 0x0A, 0x04, 0x05, 0x03, 0x0C, 0x01, 0x0A, 0x0F, 0x09, 0x02, 0x06, 0x08, 0x00, 0x0D, 0x03, 0x04, 0x0E, 0x07, 0x05, 0x0B, 0x0A, 0x0F, 0x04, 0x02, 0x07, 0x0C, 0x09, 0x05, 0x06, 0x01, 0x0D, 0x0E, 0x00, 0x0B, 0x03, 0x08, 0x09, 0x0E, 0x0F, 0x05, 0x02, 0x08, 0x0C, 0x03, 0x07, 0x00, 0x04, 0x0A, 0x01, 0x0D, 0x0B, 0x06, 0x04, 0x03, 0x02, 0x0C, 0x09, 0x05, 0x0F, 0x0A, 0x0B, 0x0E, 0x01, 0x07, 0x06, 0x00, 0x08, 0x0D, 0x04, 0x0B, 0x02, 0x0E, 0x0F, 0x00, 0x08, 0x0D, 0x03, 0x0C, 0x09, 0x07, 0x05, 0x0A, 0x06, 0x01, 0x0D, 0x00, 0x0B, 0x07, 0x04, 0x09, 0x01, 0x0A, 0x0E, 0x03, 0x05, 0x0C, 0x02, 0x0F, 0x08, 0x06, 0x01, 0x04, 0x0B, 0x0D, 0x0C, 0x03, 0x07, 0x0E, 0x0A, 0x0F, 0x06, 0x08, 0x00, 0x05, 0x09, 0x02, 0x06, 0x0B, 0x0D, 0x08, 0x01, 0x04, 0x0A, 0x07, 0x09, 0x05, 0x00, 0x0F, 0x0E, 0x02, 0x03, 0x0C, 0x0D, 0x02, 0x08, 0x04, 0x06, 0x0F, 0x0B, 0x01, 0x0A, 0x09, 0x03, 0x0E, 0x05, 0x00, 0x0C, 0x07, 0x01, 0x0F, 0x0D, 0x08, 0x0A, 0x03, 0x07, 0x04, 0x0C, 0x05, 0x06, 0x0B, 0x00, 0x0E, 0x09, 0x02, 0x07, 0x0B, 0x04, 0x01, 0x09, 0x0C, 0x0E, 0x02, 0x00, 0x06, 0x0A, 0x0D, 0x0F, 0x03, 0x05, 0x08, 0x02, 0x01, 0x0E, 0x07, 0x04, 0x0A, 0x08, 0x0D, 0x0F, 0x0C, 0x09, 0x00, 0x03, 0x05, 0x06, 0x0B]

def dec_8bytes(x):
    x=switch_rev(x, swt_1, 64)
    a = x[:32]
    b = x[32:]
    a = bit_xor(a, e(b, 15), 32)
    j=14
    while j >= 0:
        t = a
        a = bit_xor(b, e(a, j), 32)
        b = t
        j-=1
    x = switch_rev(a+b, swt_0, 64)
    return x

out=''
for i in range(0, 36, 8):
    x = fin_bits[i*8:(i+8)*8]
    res = dec_8bytes(x)
    out+=hex(int(''.join(map(str,res)),2))[2:-1].decode('hex')
l=[0,1,14,12,17,18,19,27,28,2,15,20,31,29,30,16,13,5]
flag = ''
for i in l:
    flag+=out[i]

# second part
l=[19,18,5,7,17,1,0,20,6,29,28,27,15,16,4,3,2,32]
x=[0x7C, 0x81, 0x61, 0x99, 0x67, 0x9B, 0x14, 0xEA, 0x68, 0x87, 0x10, 0xEC, 0x16, 0xF9, 0x07, 0xF2, 0x0F, 0xF3, 0x03, 0xF4, 0x33, 0xCF, 0x27, 0xC6, 0x26, 0xC3, 0x3D, 0xD0, 0x2C, 0xD2, 0x23, 0xDE, 0x28, 0xD1, 0x01, 0xE6]
for i in range(len(x)):
    for j in[0,2,4,6]:
        x[i] ^= 1 << (j + i % 2)
s = ''.join

       
       
       

    

Hacking more

...