Coconut CTF: Obfuscate Bin

From Indonesian Research And Development Center
Jump to: navigation, search

Misi

Misi pada level ini adalah mencari password dari file elf executable yang diobfuscate dan diproteksi dengan beberapa fitur anti debugging diantaranya adalah anti ptrace. Fitur anti debugging tersebut pernah dipresentasikan oleh aczid pada tahun 2012 (lihat bagian referensi pada tutorial ini).


Static Analysis

  • Hal pertama yang dilakukan adalah mencari tahu jenis file pada misi ini:
% file obfbin
obfbin: ELF, unknown class 83
  • Dari langkah di atas, bisa terlihat bahwa file tersebut tipenya adalah elf namun tidak ada informasi lebih lanjut. Selanjutnya kita coba menggunakan strings untuk mencari string pada file executable tersebut (bagian yang menarik akan diberi tanda pada listing berikut):
% strings obfbin
ELFSAREUBER1337
/lib/ld-linux.so.2
WKWKWKWKWKWKWKWKWKWKWKWKWKWKWKW
WKWKWKWKWKWKWKWKWKWKWKWKWKWKWKWKWKW
__gmon_start__
libc.so.6
_IO_stdin_used
strncmp                         <----- fungsi yang diimport (strncmp)
puts                            <----- fungsi yang diimport (puts)
_exit
printf                          <----- fungsi yang diimport (printf)
strlen                          <----- fungsi yang diimport (strlen)
ptrace
__libc_start_main
GLIBC_2.0
PTRhp
[^_]
=))!
usahayahbro                     <----- interesting
 Mantap, Itulah Flagnya         <----- interesting
 Belum Beruntung, Coba lagi!    <----- interesting
 *****[%s] ******
 Gunakan: %s <password>
WKWKWKWKWKWKWKWKWKWKWKWKWKW
...
  • Selanjutnya kita mencoba melihat informasi file tersebut menggunakan readelf walaupun tidak banyak informasi yang dapat diperoleh:
% readelf -e obfbin
ELF Header:
  Magic:   7f 45 4c 46 53 41 52 45 55 42 45 52 31 33 33 37
  Class:                             <unknown: 53>
  Data:                              <unknown: 41>
  Version:                           82 <unknown: %lx>
  OS/ABI:                            <unknown: 45>
  ABI Version:                       85
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x7a69
  Entry point address:               0x8048420
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4532 (bytes into file)
  Flags:                             0x7a69
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         31337
  Section header string table index: 0
readelf: Error: Unable to read in 0x132068 bytes of section headers

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x007b0 0x007b0 R E 0x1000
  LOAD           0x0007b0 0x080497b0 0x080497b0 0x00120 0x00128 RW  0x1000
  DYNAMIC        0x0007c8 0x080497c8 0x080497c8 0x000d0 0x000d0 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00044 0x00044 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
  • Usaha untuk melakukan disassembly menggunakan objdump pun tidak banyak membantu:
% objdump -M intel -D obfbin
objdump: obfbin: File format not recognized


Solusi 1

Seperti bisa terlihat pada bagian di atas, beberapa langkah yang dilakukan hanya memberikan informasi yang sangat minim. Solusi pertama yang dapat dilakukan adalah melakukan hard patching, walaupun solusi ini sebenarnya kurang elegan. Caranya adalah sebagai berikut:

  • Buka file misi tersebut menggunakan IDA Pro dan perhatikan bagian berikut ini:
