Evr_Q

0x00 写在前面

这题一开始是准备TLS+SMC+反调试的,发现放在第一题有些不太合适,就把SMC的调用部分删掉了。
 (其实留下了彩蛋,smc的实现我没有删XD)

  设计思路:
  用TLS检测工具进程和调试器,进入主函数后先检测用户名,通过后检测StartCode(即flag),最后输入’Y’确认CM。

  部分细节:

  • Win10的TLS在vs17上有点小Bug,只能在Debug模式下跑起来,于是没有选择Release版本,如果给大家带来困扰这里十分抱歉。
  • 用户名注册存在多解,原因是我把进位值舍去了(输入’I’也能通过username验证哦)
  • StartCode部分先验证长度为35
    Step1: 全体 xor 0x76
    Step2: [7:14]每个字节先异或0xAD, 再将0b10101010位与0b01010101位互换
    Step3: [14:21]每个字节先异或0xBE, 再将0b11001100位与0b00110011位互换
    Step4: [21:28]每个字节先异或0xAD, 再将0b11110000位于0b00001111位互换
  • Step2~4加密前先调用ntdll!NtQueryInformationProcess, 各检查1种标志(7, 30,31)
  • 比较简单的做法直接用ida看了,cuz没有造成任何静态反编译的难度

0x01 Wp

2017HCTF

    import random
    import os
    import hashlib

    enc_flag = [30, 21, 2, 16, 13, 72, 72, 111, 221, 221, 72, 100, 99, 215, 46, 44, 254, 106, 109, 42, 242, 111, 154, 77, 139, 75, 30, 30, 14, 14, 14, 14, 14, 14, 11]
    dec_flag = [0] * len(enc_flag)

    #/////////////////////////////////////////////////
    def dec0_f(dec_t, enc_t, num):
        for i in range(num):
            dec_t[i] = chr(enc_t[i] ^ 0x76)
        return dec_t
    #/////////////////////////////////////////////////
    def dec1_f(dec_t, enc_t, num):
        for i in range(num):
            v1 = (enc_t[i] & 0x55) << 1
            v2 = (enc_t[i] >> 1) & 0x55
            enc_t[i] = v1 | v2
            dec_t[i] = enc_t[i] ^ 0xAD
        return dec_t
    #/////////////////////////////////////////////////
    def dec2_f(dec_t, enc_t, num):
        for i in range(num):
            v1 = (enc_t[i] & 0x33) << 2
            v2 = (enc_t[i] >> 2) & 0x33
            enc_t[i] = v1 | v2
            dec_t[i] = enc_t[i] ^ 0xBE
        return dec_t
    #/////////////////////////////////////////////////
    def dec3_f(dec_t, enc_t, num):
        for i in range(num):
            v1 = (enc_t[i] & 0xF) << 4
            v2 = (enc_t[i] >> 4) & 0xF
            enc_t[i] = v1 | v2
            dec_t[i] = enc_t[i] ^ 0xEF
        return dec_t
    #/////////////////////////////////////////////////
    def dec_f(dec_flag, enc_flag):
        for i in range(len(enc_flag)):
            dec_flag[i] = enc_flag[i]
        dec_flag[21:28] = dec3_f(dec_flag[21:28], enc_flag[21:28], 7)
        dec_flag[14:21] = dec2_f(dec_flag[14:21], enc_flag[14:21], 7)
        dec_flag[7:14] = dec1_f(dec_flag[7:14], enc_flag[7:14], 7)
        dec_flag = dec0_f(dec_flag, dec_flag, 35)
    #/////////////////////////////////////////////////

    dec_f(dec_flag, enc_flag)

    print ''.join(dec_flag)

flag:

hctf{>>D55_CH0CK3R_B0o0M!-xxxxxxxx}

ez_crackme

考察对简单解释器的逆向能力。

加密解密过程

box=[]
for i in range(32):
    x=(x+51)%32
    box.append(x)

先用如上方式初始化一个box。

用这个box将输入的明文进行乱序。

head = (out[0]&0xe0)>>5
    for i in range(31):
        out[i] = ((out[i]&0x1f)<<3)+((out[i+1]&0xe0)>>5)
    out[31] = ((out[31]&0x1f)<<3) + head

然后用如上方式,将乱序后的结果进行整体循环左移3位。

key = 'deadbeef'.decode('hex')
    for i in range(32):
        out2.append(out[i]^((ord(key[i%4])+i)&0xff))

然后利用key和下标i对左移后的结果做异或即可。

完整python加密解密脚本:

key = 'deadbeef'.decode('hex')

def encrypt(flag):
    out=[]
    out2=[]
    x=0#gen box
    box=[]
    for i in range(32):
        x=(x+51)%32
        box.append(x)
    for i in range(32):
        out.append(ord(flag[box[i]]))
    head = (out[0]&0xe0)>>5
    for i in range(31):
        out[i] = ((out[i]&0x1f)<<3)+((out[i+1]&0xe0)>>5)
    out[31] = ((out[31]&0x1f)<<3) + head
    for i in range(32):
        out2.append(out[i]^((ord(key[i%4])+i)&0xff))
    return  out2

def decrypt(enc_list):
    out=[]
    out2=[0]*32
    x=0#gen box
    box=[]
    for i in range(32):
        x=(x+51)%32
        box.append(x)
    for i in range(32):
        out.append(enc_list[i]^(ord(key[i%4])+i))

    tail = out[31]&0x7
    for i in reversed(range(1,32)):
        out[i] = ((out[i]&0xf8)>>3)+((out[i-1]&0x7)<<5)
    out[0] = ((out[0]&0xf8)>>3)+(tail<<5)
    for i in range(32):
        out2[box[i]] = out[i]
    return  ''.join(map(chr,out2))

