[CTF] HITCON CTF 2018 Write Up – EOP

這題是個逆向

要輸入正確的 FLAG


.text:0000000000005666                 call    objects_init
.text:000000000000566B                 lea     rsi, input
.text:0000000000005672                 lea     rdi, format     ; "%49s"
.text:0000000000005679                 mov     eax, 0
.text:000000000000567E                 call    _scanf
.text:0000000000005683                 lea     rdi, input      ; s
.text:000000000000568A                 call    _strlen
.text:000000000000568F                 cmp     rax, 48
.text:0000000000005693                 jz      short loc_569A
.text:0000000000005695                 call    putNo

.text:000000000000570B label_break_loop:                       ; CODE XREF: main+48↑j
.text:000000000000570B                 mov     edx, 48         ; n
.text:0000000000005710                 lea     rsi, flag_encrypted ; s2
.text:0000000000005717                 lea     rdi, input_encrypted ; s1
.text:000000000000571E                 call    _memcmp
.text:0000000000005723                 test    eax, eax
.text:0000000000005725                 jnz     short label_fail
.text:0000000000005727                 lea     rsi, input
.text:000000000000572E                 lea     rdi, aGreatHereSTheF ; "Great! Here's the flag: hitcon{%s}\n"
.text:0000000000005735                 mov     eax, 0
.text:000000000000573A                 call    _printf
.text:000000000000573F                 jmp     short label_reutrn_0
.text:0000000000005741 ; ---------------------------------------------------------------------------
.text:0000000000005741
.text:0000000000005741 label_fail:                             ; CODE XREF: main+C8↑j
.text:0000000000005741                 call    putNo

題目要輸入正確的 Flag,Flag 長度為 48,輸入的東西會經過加密後,透過 memcpy 判斷是不是跟加密的 Flag 一樣

這類型題目通常不是暴力碰撞,就是用了可逆的加密

所以先來找如何處理 input


char qword_2131A0[16];

char qword_2131B0[16];

int main() {
    char input[49];
    char input_encrypted[49];
   
    scanf("%49s", &input);
   
    if (strlen(input) != 48) {
       puts("No");
    } else {
        int i = 0;
        for (i = 0 ; i < 48; i++) { try { *(uin64_t*)qword_2131A0 = *(uin64_t*)(input + 16 * i); *(uin64_t*)(qword_2131A0 + 8) = *(uin64_t*)(input + 16 * i + 8); execute_object(0x1C); } catche(exception& ex) { if (ex->object_index != 65) {
                    execute_object(ex->object_index);
                } else {
                   *(uin64_t*)(input_encrypted + 16 * i) = *(uin64_t*)(qword_2131B0);
                   *(uin64_t*)(input_encrypted + 16 * i + 8) = *(uin64_t*)(qword_2131B0 + 8);
                }
            }
        }
    }
}

 

從 main 可以看到程式用了 try-catch 以及 throw exception 來控制流程

main 流程大概是長上面那樣,有一個 for-loop 處理 input,每次複製16個bytes到 0x0000002131A0

最後呼叫 execute_object ,如果有 exception 會看他存的一個內容是不是 65,非 65 的話繼續用這個 index 找物件的函數執行,是 65 的話把 qword_2131B0 的內容複製到 input_encrypted 中,繼續下一次的 Loop, 總共執行三次後離開



@func main
.text:00000000000056A1                 cmp     [rbp+i], 47
.text:00000000000056A5                 jg      short label_break_loop
.text:00000000000056A7                 mov     [rbp+function_index], 1Ch
.text:00000000000056AE                 mov     eax, [rbp-28]
.text:00000000000056B1                 movsxd  rdx, eax
.text:00000000000056B4                 lea     rax, input
.text:00000000000056BB                 add     rax, rdx
.text:00000000000056BE                 mov     rdx, [rax+8]
.text:00000000000056C2                 mov     rax, [rax]
.text:00000000000056C5                 mov     cs:ptr_0, rax
.text:00000000000056CC                 mov     cs:ptr_8, rdx
.text:00000000000056D3                 mov     eax, [rbp+function_index]
.text:00000000000056D6                 mov     edi, eax
.text:00000000000056D8                 call    execute_object