LOAD:0804851D sub_804851D     proc near                                         ; DATA XREF: start+17
LOAD:0804851D
LOAD:0804851D arg_0           = dword ptr  8
LOAD:0804851D arg_4           = dword ptr  0Ch
LOAD:0804851D
LOAD:0804851D                 push    ebp
LOAD:0804851E                 mov     ebp, esp
LOAD:08048520                 and     esp, 0FFFFFFF0h
LOAD:08048523                 sub     esp, 10h
LOAD:08048526                 cmp     [ebp+arg_0], 2                            ; periksa apakah argumen (argc) jumlahnya 2
LOAD:0804852A                 jz      short loc_8048540                         ; jika ya, lanjutkan untuk memeriksa password
LOAD:0804852C                 mov     eax, [ebp+arg_4]                          ; eax = parameter/argumen aplikasi -----+
LOAD:0804852F                 mov     eax, [eax]                                ;                                       |
LOAD:08048531                 mov     [esp], eax                                ; parameter/argumen                     |
LOAD:08048534                 call    sub_804863B                               ; tampilkan pesan cara penggunaan       |
LOAD:08048539                 mov     eax, 0FFFFFFFFh                           ; ret_val = -1                          |
LOAD:0804853E                 jmp     short locret_804858B                      ; return -1; -----------------------+   |
LOAD:08048540                                                                   ;                                   |   |
LOAD:08048540 loc_8048540:                                                      ; CODE XREF: sub_804851D+D <--------)---'
LOAD:08048540                 mov     eax, [ebp+arg_4]                          ; eax = parameter/argumen           |
LOAD:08048543                 add     eax, 4                                    ; argumen ke-2 (password)           |
LOAD:08048546                 mov     eax, [eax]                                ;                                   |
LOAD:08048548                 mov     [esp], eax                                ; param 1: user_pwd                 |
LOAD:0804854B                 call    sub_804858D                               ; panggil fungsi rot13(user_pwd) ---)-----------+
LOAD:08048550                 mov     dword ptr [esp+8], 0Bh                    ; param 3: 0x0B (pwd len)           |           |
LOAD:08048558                 mov     [esp+4], eax                              ; param 2: rot13(user_pwd)          |           |
LOAD:0804855C                 mov     dword ptr [esp], offset aUsahayahbro      ; param 1: "usahayahbro" (valid pwd)|           |
LOAD:08048563                 call    sub_8048404                               ; strncmp("usahayahbro",pwd,0x0B);  |           |
LOAD:08048568                 test    eax, eax                                  ; jika valid, eax == 0              |           |
LOAD:0804856A                 jnz     short loc_804857A                         ; salah (eax != 0) **BAD BOY!** ----)---+       |
LOAD:0804856C                 mov     dword ptr [esp], offset aMantapItulahFl   ; "\n Mantap, Itulah Flagnya"       |   |       |
LOAD:08048573                 call    sub_80483F4                               ; puts("\n Mantap, Itulah Flagnya");|   |       |
LOAD:08048578                 jmp     short loc_8048586                         ; bail out -------------------------)---)---+   |
LOAD:0804857A                                                                   ;                                   |   |   |   |
LOAD:0804857A loc_804857A:                                                      ; CODE XREF: sub_804851D+4D         |   |   |   |
LOAD:0804857A                 mov     dword ptr [esp], offset aBelumBeruntung   ; "\n Belum Beruntung, Coba lagi! "<)---'   |   |
LOAD:08048581                 call    sub_80483F4                               ;                                   |       |   |
LOAD:08048586                                                                   ;                                   |       |   |
LOAD:08048586 loc_8048586:                                                      ; CODE XREF: sub_804851D+5B <-------)-------'   |
LOAD:08048586                 mov     eax, 0                                    ; ret_val = 0 (return value)        |           |
LOAD:0804858B                                                                   ;                                   |           |
LOAD:0804858B locret_804858B:                                                   ; CODE XREF: sub_804851D+21         |           |
LOAD:0804858B                 leave                                             ;                                   |           |
LOAD:0804858C                 retn                                              ; return ret_val; <-----------------'           |
LOAD:0804858C sub_804851D     endp                                              ;                                               |
...                                                                             ;                                               |
LOAD:0804858D sub_804858D     proc near                                         ; CODE XREF: sub_804851D+2E <-------------------'
LOAD:0804858D
LOAD:0804858D var_C           = dword ptr -0Ch
LOAD:0804858D arg_0           = dword ptr  8
LOAD:0804858D
LOAD:0804858D                 push    ebp
LOAD:0804858E                 mov     ebp, esp
LOAD:08048590                 push    ebx
LOAD:08048591                 sub     esp, 24h                                  ; alokasi stack 0x24 bytes
LOAD:08048594                 mov     [ebp+var_C], 0                            ; counter = 0
LOAD:0804859B                 jmp     short loc_80485BF                         ;
LOAD:0804859D                                                                   ;
LOAD:0804859D loc_804859D:                                                      ; CODE XREF: sub_804858D+42 <-------.
LOAD:0804859D                 mov     eax, [ebp+var_C]                          ; eax = counter                     |
LOAD:080485A0                 mov     ebx, eax                                  ;                                   |
LOAD:080485A2                 add     ebx, [ebp+arg_0]                          ;                                   |
LOAD:080485A5                 mov     eax, [ebp+var_C]                          ;                                   |
LOAD:080485A8                 add     eax, [ebp+arg_0]                          ;                                   |
LOAD:080485AB                 movzx   eax, byte ptr [eax]                       ;                                   |
LOAD:080485AE                 movsx   eax, al                                   ;                                   |
LOAD:080485B1                 mov     [esp], eax                                ; param 1: user_pwd[counter]        |
LOAD:080485B4                 call    sub_80485DA                               ; rot13(user_pwd[counter]); --------)---+
LOAD:080485B9                 mov     [ebx], al                                 ;                                   |   |
LOAD:080485BB                 add     [ebp+var_C], 1                            ; counter++                         |   |
LOAD:080485BF                                                                   ;                                   |   |
LOAD:080485BF loc_80485BF:                                                      ; CODE XREF: sub_804858D+E          |   |
LOAD:080485BF                 mov     ebx, [ebp+var_C]                          ; ebx = counter                     |   |
LOAD:080485C2                 mov     eax, [ebp+arg_0]                          ; eax = user_pwd                    |   |
LOAD:080485C5                 mov     [esp], eax                                ; param 1: user_pwd                 |   |
LOAD:080485C8                 call    sub_80483D4                               ; strlen(user_pwd);                 |   |
LOAD:080485CD                 cmp     ebx, eax                                  ; counter == strlen(user_pwd)       |   |
LOAD:080485CF                 jb      short loc_804859D                         ; ulangi jika masih ada karakter ---+   |
LOAD:080485D1                 mov     eax, [ebp+arg_0]                          ; ret_val = rot13(user_pwd)             |
LOAD:080485D4                 add     esp, 24h                                  ; restore/cleanup stack                 |
LOAD:080485D7                 pop     ebx                                       ;                                       |
LOAD:080485D8                 pop     ebp                                       ;                                       |
LOAD:080485D9                 retn                                              ; return ret_val;                       |
LOAD:080485D9 sub_804858D     endp                                              ;                                       |
...                                                                             ;                                       |
LOAD:080485DA sub_80485DA     proc near                                         ; CODE XREF: sub_804858D+27 <-----------'
LOAD:080485DA
LOAD:080485DA var_C           = dword ptr -0Ch
LOAD:080485DA arg_0           = dword ptr  8
LOAD:080485DA
LOAD:080485DA                 push    ebp
LOAD:080485DB                 mov     ebp, esp
LOAD:080485DD                 push    esi
LOAD:080485DE                 push    ebx
LOAD:080485DF                 sub     esp, 10h
LOAD:080485E2                 mov     eax, [ebp+arg_0]
LOAD:080485E5                 and     eax, 0DFh
LOAD:080485EA                 xor     eax, 40h
LOAD:080485ED                 mov     [ebp+var_C], eax
LOAD:080485F0                 cmp     [ebp+var_C], 0
LOAD:080485F4                 jz      short loc_8048631
LOAD:080485F6                 cmp     [ebp+var_C], 1Ah
LOAD:080485FA                 jg      short loc_8048631
LOAD:080485FC                 mov     eax, [ebp+arg_0]
LOAD:080485FF                 mov     ebx, eax
LOAD:08048601                 and     ebx, 60h
LOAD:08048604                 mov     eax, [ebp+var_C]
LOAD:08048607                 lea     ecx, [eax+0Ch]
LOAD:0804860A                 mov     edx, 4EC4EC4Fh
LOAD:0804860F                 mov     eax, ecx
LOAD:08048611                 imul    edx
LOAD:08048613                 sar     edx, 3
LOAD:08048616                 mov     eax, ecx
LOAD:08048618                 sar     eax, 1Fh
LOAD:0804861B                 mov     esi, edx
LOAD:0804861D                 sub     esi, eax
LOAD:0804861F                 mov     eax, esi
LOAD:08048621                 imul    eax, 1Ah
LOAD:08048624                 mov     edx, ecx
LOAD:08048626                 sub     edx, eax
LOAD:08048628                 mov     eax, edx
LOAD:0804862A                 add     eax, 1
LOAD:0804862D                 or      eax, ebx
LOAD:0804862F                 jmp     short loc_8048634
LOAD:08048631
LOAD:08048631 loc_8048631:                                                      ; CODE XREF: sub_80485DA+1A
LOAD:08048631                                                                   ; sub_80485DA+20
LOAD:08048631                 mov     eax, [ebp+arg_0]
LOAD:08048634
LOAD:08048634 loc_8048634:                                                      ; CODE XREF: sub_80485DA+55
LOAD:08048634                 add     esp, 10h
LOAD:08048637                 pop     ebx
LOAD:08048638                 pop     esi
LOAD:08048639                 pop     ebp
LOAD:0804863A                 retn
LOAD:0804863A sub_80485DA     endp
  • Dengan memperhatikan kode di atas, kita dapat melakukan patching pada bagian ini:
