<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    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
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类