type
status
date
slug
summary
tags
category
icon
password
week1~2
password
爆破
ret2libc
ezpwn
在这道题中尝试了自己手工写shellcode的机器码
同时,如果用asm模块进行写的话,举个例子如下
fmt1.0
这道题有点东西,我们首先看看反汇编:
发现只有一个printf输出,和一个栈溢出漏洞。
其实相对简单的能够意识到可以进行对返回地址的修改来将printf函数和read函数多次利用
问题就是出现在这里,我们在对返回地址进行修改的时候,大多数情况其实都是直接将main或者是vuln的一开始的函数覆盖掉原来的返回地址就好了,这里一般来说应该也是这个情况
但是问题出现了,当我们使用这个地址作为返回地址的时候,在第二轮进行printf函数的时候,会有这个情况:
► 0x7ffa60c81e98 movaps xmmword ptr [rsp + 0x40], xmm0
程序卡死在这个命令不动了
这个命令是用来干什么的呢?这里截取了相关解释:
这条指令是将xmm0
寄存器中的值移动到栈上某个位置(rsp + 0x40
)。movaps
指令要求目标地址必须是16字节对齐的,如果不是的话,它会引发SIGSEGV
(段错误)。
意思就是我们在使用printf开始的时候,我们的rsp指针一定要是16字节对齐的!
那我们应该怎么修改呢?
这里我修改了返回的地址,从一开始的vuln地址变成了舍去push rbp这个地址
因为对我第二遍使用的vuln函数来说其实有没有rbp都好像可以哈哈哈,这样就让rsp少了一次减去0x8的机会,让其保持在十六进制对齐,这样就可以进行printf的正常使用了!
完整代码如下:
别看这个原理很简单,但是了解这个东西真的耗费了好几个小时
white-canary
这个题我真的不该没做出来,这个题目正好打击的到我的一个弱项,那就是不喜欢看别的源代码函数,总以为是没用的初始化函数,但是其实并不是这个样子,有可能就是在这些函数中,就是存在着重要的突破口。
我们打开源代码文件
发现是存在向一个buf地址进行输入,同时存在一个栈溢出,还是一个gets栈溢出,没有长度限制
同时我们知道buf是一个有rwx权限的地方,证明可以在这个地方写shellcode
然后呢?然后我就没有思路了,在网上能查的关于canary泄露的,要不是有格式化字符串漏洞的泄露,要不是有子线程的爆破,但是我在这道题中都没用找到。
最后最后,才发现了有一个init函数,但是也没注意这个函数(因为我没看到调用),里面居然直接把canary算法写出来了!!!!
意思是我看的关于canary的都是无用功,唉
不过还是学习到了,要注意看除了main函数以外的其他函数是不是有突破空间。
而且事后其他师傅直接提点我:你看到gdb中这些函数的地址空间是有执行权限的就知道有着自己写的初始化函数了!
谢谢,我懂了
week 3
fmt2
这应该算是我第一次手搓格式化字符串的漏洞吧,就是还挺值得纪念的
主要是终于发现了,
fmtstr_payload
函数真的在x64的系统上不好用,一直都会报不少错,所以手搓还是挺好的。打开ida,发现是格式化漏洞
我们直接修改返回地址为
one_gadget
函数,同时注意,因为one_gadget
函数也是在libc中的,所以也不至于直接全部改,改几个字节就好了why_not_puts
ez_fullprotection
自己想了好久做出来的题,还是感觉不一样,好爽哈哈哈哈
由题意,所有防御皆开启
再看看ida
进入game()
我们注意到v1这里是标了亮黄色的,这代表v1可能没有被赋值
我们通过gdb调试的话也可以看出:
我们进行了scanf之后,局部变量v1并没有被赋值,所以这就泄露了函数的地址,我们可以就此绕过PIE(但是为啥scanf没能赋值,我也没看懂,希望到时候的WP有写吧)
官方的wp是这样说的,它解释了关于scanf的一个性质:
scanf有个特性,当我们输⼊⾮法数据时,⽐如我们这⾥输⼊⾮数字,它不会覆盖原本参数的所在地址上的数据,从⽽利⽤后⾯的格式化字符串来打印出栈上数据,从⽽ leak 出 pie
意思就是如果我们输入的和scanf想要的不一样,它就不会改内存,所以内存里面的值就是原来的值
然后进入
发现新线程的函数中存在gets函数,明显栈溢出,但是我们知道此时这个子线程存在canary
经过网上的资料查询,发现是TLS劫持攻击:
原理:
TLS(Thread-Local Storage)劫持攻击是一种针对应用程序的攻击方法,它利用线程本地存储的机制来实施恶意活动。线程本地存储是一种允许数据在多个线程之间隔离的存储机制,每个线程都有自己的数据副本,常用于存储每个线程的用户会话、状态或配置。在TLS劫持攻击中,攻击者通过获取对目标进程足够的访问权限,然后修改TLS数据结构中的特定值,例如通过指针重定向、代码注入或数据篡改。
按照我的理解就是,开辟线程的时候,线程本地存储会将诸多相关的数据进行一个备份,放在这个线程内存高地址的地方。canary也是一样,这样线程就是直接对TLS中的canary副本进行对比,所以当我们进行比较大一点的栈溢出的时候,就可以进行覆盖,将其修改。这样在函数验证的时候就可以通过。
所以这个题就转化成了进行很大的栈溢出,看看其offset是多少。
我们可以用canary命令先在gdbdbg中看看canary大致在哪,然后自己对比
爆破脚本:
得到大概爆破是在0x870左右,我们在这个附近都行,只要超过了0x870就行
然后就是常规的ROP链操作了,这里用栈迁移比较方便,毕竟我也不知道泄露libc地址后该返回到哪里,也不知道返回到的地方有没有什么其他的限制,所以在bss+0x300的地址上先写个ROP链,再迁移过去就行
EVA
这个题是后面和T1d师傅讨论出来的,或者说是T1d师傅交给我了这个思路
这个思路应该是个非预期
这个思路就是:直接通过修改
__stack_chk_fail
函数的got表来绕过canary真的很厉害这个思路,感觉可以用于很多地方,只要在这个二进制文件保持着partial RELRO的程度,就可以尝试着修改
__stack_chk_fail
来进行修改,把这个函数的got表随便指向一个ret指令,就可以进行绕过canary的检查,把__stack_chk_fail
函数变成一个空函数我们查看源代码
可以看出,当我们选择‘2’后,可以修改rbp以及之后的0x10字节,也就是rbp和return地址
修改rbp就可以修改很多main函数之中调用的函数
可以看到从这个地方,改rbp的值来进行修改read函数覆盖的地方
还有write函数也可以被修改
所以可以通过先选2,然后发送
将rbp修改到这里
这样就可以泄漏libc基地址
泄漏完了之后到达重新选择1和2
选择1可以重新覆写rbp
在这个地方我们直接进行输入:
达到这个效果
可以看出我们此时直接将got表中的
__stack_chk_fail
函数变成ret指令了。这样就可以直接绕过canary了
这里是exp.py
week 4
fmt3
没做出来,不过应该就是关于fmt和栈迁移之类的操作