LOAD:08048540                         loc_8048540:
LOAD:08048540 8B 45 0C                                mov     eax, [ebp+arg_4]
LOAD:08048543 83 C0 04                                add     eax, 4
LOAD:08048546 8B 00                                   mov     eax, [eax]
LOAD:08048548 89 04 24                                mov     [esp], eax
LOAD:0804854B E8 3D 00 00 00                          call    sub_804858D
LOAD:08048550 C7 44 24 08 0B 00 00 00                 mov     dword ptr [esp+8], 0Bh                    ; <<< *****patch di sini*****
LOAD:08048558 89 44 24 04                             mov     [esp+4], eax                              ; <<< dari sini loncat ke sini -+
LOAD:0804855C C7 04 24 35 87 04 08                    mov     dword ptr [esp], offset aUsahayahbro      ; "usahayahbro"                 |
LOAD:08048563 E8 9C FE FF FF                          call    sub_8048404                               ;                               |
LOAD:08048568 85 C0                                   test    eax, eax                                  ;                               |
LOAD:0804856A 75 0E                                   jnz     short loc_804857A                         ;                               |
LOAD:0804856C C7 04 24 41 87 04 08                    mov     dword ptr [esp], offset aMantapItulahFl   ; "\n Mantap, Itulah Flagnya"   |
LOAD:08048573 E8 7C FE FF FF                          call    sub_80483F4                               ; <-----------------------------'
LOAD:08048578 EB 0C                                   jmp     short loc_8048586
LOAD:0804857A
LOAD:0804857A                         loc_804857A:
LOAD:0804857A C7 04 24 5C 87 04 08                    mov     dword ptr [esp], offset aBelumBeruntung   ; "\n Belum Beruntung, Coba lagi! "
LOAD:08048581 E8 6E FE FF FF                          call    sub_80483F4
LOAD:08048586
LOAD:08048586                         loc_8048586:
LOAD:08048586 B8 00 00 00 00                          mov     eax, 0
LOAD:0804858B
LOAD:0804858B                         locret_804858B:
LOAD:0804858B C9                                      leave
LOAD:0804858C C3                                      retn
LOAD:0804858C                         sub_804851D     endp
  • Patching yang akan dilakukan adalah dengan mengubah instruksi pada alamat 0x08048550 menjadi mov [esp], eax dan jika memperhatikan potongan disassembly di atas, bisa terlihat bahwa mnemonix untuk instruksi tersebut menggunakan 3 byte, yaitu 89 04 24 (hexadesimal). Setelah itu, loncat ke alamat 0x08048573 untuk menampilkan password yang benar. Instruksi yang akan kita gunakan untuk jump adalah jmp yang mnemonixnya adalah EB dan jarak lompatannya bisa dihitung dengan menggunakan rumus: alamat_tujuan - alamat_asal - 2 byte. Dikurangi 2 byte karena instruksi jump yang akan kita gunakan ukurannya 2 byte. Jadi mnemonix lengkap untuk instruksi jmp tersebut adalah EB 1E. Berikut ini adalah potongan disassembly patch yang akan digunakan:
