# The return of Anti Debug ![](https://i.imgur.com/grmhISm.png) - Bài này mang tên antidebug vì tác giả chỉ cho chúng ta `source code` assembly và `log` lúc chương trình đang chạy, tiếp đến là file `DUMP` binary : - `CODE.TXT` : chứa code assembly được coppy từ IDA. - `file DUMP` : Binary data - `LOG.TXT` : Log lúc chạy chương trình - File `LOG.txt`: ``` nguyen@nguyen:~/Desktop/test$ ./a.out Oh no, someone leaked something... AE 88 89 ``` - Mình sẽ tiến hành đọc file `CODE.TXT` để rõ hơn, như thường lệ mình bắt đầu từ hàm `main`: ```assembly= public main main proc near ; DATA XREF: _start+21↑o var_BC = dword ptr -0BCh var_B8 = dword ptr -0B8h var_B4 = dword ptr -0B4h stream = qword ptr -0B0h ptr = qword ptr -0A8h s = byte ptr -0A0h var_50 = byte ptr -50h var_8 = qword ptr -8 ; __unwind { endbr64 push rbp mov rbp, rsp sub rsp, 0C0h mov rax, fs:28h mov [rbp+var_8], rax xor eax, eax lea rsi, modes ; "r" lea rdi, aSomethingsecre ; "./somethingSecret.txt" call _fopen mov [rbp+stream], rax mov edi, 4Ch ; 'L' ; size call _malloc mov [rbp+ptr], rax mov rdx, [rbp+stream] mov rax, [rbp+ptr] mov rcx, rdx ; stream mov edx, 1 ; n mov esi, 42h ; 'B' ; size mov rdi, rax ; ptr call _fread mov rax, [rbp+stream] mov rdi, rax ; stream call _fclose lea rdi, s ; "Oh no, someone leaked something..." call _put ... ``` - Đoạn bên trên chương trình đã open file `somethingSecret.txt` và đọc file này nên chắc chắn file này chứa flag chúng ta cần tìm. Chương trình đọc và lưu vào vùng nhớ tên là `ptr`. Lúc này `ptr` sẽ chứa địa chỉ trỏ tới data đã đọc. - Tiếp đến chúng ta có thể thấy dòng chữ `Oh no, someone leaked something...`, và tiếp đến là những data bị leak. ```assembly= lea rdi, s ; "Oh no, someone leaked something..." call _puts lea rax, [rbp+s] mov edx, 42h ; 'B' ; n mov esi, 0 ; c mov rdi, rax ; s call _memset lea rax, [rbp+var_50] mov edx, 42h ; 'B' ; n mov esi, 0 ; c mov rdi, rax ; s call _memset mov edi, 0 ; timer call _time mov edi, eax ; seed call _srand mov [rbp+var_BC], 0 jmp short loc_1657 ``` - chúng ta thấy chương trình gọi `time(0)` làm seed (`srand`) cho hàm random. - Tiếp theo ```assembly= jmp short loc_1657 ; --------------------------------------------------------------------------- loc_163A: ; CODE XREF: main+F7↓j call _rand mov edx, eax mov eax, [rbp+var_BC] cdqe mov [rbp+rax+s], dl add [rbp+var_BC], 1 loc_1657: ; CODE XREF: main+D1↑j cmp [rbp+var_BC], 41h ; 'A' jle short loc_163A mov [rbp+var_B8], 0 jmp short loc_16BD ``` - Chương trình gọi hàm `rand` liên tục `65 lần` để sinh số ngẫu nhiên sau đó thì lần lượt cho vào vùng nhớ tên `s` : `mov [rbp+rax+s], dl`. - Tiếp theo ```assembly= jmp short loc_16BD ; --------------------------------------------------------------------------- loc_166C: ; CODE XREF: main+15D↓j mov eax, [rbp+var_B8] movsxd rdx, eax mov rax, [rbp+ptr] add rax, rdx movzx edx, byte ptr [rax] mov eax, [rbp+var_B8] cdqe movzx eax, [rbp+rax+s] xor eax, edx mov edx, eax mov eax, [rbp+var_B8] cdqe movzx eax, [rbp+rax+s] add eax, edx mov edx, eax mov eax, [rbp+var_B8] cdqe mov [rbp+rax+var_50], dl add [rbp+var_B8], 1 loc_16BD: ; CODE XREF: main+103↑j cmp [rbp+var_B8], 41h ; 'A' jle short loc_166C mov [rbp+var_B4], 0 jmp short loc_16FF ``` - Đoạn code trên khi về code C sẽ như sau : ```C= for(int var_B8=0;var_B8<=0x41;var_B8++){ var_50[var_B8] = ptr[var_B8]^s[var_B8] + s[var_B8]; } ``` - Vậy là chương trình đã encrypt flag của chúng ta và lưu vào trong stack. - Tiếp theo ```assembly= mov [rbp+var_B4], 0 jmp short loc_16FF ; --------------------------------------------------------------------------- loc_16D2: ; CODE XREF: main+19F↓j mov eax, [rbp+var_B4] cdqe movzx eax, [rbp+rax+var_50] movsx eax, al movzx eax, al mov esi, eax lea rdi, format ; "%02X " mov eax, 0 call _printf add [rbp+var_B4], 1 loc_16FF: ; CODE XREF: main+169↑j cmp [rbp+var_B4], 2 jle short loc_16D2 mov edi, 0Ah ; c call _putchar mov eax, 0 call sus mov eax, 0 mov rcx, [rbp+var_8] xor rcx, fs:28h jz short locret_1735 call ___stack_chk_fail ; --------------------------------------------------------------------------- locret_1735: ; CODE XREF: main+1C7↑j leave retn ; } // starts at 1567 main endp ``` - Vậy là chương trình đã in ra 3 byte của cipher ở trong stack và sau đó thì gọi đến hàm `sus` của (`call sus`). - Phân tích hàm sus thì giống hệt đoạn dump stack trong hint write up của tác giả đã hint. Vậy là luồng của bài này yêu cầu chúng ta phải tìm được những `cipher` có trong stack (file `DUMP` chính là stack) và đồng thời để giải được flag chúng ta phải tìm được cả dãy byte `random`. - Chúng ta thử tìm dãy byte mà chương trình đã leak bằng vòng for đơn giản : ```python= sample = bytes.fromhex("AE 88 89") dump = open("dump","rb").read() cipher = b"" for i in range(len(dump)): if dump[i:(i+3)] in sample: print(f"Found Cipher in offset: {hex(i)}") cipher = dump[i:(i+0x42)] ``` - Chạy thử : ```powershell Found Cipher in offset: 0x1f330 cipher: b'\xae\x88\x89n\x97_l\x8d\x95\x8a\x9f\x92\x81\x9f\x8b\x89\x8f\x9fh\x95\x8d_v\x9dy_\x98\x85\x86_\x8dou_{n\x91\x90r\x9f\x8c\x99\x9fb\x85m_zu\x95\x9b_c\x89q\x9f\x88vyp\x92\x9f~\x89\x99\x90' ``` - Vậy là cipher ở offset `0x1f330` trong file `DUMP`. - Còn lại chúng ta cần tìm dãy `random` đã được sinh ra để `encrypt`. - Kéo lên trên hàm `main` một chút chúng ta có thể thấy: ```assembly= ; int __cdecl main(int argc, const char **argv, const char **envp) public main main proc near ; DATA XREF: _start+21↑o var_BC = dword ptr -0BCh var_B8 = dword ptr -0B8h var_B4 = dword ptr -0B4h stream = qword ptr -0B0h ptr = qword ptr -0A8h s = byte ptr -0A0h var_50 = byte ptr -50h var_8 = qword ptr -8 ``` - `var_50` (địa chỉ của cipher) và `s` (chuỗi random), cách nhau là`0xA0-0x50=0x50` byte. - Vậy từ base của cipher chúng ta trừ đi `0x50` là chúng ta sẽ tới được địa chỉ của chuỗi `random`. - Update: ```python= sample = bytes.fromhex("AE 88 89") dump = open("dump","rb").read() cipher = b"" rand = b"" for i in range(len(dump)): if dump[i:(i+3)] in sample: print(f"Found Cipher in offset: {hex(i)}") cipher = dump[i:(i+0x42)] rand = dump[(i-80):(i-80+0x42)] ``` - Đến đây chúng ta chỉ việc làm ngược lại so với công thức encrypt là ra được flag. - Script của mình : ```python= sample = bytes.fromhex("AE 88 89") dump = open("dump","rb").read() cipher = b"" rand = b"" for i in range(len(dump)): if dump[i:(i+3)] in sample: print(f"Found Cipher in offset: {hex(i)}") cipher = dump[i:(i+0x42)] rand = dump[(i-80):(i-80+0x42)] print(f"rand: {rand}") print(f"cipher: {cipher}") print(f"secret: ",end="") for i in range(0x42): """cipher = input^rand + rand""" tmp = (cipher[i]-rand[i])^rand[i] tmp &= 0xff print(chr(tmp),end="") print("\nDone") ``` - Kết quả : ```powershell= Found Cipher in offset: 0x1f330 rand: b'\xbaX\x8f(|\x1c\x05:X\xab\xf8\xb7\xe4jz\xf2\x1b\xa8\x86Z{\xc6m\x9f\x90\xd3\x9e\\\xa9\x96\xf1c\xee\x80\x8ck\x9c\x91\xa5\xf4<\x9d\xab \x08&\x13#\xce\x99~I`\xeb\xe9\xf0\xbe\x87Lg\x1d=\xcb\x0b\xbdW' cipher: b'\xae\x88\x89n\x97_l\x8d\x95\x8a\x9f\x92\x81\x9f\x8b\x89\x8f\x9fh\x95\x8d_v\x9dy_\x98\x85\x86_\x8dou_{n\x91\x90r\x9f\x8c\x99\x9fb\x85m_zu\x95\x9b_c\x89q\x9f\x88vyp\x92\x9f~\x89\x99\x90' secret: Nhung_biet_ly_keo_dai_day_dut_moi_chinh_la_bua_tiec_cua_thanh_xuan Done ``` --- # Baby Apk ![](https://i.imgur.com/9tGBFgg.png) - Ném vào `jadx` mình biết được `app` viết bằng flutter - Sau một hồi tìm hiểu và đọc ở `https://cryptax.medium.com/reversing-an-android-sample-which-uses-flutter-23c3ff04b847` mình được biết app được build theo `mode debug` và code gốc vẫn còn nằm trong file `Resources/assets/flutter_assets/kernel_blob.bin` - Mình tiến hành extract source và `strings` file này để tìm code: ![](https://i.imgur.com/DUPLzFJ.png) - Tìm đến package `wannagame_championship` : ![](https://i.imgur.com/CvofCVB.png)