Capture the Flag

Capture the Flag

by invalid

Ini adalah writeup singkat dari soal kategori Shellcode pada Beginner Malware Reversing Challenges yang terdapat pada situs MalwareTech. Kategori soal ini sangat mudah untuk dikerjakan dan cocok untuk pemula.

Shellcode1


Soal yang diberikan adalah tipe windows executable:

% file shellcode1.exe_
shellcode1.exe_: PE32 executable (GUI) Intel 80386, for MS Windows

Jika executable tersebut dijalankan menggunakan wine, maka akan muncul pesan berupa MD5 hash d342570acf8dfc32d26776cb6938873a. Selanjutnya, gunakan IDA Pro dan load executable tersebut, maka akan terlihat entry point berikut ini:

.text:00402270 start           proc near
.text:00402270
.text:00402270 var_A0          = dword ptr -0A0h
.text:00402270 var_9C          = dword ptr -9Ch
.text:00402270 var_98          = byte ptr -98h
.text:00402270 var_4           = dword ptr -4
.text:00402270
.text:00402270                 push    ebp
.text:00402271                 mov     ebp, esp
.text:00402273                 sub     esp, 0A0h
.text:00402279                 push    esi
.text:0040227A                 lea     ecx, [ebp+var_98]        ;
.text:00402280                 call    MD5::MD5(void)           ;
.text:00402285                 push    10h                      ;
.text:00402287                 push    0                        ;
.text:00402289                 call    ds:GetProcessHeap        ;
.text:0040228F                 push    eax                      ;
.text:00402290                 call    ds:HeapAlloc             ; HeapAlloc(GetProcessHeap(), 0, 0x10)
.text:00402296                 mov     [ebp+var_4], eax         ;
.text:00402299                 mov     eax, [ebp+var_4]         ;
.text:0040229C                 mov     dword ptr [eax], offset a2bBBb ; "2b\n:¦ÜB*bb"
.text:004022A2                 push    offset a2bBBb            ; "2b\n:¦ÜB*bb"
.text:004022A7                 call    strlen                   ;
.text:004022AC                 add     esp, 4                   ;
.text:004022AF                 mov     ecx, [ebp+var_4]         ;
.text:004022B2                 mov     [ecx+4], eax             ;
.text:004022B5                 push    40h                      ;
.text:004022B7                 push    1000h                    ; 0x1000 = MEM_COMMIT
.text:004022BC                 push    0Dh                      ;
.text:004022BE                 push    0                        ;
.text:004022C0                 call    ds:VirtualAlloc          ; VirtualAlloc(0, 0x0d, MEM_COMMIT, 0x40)
.text:004022C6                 mov     [ebp+var_A0], eax        ;
.text:004022CC                 push    0Dh                      ; size_t = 0x0d
.text:004022CE                 push    offset unk_404068        ; offset shellcode
.text:004022D3                 mov     edx, [ebp+var_A0]        ;
.text:004022D9                 push    edx                      ; edx = [ebp+var_A0]
.text:004022DA                 call    memcpy                   ; memcpy([ebp+var_A0], unk_404068, 0x0d)
.text:004022DF                 add     esp, 0Ch                 ;
.text:004022E2                 mov     esi, [ebp+var_4]         ; esi = parameter untuk shellcode
.text:004022E5                 call    [ebp+var_A0]             ; call shellcode
.text:004022EB                 push    offset a2bBBb            ; "2b\n:¦ÜB*bb"
.text:004022F0                 lea     ecx, [ebp+var_98]        ;
.text:004022F6                 call    MD5::digestString(char *);
.text:004022FB                 mov     [ebp+var_9C], eax        ; [ebp+var_9C] = MD5::digestString(offset a2bBBb)
.text:00402301                 push    30h                      ;
.text:00402303                 push    offset aWeVeBeenCompro   ; "We've been compromised!"
.text:00402308                 mov     eax, [ebp+var_9C]        ;
.text:0040230E                 push    eax                      ;
.text:0040230F                 push    0                        ;
.text:00402311                 call    ds:MessageBoxA           ; MessageBox(0, [ebp+var_9C], "We've been compromised!",..)
.text:00402317                 push    0                        ;
.text:00402319                 call    ds:ExitProcess           ; ExitProcess(0)
.text:00402319 start           endp

Berikut ini adalaah bagian penting pada potongan disassembly di atas:

.text:004022CC                 push    0Dh                      ; size_t = 0x0d
.text:004022CE                 push    offset unk_404068        ; offset shellcode
.text:004022D3                 mov     edx, [ebp+var_A0]        ;
.text:004022D9                 push    edx                      ; edx = [ebp+var_A0]
.text:004022DA                 call    memcpy                   ; memcpy([ebp+var_A0], unk_404068, 0x0d)
.text:004022DF                 add     esp, 0Ch                 ;
.text:004022E2                 mov     esi, [ebp+var_4]         ; esi = parameter untuk shellcode
.text:004022E5                 call    [ebp+var_A0]             ; call shellcode