LOAD:08048540                         loc_8048540:                                                      ;
LOAD:08048540 8B 45 0C                                mov     eax, [ebp+arg_4]                          ;
LOAD:08048543 83 C0 04                                add     eax, 4                                    ;
LOAD:08048546 8B 00                                   mov     eax, [eax]                                ;
LOAD:08048548 89 04 24                                mov     [esp], eax                                ;
LOAD:0804854B E8 3D 00 00 00                          call    sub_804858D                               ;
LOAD:08048550 89 04 24                                mov     [esp], eax                                ; param 1: passwd
LOAD:08048553 EB 1E                                   jmp     short loc_8048573                         ; loncat ke sini ---------------+
LOAD:08048555 00                                      db    0                                           ;                               |
LOAD:08048556 00                                      db    0                                           ;                               |
LOAD:08048557 00                                      db    0                                           ;                               |
LOAD:08048558 89 44 24 04                             mov     [esp+4], eax                              ;                               |
LOAD:0804855C C7 04 24 35 87 04 08                    mov     dword ptr [esp], offset aUsahayahbro      ; "usahayahbro"                 |
LOAD:08048563 E8 9C FE FF FF                          call    sub_8048404                               ;                               |
LOAD:08048568 85 C0                                   test    eax, eax                                  ;                               |
LOAD:0804856A 75 0E                                   jnz     short loc_804857A                         ;                               |
LOAD:0804856C C7 04 24 41 87 04 08                    mov     dword ptr [esp], offset aMantapItulahFl   ; "\n Mantap, Itulah Flagnya"   |
LOAD:08048573                                                                                           ;                               |
LOAD:08048573                         loc_8048573:                                                      ;                               |
LOAD:08048573 E8 7C FE FF FF                          call    sub_80483F4                               ; printf(passwd); <-------------'
LOAD:08048578 EB 0C                                   jmp     short loc_8048586
  • Setelah itu, kita perlu mencari offset yang akan di-patch yaitu 0x550. Untuk patching, gunakan perintah berikut ini:
% echo -n "0000550: 8904 24eb 1e00 0000 8944 2404 c704 2435" | xxd -r - obfbin
  • Langkah terakhir adalah menjalankan executable obfbin tersebut dengan parameter password yang valid seperti ini:
% ./obfbin usahayahbro
hfnunlnuoeb
  • Itu adalah password valid yang kita butuhkan. Untuk membuktikannya, kita tinggal menggunakan password tersebut sebagai parameter pada executable obfbin yang belum di-patch:
% ./obfbin hfnunlnuoeb

 Mantap, Itulah Flagnya


Solusi 2

Solusi ke-2 ini sifatnya sedikit lebih elegan yaitu melakukan kalkukasi dengan meminjam algoritma pada fungsi sub_80485DA pada potongan disassembly yang telah dibahas pada solusi 1.


Penutup

Pengetahuan mengenai instruksi pada suatu arsitektur komputer akan mempermudah Anda dalam melakukan reverse engineering. Sekian tutorial kali ini, semoga bermanfaat. Terima kasih kepada Tuhan Yang Maha Esa, RNDC, Maxindo, N3 dan Anda yang telah membaca tutorial ini.


Referensi