# Simple Reverse 0x12(Lab - TLSCallback) ## Background [課程相關影片](https://www.youtube.com/live/4-hgyiCV3ZA?feature=share&t=6624) [[C語言] function pointer的應用[四]: function pointer array](https://medium.com/@racktar7743/c語言-function-pointer的應用-四-function-pointer-array-d0d624db8406) ## Source Code :::spoiler IDA main function ```cpp int __cdecl main(int argc, const char **argv, const char **envp) { __int64 v3; // rbx int v4; // edi __int64 v5; // r14 char *v6; // rsi __int64 v7; // rax const char *v8; // rcx printf("Give me flag: "); scanf("%58s"); v3 = 0i64; v4 = 0; v5 = 0i64; v6 = flag; do { (funcs_140001156[v4 % 3u])(&flag[v5]); ++v6; v7 = v5 & 3; ++v4; ++v5; *(v6 - 1) += key_140004050[v7]; } while ( v4 < 58 ); while ( flag[v3] == byte_1400022B8[v3] ) { if ( ++v3 >= 58 ) { v8 = "Correct!"; goto LABEL_7; } } v8 = "Wrong QAO"; LABEL_7: puts(v8); return 0; } ``` ::: ## Recon 這一題也蠻簡單的,只要有耐心分析一下就可以了 1. 首先執行一下這隻程式,發現沒啥特別的,就和之前的題目一樣 ![](https://hackmd.io/_uploads/ryT1QMbKh.png) 2. 用IDA看一下,可以發現也蠻單純的,就用function pointer array然後傳入我們輸入的flag進行一些事情再加上一個數值(來自某一個array) 3. 仔細看一下有哪些function然後分別做了甚麼事 ![](https://hackmd.io/_uploads/SkDpNGbYh.png) 1. xor 0x87 :::spoiler source ``` void __fastcall do_xor(_BYTE *a1) { *a1 ^= 0x87u; } ``` ::: 2. xor 0xff :::spoiler source ``` void __fastcall do_inverse(_BYTE *a1) { *a1 = ~*a1; } ``` ::: 3. xor 0x63 :::spoiler source ``` void __fastcall do_xor_2(_BYTE *a1) { *a1 ^= 0x63u; } ``` ::: 4. <font color="FF0000">陷阱</font> 如果直接分析這樣的code會做白工,因為這一題有tls callback function在搞事,這件事情IDA和x64dbg都有分析出來,或者是也可以用PE-Bear看一下,所以我們就朝這個方向分析一下,看起來兩者都沒有很複雜,tlscallback function 2就只是把剛剛前面的function pointer array的順序置換一下,而tlscallback function 1也只是用置換過後的function pointer array把key的數值做一些操作而已,如果看psuedo code看不太懂得話可以直接用x64dbg用肉眼跟一下(我就這樣XDD),應該也是可以很直觀的猜出這些事情 :::spoiler TLS Callback function 1 & 2 ![](https://hackmd.io/_uploads/SJ4tvzZF2.png) ![](https://hackmd.io/_uploads/BkN5wfWK3.png) ::: 5. 用x64dbg直接動態跟code,以下的screenshot我都有加上一些comment幫助理解 * TLSCallback相關的code ![](https://hackmd.io/_uploads/S1b9FzWth.png) * 三個Function pointer ![](https://hackmd.io/_uploads/BkW1qGbKn.png) * main function ![](https://hackmd.io/_uploads/SJwm5zbF3.png) 6. 結論 在function pointer的順序是xor 0x63 $\to$ xor 0x87 $\to$ xor 0xff 在key的部分是0x21 $\to$ 0xce $\to$ 0x39 $\to$ 0x40 ```asm xor 0x63 + 0x21 xor 0x87 + 0xce xor 0xff + 0x39 xor 0x63 + 0x40 xor 0x87 + 0x21 xor 0xff + 0xce xor 0x63 + 0x39 ... ``` :::info Note: 相加的部分最後只會取==低位byte==喔,所以如果減回去發現是負的,就要在加0x100導正回來 ::: 7. 開寫script ## Exploit ```python= key = [0x21, 0xCE, 0x39, 0x40] enc_flag = [0x46, 0x99, 0xF7, 0x64, 0x1D, 0x79, 0x44, 0x22, 0xC1, 0xD3, 0x27, 0xCD, 0x31, 0xC1, 0xD9, 0x77, 0xEC, 0x7A, 0x75, 0x24, 0xBF, 0xDD, 0x24, 0xDD, 0x23, 0xB2, 0xCD, 0x7C, 0x02, 0x58, 0x46, 0x24, 0xAC, 0xD8, 0x21, 0xD1, 0x5D, 0xBC, 0xC5, 0x7C, 0x05, 0x6C, 0x48, 0x2B, 0xBB, 0xD5, 0x11, 0xCB, 0x35, 0xB6, 0xD9, 0x57, 0x0F, 0x60, 0x3F, 0x34, 0xFF, 0xEC] def xor(index, val): if index % 3 == 0: return val ^ 0x63 elif index % 3 == 1: return val ^ 0x87 else: return val ^ 0xff FLAG = [] for i in range(len(enc_flag)): tmp = enc_flag[i] - key[i % 4] if tmp < 0: tmp += 0x100 tmp = xor(i, tmp) FLAG.append(bytes.fromhex(hex(tmp)[2:]).decode('utf-8')) print("".join(FLAG)) ``` Flag: `FLAG{The_first_TLS_callback_function_is_called_two_times!}`