Patz's Algorithm Journey

The way we hack

2008年12月11日 #

一个小小的溢出试验

  今天在学习溢出时写了个简单程序,源代码如下。
 1#include <stdio.h>
 2#include <stdlib.h>
 3
 4int foo_normal(char*);
 5int foo_abnormal(char*);
 6
 7int main()
 8{
 9    int i;
10    char szTmp[] = {
11        0x310x310x310x31
12        0x320x320x320x32
13        0x330x330x330x33,
14        0x000x400x130x45,
15        
16        0x310x310x310x31
17        0x320x320x320x32
18        0x330x330x330x33,
19        0x4e0x130x400x00
20        }
;
21        
22    i = 0;
23    
24    if (i == 0)
25        foo_normal(szTmp);
26    else
27        foo_abnormal(szTmp);
28        
29    return(0);
30}
    
31
32
33int foo_normal(char* _sz)
34{
35    char buffer[5];
36    memcpy(buffer, _sz, sizeof(char)*32);
37    printf("Application terminates normally.\n");
38    return(0);
39}
    
40int foo_abnormal(char* _sz)
41{
42    char buffer[5];
43    memcpy(buffer, _sz, sizeof(char)*3);
44    printf("You should have never seen this.\n");
45    return (0);
46}
    

  打算通过foo_normal中的memcpy函数覆盖栈中的EIP,改为调用foo_abnormal处的语句,来达到溢出攻击的目的。按照正常情况看,在foo_normal中,栈里有4字节的CS和4字节的EIP,然后是5字节的字符串数组——对齐后是8字节,还有4字节的EBP。所以当往buffer中复制12字节数据就可以覆盖掉EIP而达到溢出的目的。但实际上使用32字节的数据覆盖buffer及其后的数据,才把EIP给照顾到。使用OllyDBG跟了一下:
 1 004013F2  /$  55            push    ebp
 2 004013F3  |.  89E5          mov     ebp, esp
 3 004013F5  |.  83EC 28       sub     esp, 28
 4 004013F8  |.  C74424 08 050>mov     dword ptr [esp+8], 5             ; ||
 5 00401400  |.  8B45 08       mov     eax, dword ptr [ebp+8]           ; ||
 6 00401403  |.  894424 04     mov     dword ptr [esp+4], eax           ; ||
 7 00401407  |.  8D45 E8       lea     eax, dword ptr [ebp-18]          ; ||
 8 0040140A  |.  890424        mov     dword ptr [esp], eax             ; ||
 9 0040140D  |.  E8 FE050000   call    <jmp.&msvcrt.memcpy>             ; |\memcpy
10 00401412  |.  C70424 D01340>mov     dword ptr [esp], 004013D0        ; |ASCII "Application terminates normally.",LF
11 00401419  |.  E8 EA050000   call    <jmp.&msvcrt.printf>             ; \printf
12 0040141E  |.  B8 00000000   mov     eax, 0
13 00401423  |.  C9            leave
14 00401424  \.  C3            retn

  发现在进入函数的时候申请了28个字节的空间——除去12字节给memcpy的参数,比预想的多了6字节。看来使用的3.3.1版本的gcc是16字节对齐的。

  ……让我抓狂了一个小时。

posted @ 2008-12-11 22:55 patz 阅读(199) | 评论 (0)编辑 收藏

2008年9月9日 #

如何在命令行下读入一行输入

        写命令行下的程序时,总需要一次读入一行输入后再做处理。如果用getline()的话,缓冲区char*的大小是事先定好的。虽然把缓冲区设大点也能完成任务,不过总让人觉得不舒服。最简单的办法是用cin.get(),自动读到(但不包括)'\n'。再要读接下来一整行时加上一个cin.ignore()把未读入的'\n'给忽略就行了。

        cin.get()详细说明见这里,其原型如下:

1int get();
2istream& get ( char& c );
3istream& get ( char* s, streamsize n );
4istream& get ( char* s, streamsize n, char delim );
5istream& get ( streambuf& sb);
6istream& get ( streambuf& sb, char delim ); 

posted @ 2008-09-09 23:53 patz 阅读(768) | 评论 (1)编辑 收藏

仅列出标题