@func execute_object
.text:00000000000055C5                 mov     edx, [rbp+function_index]
.text:00000000000055C8                 movsxd  rdx, edx
.text:00000000000055CB                 lea     rcx, ds:0[rdx*8]
.text:00000000000055D3                 lea     rdx, objects    ; objects pointers
.text:00000000000055DA                 mov     rdx, [rcx+rdx]
.text:00000000000055DE                 mov     [rax], rdx
.text:00000000000055E1                 mov     edx, 0
.text:00000000000055E6                 lea     rsi, _ZTIP4Base ; `typeinfo for'Base *
.text:00000000000055ED                 mov     rdi, rax
.text:00000000000055F0                 call    ___cxa_throw
.text:00000000000055F5 ; ---------------------------------------------------------------------------
.text:00000000000055F5                 cmp     rdx, 1
.text:00000000000055F9                 jz      short loc_5603
.text:00000000000055FB                 mov     rdi, rax        ; struct _Unwind_Exception *
.text:00000000000055FE                 call    __Unwind_Resume
.text:0000000000005603 ; ---------------------------------------------------------------------------
.text:0000000000005603                 mov     rdi, rax
.text:0000000000005606                 call    ___cxa_begin_catch
.text:000000000000560B                 mov     [rbp+except], rax
.text:000000000000560F                 mov     rax, [rbp+except]
.text:0000000000005613                 mov     rax, [rax]
.text:0000000000005616                 mov     rax, [rax]
.text:0000000000005619                 mov     rdx, [rbp+except]
.text:000000000000561D                 mov     rdi, rdx
.text:0000000000005620 ;   try {
.text:0000000000005620                 call    rax             ; call function

在 main 中可以找到圖中 execute_object 這個 call

這邊一樣可以發現又是 try-catch throw new exception 的噁心流程

這個 calll 有一個參數 (rdi) 是第幾個物件, .text:00000000000055D3 這行會取得物件實體的位置,然後在 .text:0000000000005620 呼叫成員函數

所以從 main 開始看 .text:00000000000056A7 第一次會 execute_object(0x1c); 呼叫開始執行加密的


.bss:00000000002131E0 ; __int64 objects[]
.bss:00000000002131E0 objects         dq ?                    ; DATA XREF: objects_init+312↑w
.bss:00000000002131E0                                         ; execute_object+24↑o
.bss:00000000002131E8 qword_2131E8    dq ?                    ; DATA XREF: objects_init+702↑w
.bss:00000000002131F0 qword_2131F0    dq ?                    ; DATA XREF: objects_init+B7E↑w
.bss:00000000002131F8 qword_2131F8    dq ?                    ; DATA XREF: objects_init+32E↑w
.bss:0000000000213200 qword_213200    dq ?                    ; DATA XREF: objects_init+55E↑w
.bss:0000000000213208 qword_213208    dq ?                    ; DATA XREF: objects_init+A2E↑w
.bss:0000000000213210 qword_213210    dq ?                    ; DATA XREF: objects_init+2A2↑w
.bss:0000000000213218 qword_213218    dq ?                    ; DATA XREF: objects_init+73A↑w
.bss:0000000000213220 qword_213220    dq ?                    ; DATA XREF: objects_init+2F6↑w
.bss:0000000000213228 qword_213228    dq ?                    ; DATA XREF: objects_init+462↑w
.bss:0000000000213230 qword_213230    dq ?                    ; DATA XREF: objects_init+34A↑w
.bss:0000000000213238 qword_213238    dq ?                    ; DATA XREF: objects_init+A4A↑w
.bss:0000000000213240 qword_213240    dq ?                    ; DATA XREF: objects_init+9DA↑w
.bss:0000000000213248 qword_213248    dq ?                    ; DATA XREF: objects_init+7C6↑w
.bss:0000000000213250 qword_213250    dq ?                    ; DATA XREF: objects_init+3A↑w
.bss:0000000000213258 qword_213258    dq ?                    ; DATA XREF: objects_init+C0A↑w
.bss:0000000000213260 qword_213260    dq ?                    ; DATA XREF: objects_init+152↑w
.bss:0000000000213268 qword_213268    dq ?                    ; DATA XREF: objects_init+D22↑w
.bss:0000000000213270 qword_213270    dq ?                    ; DATA XREF: objects_init+AA↑w
.bss:0000000000213278 qword_213278    dq ?                    ; DATA XREF: objects_init+5CE↑w
.bss:0000000000213280 qword_213280    dq ?                    ; DATA XREF: objects_init+C42↑w
.bss:0000000000213288 qword_213288    dq ?                    ; DATA XREF: objects_init+836↑w
.bss:0000000000213290 qword_213290    dq ?                    ; DATA XREF: objects_init+2DA↑w
.bss:0000000000213298 qword_213298    dq ?                    ; DATA XREF: objects_init+216↑w
.bss:00000000002132A0 qword_2132A0    dq ?                    ; DATA XREF: objects_init+3F2↑w
.bss:00000000002132A8 qword_2132A8    dq ?                    ; DATA XREF: objects_init+57A↑w
.bss:00000000002132B0 qword_2132B0    dq ?                    ; DATA XREF: objects_init+72↑w
.bss:00000000002132B8 qword_2132B8    dq ?                    ; DATA XREF: objects_init+40E↑w
.bss:00000000002132C0 qword_2132C0    dq ?  ;第一次取得的物件位置  DATA XREF: objects_init+7FE↑w

接著我們繼續看, execute_object 會從物件地址的陣列中取出

第一次執行時是使用第 0x1c 個物件

00000000002131E0 + 0x1C * 8 = 0x00000000002132C0


.text:0000000000005018                 call    __Znwm          ; operator new(ulong)
.text:000000000000501D                 mov     rbx, rax
.text:0000000000005020                 mov     rdi, rbx
.text:0000000000005023                 call    sub_B8BC <------------------------
.text:0000000000005028                 mov     cs:qword_2132C0, rbx <-----------------------
.text:000000000000B8BC                 push    rbp
.text:000000000000B8BD                 mov     rbp, rsp
.text:000000000000B8C0                 sub     rsp, 10h
.text:000000000000B8C4                 mov     [rbp+var_8], rdi
.text:000000000000B8C8                 mov     rax, [rbp+var_8]
.text:000000000000B8CC                 mov     rdi, rax
.text:000000000000B8CF                 call    sub_ACD2
.text:000000000000B8D4                 lea     rdx, off_210EA0 <-------------------- asign vtable
.text:000000000000B8DB                 mov     rax, [rbp+var_8]
.text:000000000000B8DF                 mov     [rax], rdx
.text:000000000000B8E2                 nop
.text:000000000000B8E3                 leave
.text:000000000000B8E4                 retn
.data.rel.ro:0000000000210EA0 off_210EA0      dq offset sub_68C0      ; DATA XREF: sub_B8BC+18↑o

用 IDA 來看誰用到了這個位置,可以找到 0000000000005028

在這裡可以看到物件被new 出來後把位置塞進去了, syb_B8BC 想必就是他的建構子

從建構子就能找到 vtable 為 off_210EA0

最後找到成員函數 sub_68C0


.text:00000000000068C0                 push    rbp
.text:00000000000068C1                 mov     rbp, rsp
.text:00000000000068C4                 push    rbx
.text:00000000000068C5                 sub     rsp, 28h
.text:00000000000068C9                 mov     [rbp+var_28], rdi
.text:00000000000068CD                 mov     edi, 8
.text:00000000000068D2                 call    ___cxa_allocate_exception
.text:00000000000068D7                 mov     rbx, rax
.text:00000000000068DA                 mov     rdi, rbx
.text:00000000000068DD                 call    sub_57F8
.text:00000000000068E2                 mov     rax, cs:_ZNSt9exceptionD1Ev_ptr
.text:00000000000068E9                 mov     rdx, rax
.text:00000000000068EC                 lea     rsi, _ZTISt9exception ; `typeinfo for'std::exception
.text:00000000000068F3                 mov     rdi, rbx
.text:00000000000068F6 ;   try {
.text:00000000000068F6                 call    ___cxa_throw
.text:00000000000068F6 ;   } // starts at 68F6
.text:00000000000068FB ; ---------------------------------------------------------------------------
.text:00000000000068FB ;   catch(...) // owned by 68F6
.text:00000000000068FB                 mov     rdi, rax
.text:00000000000068FE                 call    ___cxa_begin_catch
.text:0000000000006903                 mov     [rbp+var_14], 0
.text:000000000000690A
.text:000000000000690A loc_690A:                               ; CODE XREF: sub_68C0+88↓j
.text:000000000000690A                 cmp     [rbp+var_14], 0Fh
.text:000000000000690E                 jg      short loc_694A
.text:0000000000006910                 mov     eax, [rbp+var_14]
.text:0000000000006913                 movsxd  rdx, eax
.text:0000000000006916                 lea     rax, ptr_0
.text:000000000000691D                 movzx   ecx, byte ptr [rdx+rax]
.text:0000000000006921                 mov     eax, [rbp+var_14]
.text:0000000000006924                 movsxd  rdx, eax
.text:0000000000006927                 lea     rax, ptr_out_0
.text:000000000000692E                 movzx   eax, byte ptr [rdx+rax]
.text:0000000000006932                 xor     ecx, eax
.text:0000000000006934                 mov     eax, [rbp+var_14]
.text:0000000000006937                 movsxd  rdx, eax
.text:000000000000693A                 lea     rax, ptr_0
.text:0000000000006941                 mov     [rdx+rax], cl
.text:0000000000006944                 add     [rbp+var_14], 1
.text:0000000000006948                 jmp     short loc_690A
.text:000000000000694A ; ---------------------------------------------------------------------------
.text:000000000000694A
.text:000000000000694A loc_694A:                               ; CODE XREF: sub_68C0+4E↑j
.text:000000000000694A                 mov     edi, 4
.text:000000000000694F                 call    ___cxa_allocate_exception
.text:0000000000006954                 mov     dword ptr [rax], 51
.text:000000000000695A                 mov     edx, 0
.text:000000000000695F                 lea     rsi, _ZTIi      ; `typeinfo for'int
.text:0000000000006966                 mov     rdi, rax
.text:0000000000006969 ;   try {
.text:0000000000006969                 call    ___cxa_throw
.text:0000000000006969 ;   } // starts at 6969
.text:000000000000696E ; ---------------------------------------------------------------------------
.text:000000000000696E ;   cleanup() // owned by 6969
.text:000000000000696E                 mov     rbx, rax
.text:0000000000006971                 call    ___cxa_end_catch
.text:0000000000006976                 mov     rax, rbx
.text:0000000000006979                 mov     rdi, rax        ; struct _Unwind_Exception *
.text:000000000000697C                 call    __Unwind_Resume
.text:000000000000697C ; } // starts at 68C0
.text:000000000000697C sub_68C0        endp

在這邊又是 try-catch 惡夢

真正的程式碼在 .text:0000000000006903 ~ .text:0000000000006948

也就是 call ___cxa_begin_catch 的下一行到 mov edi, 4 前一行結束

裡面放的是加密的程式

接著new 出一個物件把下一個用到的物件編號 51 放入 (.text:0000000000006954) ,最後 throw exception 出去

然後剛剛 new 物件的地方有一百多個物件

每一個物件都是同樣的結構

所以可能有非常多的函數在處理,手動追的話非常累

所以開始想有沒有可以取出程式碼的方法

稍微看了一下

函數的頭 .text:00000000000068C0 到 .text:00000000000068FE 的 offset 是 0x43

最後發現每一個用到的函數頭到需要的程式碼的偏移都是 0x43

所以就用 idapython 寫了一個工具來追蹤加密流程


import idautils
from ida_hexrays import init_hexrays_plugin, decompile
from ida_funcs import get_func
from ida_lines import tag_remove

out = open('eop.asm', 'w')
out2 = open('eop.c', 'w')

def decompile_func(ea):
  if not init_hexrays_plugin():
    return False

  f = get_func(ea)
  if f is None:
    return False

  cfunc = decompile(f);
  if cfunc is None:
    return False

  lines = []
  sv = cfunc.get_pseudocode();
  for sline in sv:
    line = tag_remove(sline.line);
    lines.append(line)
  return "\n".join(lines)

all = ''

i = 0x1C

while i != 65:
  
    object_pointer = 0x2131E0 + i * 8
    xrefs = idautils.XrefsTo(object_pointer, 0)

    for xx in xrefs:
        prev_call = PrevHead(xx.frm)
        prev_call_addr = idc.GetOperandValue(prev_call, 0)
        
        lea_edx = prev_call_addr + 0x18
        vtable = idc.GetOperandValue(lea_edx, 1)
        call_addr = Qword(vtable)
        
        print 'Begin function addr ('+hex(i)+')'+ hex(call_addr)
          
        real_code_addr = call_addr + 0x43
        j = real_code_addr
        
        while True:
            asm = idc.GetDisasm(j)
            next_asm = idc.GetDisasm(NextHead(j))
            if '___cxa_allocate_exception' in next_asm:
                break
            print asm
            out.write(asm + "\n")
            j = NextHead(j)
            
        k = j
        j = NextHead(j)
        l = NextHead(j)
        i = idc.GetOperandValue(l, 1)
        
        MakeUnkn(call_addr, 0)
        idc.PatchByte(k, 0xC3)
        MakeFunction(real_code_addr)
        SetType(real_code_addr, "void x()")
        
        code = decompile_func(real_code_addr)
        print code
        code = code[code.find("{") + 2 + 1:code.find("}") - 1] + "\n"
        all += code
        break

out2.write(all)
out.close()
out2.close()

這個腳本主要做了幾個事情

從 0x1C 開始抓函數,然後從函數頭 + 0x43 的位置一路抓到 ___cxa_allocate_exception 前二行結束

最後為了方便 IDA Pro 做反編譯,我 patch 了 mov edi, 4 成 ret ,然後函數開始改成 +0x43 的地方

在取出程式碼最後輸出


mov     dword ptr [rbp-14h], 0
cmp     dword ptr [rbp-14h], 0Fh
jg      short locret_694A
mov     eax, [rbp-14h]
movsxd  rdx, eax
lea     rax, ptr_0
movzx   ecx, byte ptr [rdx+rax]
mov     eax, [rbp-14h]
movsxd  rdx, eax
lea     rax, out_0
movzx   eax, byte ptr [rdx+rax]
xor     ecx, eax
mov     eax, [rbp-14h]
movsxd  rdx, eax
lea     rax, ptr_0
mov     [rdx+rax], cl
add     dword ptr [rbp-14h], 1
jmp     short loc_690A
retn
movzx   eax, byte ptr cs:ptr_0
movzx   eax, al
movzx   edx, byte ptr cs:ptr_0+1
movzx   edx, dl
shl     edx, 8
or      edx, eax
movzx   eax, byte ptr cs:ptr_0+2
movzx   eax, al
shl     eax, 10h
or      edx, eax
movzx   eax, byte ptr cs:ptr_0+3
movzx   eax, al
...

大概長這樣,不過 ASM 有 1000 行還是很累,所以看反編譯的虛擬C扣


 __int64 v0; // rbp

  for ( *(_DWORD *)(v0 - 20) = 0; *(_DWORD *)(v0 - 20) <= 15; ++*(_DWORD *)(v0 - 20) )
    ptr_0[*(signed int *)(v0 - 20)] ^= *((_BYTE *)&out_0 + *(signed int *)(v0 - 20));
 h1 = ((ptr_0[3] << 24) | (ptr_0[2] << 16) | *(unsigned __int16 *)ptr_0) ^ *(_DWORD *)pKey;
 h2 = ((ptr_0[7] << 24) | (ptr_0[6] << 16) | *(unsigned __int16 *)&ptr_0[4]) ^ *((_DWORD *)pKey + 1);
 h3 = ((ptr_8[3] << 24) | (ptr_8[2] << 16) | *(unsigned __int16 *)ptr_8) ^ *((_DWORD *)pKey + 2);
 h4 = ((ptr_8[7] << 24) | (ptr_8[6] << 16) | *(unsigned __int16 *)&ptr_8[4]) ^ *((_DWORD *)pKey + 3); ; h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey + (unsigned __int8)h1 + 64LL) ^ *((_DWORD *)pKey + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 8) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 9) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 10) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 11) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 0x240LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 0x140LL) ^ *((_DWORD *)pKey + ((unsigned int)h2 >> 24) + 0x40LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 0x340LL);
 h3 ^= *((_DWORD *)pKey + 12) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 13) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 14) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 15) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 16) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 17) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 18) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 19) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 20) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 21) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 22) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 23) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 24) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 25) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 26) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 27) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 28) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 29) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 30) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 31) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 32) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 33) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h3
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h3 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 34) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 35) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h1) + 576LL) ^ *((_DWORD *)pKey + BYTE1(h1) + 320LL) ^ *((_DWORD *)pKey
                                                                                       + (unsigned __int8)h1
                                                                                       + 64LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h1 >> 24)
                                                                                                 + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h2) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h2 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h2 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h2) + 832LL);
 h3 ^= *((_DWORD *)pKey + 36) + h6 + h5;
 h3 = __ROR4__(h3, 1);
 h4 = __ROL4__(h4, 1);
 h4 ^= *((_DWORD *)pKey + 37) + h5 + 2 * h6;
 h5 = *((_DWORD *)pKey + BYTE2(h3) + 0x240LL) ^ *((_DWORD *)pKey + BYTE1(h3) + 320LL) ^ *((_DWORD *)pKey
                                                                                         + (unsigned __int8)h3
                                                                                         + 64LL) ^ *((_DWORD *)pKey + ((unsigned int)h3 >> 24) + 832LL);
 h6 = *((_DWORD *)pKey + BYTE1(h4) + 576LL) ^ *((_DWORD *)pKey + (unsigned __int8)h4 + 320LL) ^ *((_DWORD *)pKey
                                                                                                 + ((unsigned int)h4 >> 24)
                                                                                                 + 64LL) ^ *((_DWORD *)pKey + BYTE2(h4) + 832LL);
 h1 ^= *((_DWORD *)pKey + 38) + h6 + h5;
 h1 = __ROR4__(h1, 1);
 h2 = __ROL4__(h2, 1);
 h2 ^= *((_DWORD *)pKey + 39) + h5 + 2 * h6;
 ;
 h3 ^= *((_DWORD *)pKey + 4);
 h4 ^= *((_DWORD *)pKey + 5);
 h1 ^= *((_DWORD *)pKey + 6);
 h2 ^= *((_DWORD *)pKey + 7);
 LOBYTE(out_0) = h3;
 BYTE1(out_0) = BYTE1(h3);
 BYTE2(out_0) = BYTE2(h3);
 BYTE3(out_0) = HIBYTE(h3);
 BYTE4(out_0) = h4;
 BYTE5(out_0) = BYTE1(h4);
 BYTE6(out_0) = BYTE2(h4);
 HIBYTE(out_0) = HIBYTE(h4);
 LOBYTE(out_8) = h1;
 BYTE1(out_8) = BYTE1(h1);
 BYTE2(out_8) = BYTE2(h1);
 BYTE3(out_8) = HIBYTE(h1);
 BYTE4(out_8) = h2;
 BYTE5(out_8) = BYTE1(h2);
 BYTE6(out_8) = BYTE2(h2);
 HIBYTE(out_8) = HIBYTE(h2);

最後就可以解出 FLAG 了

(2018/11/01 Update )
我腦弱忘了 Check後面 QQ ,最後的 XOR 那邊要給從下次加密後要 ^ hash[ i - 16]  

整理後的程式碼以及解密的程式碼我放在 gist

有興趣的可以去看看 ouo

EOP 整理後 :  https://gist.github.com/taida957789/f5b606fd1286e47eb18d3b9416f21094

EOP 解密:https://gist.github.com/taida957789/57b69940f3765e9eef0cade34eacab97

 

留言

comments