#### 解释器分析

//register
#define _eax 0
#define _ebx 1
#define _ebx2 2
#define _ecx 3
#define _edx 4
#define _esp 5
#define _lf 6
#define _neq 7
#define _t_intp 8
#define _t_chp 9
#define _t_int 10
#define _flag 11
#define _enc 12
#define _key 13
//opcode
#define _mov (0<<1)
#define _mov32 (1<<1)
#define _lea_ch (2<<1)
#define _lea_int (3<<1)
#define _ldr_int (4<<1)
#define _ldr_ch (5<<1)
#define _add (6<<1)
#define _add_pint (7<<1)
#define _add_pch (8<<1)
#define _my_xor (9<<1)
#define _mod (10<<1)
#define _my_or (11<<1)
#define _my_and (12<<1)
#define _push (13<<1)
#define _pop (14<<1)
#define _shr (15<<1)
#define _shl (16<<1)
#define _ror (17<<1)
#define _cmpl (18<<1)
#define _cmpeq (19<<1)
#define loop (20<<1)
#define code_end (21<<1)
//type
#define rn 0 
#define rr 1

定义了一些寄存器以及变量,解释器指令,以及指令后面的变量种类。一个完整的指令由高7位的类型和低1位的变量类型组成。

rr表示op reg,reg,rn表示op reg,num。

用宏写的解释代码

char code[] = {
        _lea_ch | rr,_ebx, _flag,
        _my_xor | rr,_ecx, _ecx,
        _my_xor | rr,_eax,_eax,
        _my_xor | rr,_edx,_edx,

        loop,
        _add | rn,_eax, 51,
        _mod | rn,_eax, 32,
        _lea_ch | rr,_t_chp, _ebx,
        _add_pch | rr,_t_chp,_eax,
        _ldr_ch | rr,_t_int,_t_chp,
        _mov | rr,_edx,_t_int,
        _push | rr,_esp,_edx,
        _add | rn,_ecx, 1,
        _cmpl | rn, _ecx, 32,
        loop,

        _my_xor | rr,_eax,_eax,
        _lea_int | rr,_t_intp,_esp,
        _add_pint | rn,_t_intp, -32,
        _lea_int | rr,_ebx2,_t_intp,
        _ldr_int | rr,_t_int, _ebx2,
        _mov | rr,_eax,_t_int,
        _my_and | rn,_eax, 0xe0,
        _shr | rn,_eax, 5,
        _mov | rr,_edx,_eax,
        _my_xor | rr,_ecx, _ecx,
        loop,
        _ldr_int | rr,_t_int, _ebx2,
        _mov | rr,_eax,_t_int,
        _my_and | rn,_eax, 0x1f,
        _shl | rn,_eax, 3,
        _push | rr,_esp,_eax,
        _lea_int | rr,_t_intp,_esp,
        _add_pint | rn,_t_intp, -32,
        _lea_int | rr,_ebx2,_t_intp,
        _ldr_int | rr,_t_int, _ebx2,
        _mov | rr,_eax,_t_int,
        _my_and | rn,_eax, 0xe0,
        _shr | rn,_eax, 5,
        _pop | rr,_esp,_t_int,
        _add | rr,_t_int,_eax,
        _push | rr,_esp,_t_int,
        _add | rn,_ecx, 1,
        _cmpl | rn, _ecx, 31,
        loop,

        _ldr_int | rr,_t_int, _ebx2,
        _mov | rr,_eax,_t_int,
        _my_and | rn,_eax, 0x1f,
        _shl | rn,_eax, 3,
        _add | rr,_eax,_edx,
        _push | rr,_esp,_eax,

        _my_xor | rr,_ecx, _ecx,
        _mov32 | rr,_edx, _key,
        loop,
        _lea_int | rr,_t_intp,_esp,
        _add_pint | rn,_t_intp, -32,
        _lea_int | rr,_ebx2,_t_intp,
        _ldr_int | rr,_t_int, _ebx2,
        _mov | rr,_eax,_t_int,
        _push | rr,_esp,_eax,
        _mov | rr,_eax,_edx,
        _add | rr,_eax, _ecx,
        _pop | rr,_esp,_t_int,
        _my_xor | rr,_t_int,_eax,
        _push | rr,_esp,_t_int,
        _ror | rn,_edx, 8,
        _add | rn,_ecx, 1,
        _cmpl | rn, _ecx, 32,
        loop,

        _my_xor | rr,_ecx, _ecx,
        _my_xor | rr,_edx,_edx,
        _lea_ch | rr,_ebx,_enc,
        loop,
        _lea_ch | rr,_t_chp, _ebx,
        _add_pch | rr,_t_chp, _ecx,
        _ldr_ch | rr,_t_int,_t_chp,
        _mov | rr,_eax,_t_int,
        _push | rr,_esp,_eax,
        _lea_int | rr,_t_intp,_esp,
        _add_pint | rn,_t_intp, -33,
        _ldr_int | rr,_t_int,_t_intp,
        _pop | rr,_esp,_eax,
        _push | rr,_esp,_eax,
        _cmpeq | rr,_eax,_t_int,
        _my_or | rr,_edx, _neq,
        _add | rn,_ecx, 1,
        _cmpl | rn, _ecx, 32,
        loop,

        code_end
    };

其中loop的实现是用记录ip的方式来实现的。

完整的程序代码见github。

本文章首发在 网安wangan.com 网站上。

上一篇 下一篇
讨论数量: 0
只看当前版本


暂无话题~