看汇编代码,主要存在三个函数main
、vuln
、read_flag
(自己定义的);
主要是创建一个string对象v7
,然后传到vuln
函数处理,在之后就是输出和析构对象
从vuln
函数不难看出会接收字符数组,然后将接受的赋值给字符串对象v7
,但是问题就出现在这个std::string::operator=
函数上
后门函数,不多讲
在调试过程中,发现了std::string::operator=
函数的调用过程。
给出他的汇编指令
可见它是先调用strlen
函数计算rsi
也就是用户输入的内容(PS:strlen
存在\x00
截断)。然后在进入_M_replace
函数,该函数会将先将用户输入的字符串长度与0xf
就行比较,如果大于就会创建一个堆来存储字符串;反之就会放在dst
地址中。
调用创建堆的过程如下,会调用一个_M_mutate
函数
1.前面铺垫了那么多,其实它是根据strlen
函数获取输入的长度,又由于strlen
存在\x00
截断,那么我们可以构造一个payload,在0-15字节之间填充一个\x00
截断,就可以造成长度小于等于15;然后将内容直接复制到dst
中而不是堆中。
2.由于输入也没有限制长度,所以可以溢出到dst
修改他的指针值为stack_chk_fail@got
,再把最开始的8字节修改为read_flag
地址,那么就会把劫持stack_chk_fail
到后门函数上,获取flag
exp在下面自取
之后又在网上找了一个C++学习网站,感觉还行
https://legacy.cplusplus.com/reference/string/basic_string/
u24@u24-VMware-Virtual-Platform:~/桌面
/sictf
$ pwn checksec overflow
[!] Could not populate PLT: No module named
'distutils'
[*]
'/home/u24/桌面/sictf/overflow'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
u24@u24-VMware-Virtual-Platform:~/桌面
/sictf
$ pwn checksec overflow
[!] Could not populate PLT: No module named
'distutils'
[*]
'/home/u24/桌面/sictf/overflow'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
__int64
__fastcall main(
int
a1,
char
**a2,
char
**a3)
{
__int64
v4;
__int64
v5;
__int64
v6;
_BYTE v7[32];
unsigned
__int64
v8;
v8 = __readfsqword(0x28u);
std::string::basic_string(v7, a2, a3);
vuln((
__int64
)v7);
v6 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"You said: "
);
v5 = std::operator<<<
char
>(v6, v7);
std::operator<<<std::char_traits<
char
>>(v5,
"\n"
);
v4 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Bye~"
);
std::operator<<<std::char_traits<
char
>>(v4,
"\n"
);
std::string::~string(v7);
return
0LL;
}
__int64
__fastcall main(
int
a1,
char
**a2,
char
**a3)
{
__int64
v4;
__int64
v5;
__int64
v6;
_BYTE v7[32];
unsigned
__int64
v8;
v8 = __readfsqword(0x28u);
std::string::basic_string(v7, a2, a3);
vuln((
__int64
)v7);
v6 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"You said: "
);
v5 = std::operator<<<
char
>(v6, v7);
std::operator<<<std::char_traits<
char
>>(v5,
"\n"
);
v4 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Bye~"
);
std::operator<<<std::char_traits<
char
>>(v4,
"\n"
);
std::string::~string(v7);
return
0LL;
}
unsigned
__int64
__fastcall sub_4012C0(
__int64
a1)
{
__int64
v1;
char
v3[72];
unsigned
__int64
v4;
v4 = __readfsqword(0x28u);
v1 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"What do you want to say?"
);
std::operator<<<std::char_traits<
char
>>(v1,
"\n"
);
std::operator>><
char
,std::char_traits<
char
>>(&std::cin);
std::string::operator=(a1, v3);
return
__readfsqword(0x28u);
}
unsigned
__int64
__fastcall sub_4012C0(
__int64
a1)
{
__int64
v1;
char
v3[72];
unsigned
__int64
v4;
v4 = __readfsqword(0x28u);
v1 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"What do you want to say?"
);
std::operator<<<std::char_traits<
char
>>(v1,
"\n"
);
std::operator>><
char
,std::char_traits<
char
>>(&std::cin);
std::string::operator=(a1, v3);
return
__readfsqword(0x28u);
}
unsigned
__int64
read_flag()
{
__int64
v0;
__int64
v1;
__int64
v2;
__int64
v3;
FILE
*stream;
char
s[72];
unsigned
__int64
v7;
v7 = __readfsqword(0x28u);
v0 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Success!"
);
std::operator<<<std::char_traits<
char
>>(v0,
"\n"
);
stream =
fopen
(
"flag"
,
"r"
);
if
( stream )
{
fgets
(s, 64, stream);
v2 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Flag: "
);
v3 = std::operator<<<std::char_traits<
char
>>(v2, s);
std::operator<<<std::char_traits<
char
>>(v3,
"\n"
);
}
else
{
v1 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Flag is missing. Please contact an admin."
);
std::operator<<<std::char_traits<
char
>>(v1,
"\n"
);
}
return
__readfsqword(0x28u);
}
unsigned
__int64
read_flag()
{
__int64
v0;
__int64
v1;
__int64
v2;
__int64
v3;
FILE
*stream;
char
s[72];
unsigned
__int64
v7;
v7 = __readfsqword(0x28u);
v0 = std::operator<<<std::char_traits<
char
>>(&std::cout,
"Success!"
);
std::operator<<<std::char_traits<
char
>>(v0,
"\n"
);
stream =
fopen
(
"flag"
,
"r"
);
if
( stream )
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课