Pada bagian tersebut, shellcode yang terdapat pada offset 0x00404068 akan disalin pada alamat memori [ebp+var_A0]. Ukuran shellcodenya adalah 0x0d atau 13 byte. Lalu shellcode akan dieksekusi/dipanggil pada instruksi di alamat 0x004022E5. Berikut ini adalah shellcode yang terdapat pada offset 0x00404068:

.data:00404068 unk_404068      db  8Bh ; ï                      ; DATA XREF: start+5E^o
.data:00404069                 db  3Eh ; >
.data:0040406A                 db  8Bh ; ï
.data:0040406B                 db  4Eh ; N
.data:0040406C                 db    4
.data:0040406D                 db 0C0h ; +
.data:0040406E                 db  44h ; D
.data:0040406F                 db  0Fh
.data:00404070                 db 0FFh
.data:00404071                 db    5
.data:00404072                 db 0E2h ; G
.data:00404073                 db 0F9h ; ·
.data:00404074                 db 0C3h ; +

Untuk mengubah shellcode tersebut menjadi instruksi, tekan tombol c pada keyboard, maka hasilnya akan seperti ini:

.data:00404068 loc_404068:                                      ; DATA XREF: start+5E^o
.data:00404068                 mov     edi, [esi]               ;
.data:0040406A                 mov     ecx, [esi+4]             ;
.data:0040406D
.data:0040406D loc_40406D:                                      ; CODE XREF: .data:00404072^j
.data:0040406D                 rol     byte ptr [edi+ecx-1], 5  ;
.data:00404072                 loop    loc_40406D               ;
.data:00404074                 retn                             ;

Bisa terlihat bahwa instruksi pada shellcode tersebut akan melakukan operasi ROL (rotate left) sebanyak 5 bit pada setiap byte yang terdapat pada parameter yang berada pada register EDI. Register ECX pada shellcode tersebut berisi jumlah pengulangan yang harus dilakukan (atau jumlah byte yang harus di-ROL). Data pada register EDI merupakan array data yang berada pada offset a2bBBb (0x00404040) berikut ini:

.data:00404040 byte_404040     db 32h                           ; DATA XREF: start+2C^o
.data:00404040                                                  ; start+32^o ...
.data:00404041                 db  62h ; b
.data:00404042                 db  0Ah
.data:00404043                 db  3Ah ; :
.data:00404044                 db 0DBh ; ¦
.data:00404045                 db  9Ah ; Ü
.data:00404046                 db  42h ; B
.data:00404047                 db  2Ah ; *
.data:00404048                 db  62h ; b
.data:00404049                 db  62h ; b
.data:0040404A                 db  1Ah
.data:0040404B                 db  7Ah ; z
.data:0040404C                 db  22h ; "
.data:0040404D                 db  2Ah ; *
.data:0040404E                 db  69h ; i
.data:0040404F                 db  4Ah ; J
.data:00404050                 db  9Ah ; Ü
.data:00404051                 db  72h ; r
.data:00404052                 db 0A2h ; ó
.data:00404053                 db  69h ; i
.data:00404054                 db  52h ; R
.data:00404055                 db 0AAh ; ¬
.data:00404056                 db  9Ah ; Ü
.data:00404057                 db 0A2h ; ó
.data:00404058                 db  69h ; i
.data:00404059                 db  32h ; 2
.data:0040405A                 db  7Ah ; z
.data:0040405B                 db  92h ; Æ
.data:0040405C                 db  69h ; i
.data:0040405D                 db  2Ah ; *
.data:0040405E                 db 0C2h ; -
.data:0040405F                 db  82h ; é
.data:00404060                 db  62h ; b
.data:00404061                 db  7Ah ; z
.data:00404062                 db  4Ah ; J
.data:00404063                 db 0A2h ; ó
.data:00404064                 db  9Ah ; Ü
.data:00404065                 db 0EBh ; d

Kita dapat mengubah array data tersebut menjadi flag dengan melakukan operasi ROL sebanyak 5 bit pada setiap elemen pada array tersebut. Berikut ini adalah script python yang dapat digunakan untuk menampilkan flag yang benar:

#!/usr/bin/env python
s = [0x32,0x62,0xa,0x3a,0xdb,0x9a,0x42,0x2a,0x62,0x62,0x1a,0x7a,0x22,0x2a,0x69,0x4a,0x9a,0x72,0xa2,0x69,0x52,0xaa,0x9a,0xa2,0x69,0x32,0x7a,0x92,0x69,0x2a,0xc2,0x82,0x62,0x7a,0x4a,0xa2,0x9a,0xeb]

# https://gist.github.com/c633/a7a5cde5ce1b679d3c0a
rol = lambda val, r_bits, max_bits=8: \
      (val << r_bits % max_bits) & (2**max_bits-1) | \
      ((val & (2**max_bits-1)) >> (max_bits-(r_bits % max_bits)))

print ''.join(chr(rol(c, 5)) for c in s)

Jika script tersebut dijalankan, maka hasilnya adalah FLAG{SHELLCODE-ISNT-JUST-FOR-EXPLOITS}. Itu adalah flag dari soal tersebut.

Penutup


Sekian tutorial singkat kali ini, semoga bermanfaat. Terima kasih kepada Tuhan Yang Maha Esa, dan Anda yang telah membaca tutorial ini.