《深入理解计算机系统》 家庭作业3.38

题目 写道
/* 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;
}
 题目的要求是,在getbuf函数中也许“显然”地会返回1,通过输入一个数据使这个函数返回0xdeadbeef,就是在test函数中地printf中打印地是0xdeadbeef.

经过了漫长的调试和学习,现在基本将这个题目搞定了。很激动啊,第一次学习溢出攻击第一次深入程序底部去做调整。不过需要注意:具体解题中涉及到的数据分布、汇编码和条件码和机器码和编译器、实际系统环境有关。

我的系统环境 写道
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu3)

GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu". 

首先是下载源代码,并做开始实验前的基本工作。下载 -->编译 -->反编译 -->查看反编译代码。


现在我们需要认真的查看汇编代码来看看如何达到目的。

 

汇编代码 写道

bomb: file format elf32-i386

Disassembly of section .init:

0804832c <_init>:
804832c: 55 push %ebp
804832d: 89 e5 mov %esp,%ebp
804832f: 53 push %ebx
8048330: 83 ec 04 sub $0x4,%esp
8048333: e8 00 00 00 00 call 8048338 <_init+0xc>
8048338: 5b pop %ebx
8048339: 81 c3 ac 14 00 00 add $0x14ac,%ebx
804833f: 8b 93 fc ff ff ff mov -0x4(%ebx),%edx
8048345: 85 d2 test %edx,%edx
8048347: 74 05 je 804834e <_init+0x22>
8048349: e8 2e 00 00 00 call 804837c <__gmon_start__@plt>
804834e: e8 dd 00 00 00 call 8048430 <frame_dummy>
8048353: e8 28 03 00 00 call 8048680 <__do_global_ctors_aux>
8048358: 58 pop %eax
8048359: 5b pop %ebx
804835a: c9 leave
804835b: c3 ret
Disassembly of section .plt:

0804835c <getchar@plt-0x10>:
804835c: ff 35 e8 97 04 08 pushl 0x80497e8
8048362: ff 25 ec 97 04 08 jmp *0x80497ec
8048368: 00 00 add %al,(%eax)
...

0804836c <getchar@plt>:
804836c: ff 25 f0 97 04 08 jmp *0x80497f0
8048372: 68 00 00 00 00 push $0x0
8048377: e9 e0 ff ff ff jmp 804835c <_init+0x30>

0804837c <__gmon_start__@plt>:
804837c: ff 25 f4 97 04 08 jmp *0x80497f4
8048382: 68 08 00 00 00 push $0x8
8048387: e9 d0 ff ff ff jmp 804835c <_init+0x30>

0804838c <__libc_start_main@plt>:
804838c: ff 25 f8 97 04 08 jmp *0x80497f8
8048392: 68 10 00 00 00 push $0x10
8048397: e9 c0 ff ff ff jmp 804835c <_init+0x30>

0804839c <__ctype_b_loc@plt>:
804839c: ff 25 fc 97 04 08 jmp *0x80497fc
80483a2: 68 18 00 00 00 push $0x18
80483a7: e9 b0 ff ff ff jmp 804835c <_init+0x30>

080483ac <printf@plt>:
80483ac: ff 25 00 98 04 08 jmp *0x8049800
80483b2: 68 20 00 00 00 push $0x20
80483b7: e9 a0 ff ff ff jmp 804835c <_init+0x30>

080483bc <__stack_chk_fail@plt>:
80483bc: ff 25 04 98 04 08 jmp *0x8049804
80483c2: 68 28 00 00 00 push $0x28
80483c7: e9 90 ff ff ff jmp 804835c <_init+0x30>
Disassembly of section .text:

080483d0 <_start>:
80483d0: 31 ed xor %ebp,%ebp
80483d2: 5e pop %esi
80483d3: 89 e1 mov %esp,%ecx
80483d5: 83 e4 f0 and $0xfffffff0,%esp
80483d8: 50 push %eax
80483d9: 54 push %esp
80483da: 52 push %edx
80483db: 68 10 86 04 08 push $0x8048610
80483e0: 68 20 86 04 08 push $0x8048620
80483e5: 51 push %ecx
80483e6: 56 push %esi
80483e7: 68 87 85 04 08 push $0x8048587
80483ec: e8 9b ff ff ff call 804838c <__libc_start_main@plt>
80483f1: f4 hlt
80483f2: 90 nop
80483f3: 90 nop
80483f4: 90 nop
80483f5: 90 nop
80483f6: 90 nop
80483f7: 90 nop
80483f8: 90 nop
80483f9: 90 nop
80483fa: 90 nop
80483fb: 90 nop
80483fc: 90 nop
80483fd: 90 nop
80483fe: 90 nop
80483ff: 90 nop

08048400 <__do_global_dtors_aux>:
8048400: 55 push %ebp
8048401: 89 e5 mov %esp,%ebp
8048403: 83 ec 08 sub $0x8,%esp
8048406: 80 3d 14 98 04 08 00 cmpb $0x0,0x8049814
804840d: 74 0c je 804841b <__do_global_dtors_aux+0x1b>
804840f: eb 1c jmp 804842d <__do_global_dtors_aux+0x2d>
8048411: 83 c0 04 add $0x4,%eax
8048414: a3 10 98 04 08 mov %eax,0x8049810
8048419: ff d2 call *%edx
804841b: a1 10 98 04 08 mov 0x8049810,%eax
8048420: 8b 10 mov (%eax),%edx
8048422: 85 d2 test %edx,%edx
8048424: 75 eb jne 8048411 <__do_global_dtors_aux+0x11>
8048426: c6 05 14 98 04 08 01 movb $0x1,0x8049814
804842d: c9 leave
804842e: c3 ret
804842f: 90 nop

08048430 <frame_dummy>:
8048430: 55 push %ebp
8048431: 89 e5 mov %esp,%ebp
8048433: 83 ec 08 sub $0x8,%esp
8048436: a1 0c 97 04 08 mov 0x804970c,%eax
804843b: 85 c0 test %eax,%eax
804843d: 74 12 je 8048451 <frame_dummy+0x21>
804843f: b8 00 00 00 00 mov $0x0,%eax
8048444: 85 c0 test %eax,%eax
8048446: 74 09 je 8048451 <frame_dummy+0x21>
8048448: c7 04 24 0c 97 04 08 movl $0x804970c,(%esp)
804844f: ff d0 call *%eax
8048451: c9 leave
8048452: c3 ret
8048453: 90 nop

08048454 <getxs>:
8048454: 55 push %ebp
8048455: 89 e5 mov %esp,%ebp
8048457: 83 ec 28 sub $0x28,%esp
804845a: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%ebp)
8048461: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
8048468: 8b 45 08 mov 0x8(%ebp),%eax
804846b: 89 45 f0 mov %eax,-0x10(%ebp)
804846e: e9 8a 00 00 00 jmp 80484fd <getxs+0xa9>
8048473: e8 24 ff ff ff call 804839c <__ctype_b_loc@plt>
8048478: 8b 10 mov (%eax),%edx
804847a: 8b 45 fc mov -0x4(%ebp),%eax
804847d: 01 c0 add %eax,%eax
804847f: 8d 04 02 lea (%edx,%eax,1),%eax
8048482: 0f b7 00 movzwl (%eax),%eax
8048485: 0f b7 c0 movzwl %ax,%eax
8048488: 25 00 10 00 00 and $0x1000,%eax
804848d: 85 c0 test %eax,%eax
804848f: 74 6c je 80484fd <getxs+0xa9>
8048491: 83 7d fc 2f cmpl $0x2f,-0x4(%ebp)
8048495: 7e 11 jle 80484a8 <getxs+0x54>
8048497: 83 7d fc 39 cmpl $0x39,-0x4(%ebp)
804849b: 7f 0b jg 80484a8 <getxs+0x54>
804849d: 8b 45 fc mov -0x4(%ebp),%eax
80484a0: 83 e8 30 sub $0x30,%eax
80484a3: 89 45 ec mov %eax,-0x14(%ebp)
80484a6: eb 20 jmp 80484c8 <getxs+0x74>
80484a8: 83 7d fc 40 cmpl $0x40,-0x4(%ebp)
80484ac: 7e 11 jle 80484bf <getxs+0x6b>
80484ae: 83 7d fc 46 cmpl $0x46,-0x4(%ebp)
80484b2: 7f 0b jg 80484bf <getxs+0x6b>
80484b4: 8b 45 fc mov -0x4(%ebp),%eax
80484b7: 83 e8 37 sub $0x37,%eax
80484ba: 89 45 ec mov %eax,-0x14(%ebp)
80484bd: eb 09 jmp 80484c8 <getxs+0x74>
80484bf: 8b 45 fc mov -0x4(%ebp),%eax
80484c2: 83 e8 57 sub $0x57,%eax
80484c5: 89 45 ec mov %eax,-0x14(%ebp)
80484c8: 83 7d f8 00 cmpl $0x0,-0x8(%ebp)
80484cc: 74 0f je 80484dd <getxs+0x89>
80484ce: 8b 45 ec mov -0x14(%ebp),%eax
80484d1: 89 45 f4 mov %eax,-0xc(%ebp)
80484d4: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
80484db: eb 20 jmp 80484fd <getxs+0xa9>
80484dd: 8b 45 f4 mov -0xc(%ebp),%eax
80484e0: c1 e0 04 shl $0x4,%eax
80484e3: 89 c2 mov %eax,%edx
80484e5: 8b 45 ec mov -0x14(%ebp),%eax
80484e8: 8d 04 02 lea (%edx,%eax,1),%eax
80484eb: 89 c2 mov %eax,%edx
80484ed: 8b 45 f0 mov -0x10(%ebp),%eax
80484f0: 88 10 mov %dl,(%eax)
80484f2: 83 45 f0 01 addl $0x1,-0x10(%ebp)
80484f6: c7 45 f8 01 00 00 00 movl $0x1,-0x8(%ebp)
80484fd: e8 6a fe ff ff call 804836c <getchar@plt>
8048502: 89 45 fc mov %eax,-0x4(%ebp)
8048505: 83 7d fc ff cmpl $0xffffffff,-0x4(%ebp)
8048509: 74 0a je 8048515 <getxs+0xc1>
804850b: 83 7d fc 0a cmpl $0xa,-0x4(%ebp)
804850f: 0f 85 5e ff ff ff jne 8048473 <getxs+0x1f>
8048515: 8b 45 f0 mov -0x10(%ebp),%eax
8048518: c6 00 00 movb $0x0,(%eax)
804851b: 83 45 f0 01 addl $0x1,-0x10(%ebp)
804851f: 8b 45 08 mov 0x8(%ebp),%eax
8048522: c9 leave
8048523: c3 ret

08048524 <getbuf>:
8048524: 55 push %ebp
8048525: 89 e5 mov %esp,%ebp
8048527: 83 ec 18 sub $0x18,%esp
804852a: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048530: 89 45 fc mov %eax,-0x4(%ebp)
8048533: 31 c0 xor %eax,%eax
8048535: 8d 45 f0 lea -0x10(%ebp),%eax
8048538: 89 04 24 mov %eax,(%esp)
804853b: e8 14 ff ff ff call 8048454 <getxs>
8048540: b8 01 00 00 00 mov $0x1,%eax
8048545: 8b 55 fc mov -0x4(%ebp),%edx
8048548: 65 33 15 14 00 00 00 xor %gs:0x14,%edx
804854f: 74 05 je 8048556 <getbuf+0x32>
8048551: e8 66 fe ff ff call 80483bc <__stack_chk_fail@plt>
8048556: c9 leave
8048557: c3 ret

08048558 <test>:
8048558: 55 push %ebp
8048559: 89 e5 mov %esp,%ebp
804855b: 83 ec 18 sub $0x18,%esp
804855e: c7 04 24 d0 86 04 08 movl $0x80486d0,(%esp)
8048565: e8 42 fe ff ff call 80483ac <printf@plt>
804856a: e8 b5 ff ff ff call 8048524 <getbuf>
804856f: 89 45 fc mov %eax,-0x4(%ebp)
8048572: 8b 45 fc mov -0x4(%ebp),%eax
8048575: 89 44 24 04 mov %eax,0x4(%esp)
8048579: c7 04 24 e1 86 04 08 movl $0x80486e1,(%esp)
8048580: e8 27 fe ff ff call 80483ac <printf@plt>
8048585: c9 leave
8048586: c3 ret

08048587 <main>:
8048587: 8d 4c 24 04 lea 0x4(%esp),%ecx
804858b: 83 e4 f0 and $0xfffffff0,%esp
804858e: ff 71 fc pushl -0x4(%ecx)
8048591: 55 push %ebp
8048592: 89 e5 mov %esp,%ebp
8048594: 51 push %ecx
8048595: 83 ec 54 sub $0x54,%esp
8048598: 65 a1 14 00 00 00 mov %gs:0x14,%eax
804859e: 89 45 f8 mov %eax,-0x8(%ebp)
80485a1: 31 c0 xor %eax,%eax
80485a3: 8d 45 b0 lea -0x50(%ebp),%eax
80485a6: 25 ff 0f 00 00 and $0xfff,%eax
80485ab: 89 45 f4 mov %eax,-0xc(%ebp)
80485ae: 8b 45 f4 mov -0xc(%ebp),%eax
80485b1: 83 c0 0f add $0xf,%eax
80485b4: 83 c0 0f add $0xf,%eax
80485b7: c1 e8 04 shr $0x4,%eax
80485ba: c1 e0 04 shl $0x4,%eax
80485bd: 29 c4 sub %eax,%esp
80485bf: 89 65 a8 mov %esp,-0x58(%ebp)
80485c2: 8b 45 a8 mov -0x58(%ebp),%eax
80485c5: 83 c0 0f add $0xf,%eax
80485c8: c1 e8 04 shr $0x4,%eax
80485cb: c1 e0 04 shl $0x4,%eax
80485ce: 89 45 a8 mov %eax,-0x58(%ebp)
80485d1: 8b 55 a8 mov -0x58(%ebp),%edx
80485d4: 89 55 f0 mov %edx,-0x10(%ebp)
80485d7: 8b 45 f0 mov -0x10(%ebp),%eax
80485da: c7 00 00 00 00 00 movl $0x0,(%eax)
80485e0: e8 73 ff ff ff call 8048558 <test>
80485e5: b8 00 00 00 00 mov $0x0,%eax
80485ea: 8b 55 f8 mov -0x8(%ebp),%edx
80485ed: 65 33 15 14 00 00 00 xor %gs:0x14,%edx
80485f4: 74 05 je 80485fb <main+0x74>
80485f6: e8 c1 fd ff ff call 80483bc <__stack_chk_fail@plt>
80485fb: 8b 4d fc mov -0x4(%ebp),%ecx
80485fe: c9 leave
80485ff: 8d 61 fc lea -0x4(%ecx),%esp
8048602: c3 ret
8048603: 90 nop
8048604: 90 nop
8048605: 90 nop
8048606: 90 nop
8048607: 90 nop
8048608: 90 nop
8048609: 90 nop
804860a: 90 nop
804860b: 90 nop
804860c: 90 nop
804860d: 90 nop
804860e: 90 nop
804860f: 90 nop

08048610 <__libc_csu_fini>:
8048610: 55 push %ebp
8048611: 89 e5 mov %esp,%ebp
8048613: 5d pop %ebp
8048614: c3 ret
8048615: 8d 74 26 00 lea 0x0(%esi),%esi
8048619: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi

08048620 <__libc_csu_init>:
8048620: 55 push %ebp
8048621: 89 e5 mov %esp,%ebp
8048623: 57 push %edi
8048624: 56 push %esi
8048625: 53 push %ebx
8048626: e8 4f 00 00 00 call 804867a <__i686.get_pc_thunk.bx>
804862b: 81 c3 b9 11 00 00 add $0x11b9,%ebx
8048631: 83 ec 0c sub $0xc,%esp
8048634: e8 f3 fc ff ff call 804832c <_init>
8048639: 8d bb 18 ff ff ff lea -0xe8(%ebx),%edi
804863f: 8d 83 18 ff ff ff lea -0xe8(%ebx),%eax
8048645: 29 c7 sub %eax,%edi
8048647: c1 ff 02 sar $0x2,%edi
804864a: 85 ff test %edi,%edi
804864c: 74 24 je 8048672 <__libc_csu_init+0x52>
804864e: 31 f6 xor %esi,%esi
8048650: 8b 45 10 mov 0x10(%ebp),%eax
8048653: 89 44 24 08 mov %eax,0x8(%esp)
8048657: 8b 45 0c mov 0xc(%ebp),%eax
804865a: 89 44 24 04 mov %eax,0x4(%esp)
804865e: 8b 45 08 mov 0x8(%ebp),%eax
8048661: 89 04 24 mov %eax,(%esp)
8048664: ff 94 b3 18 ff ff ff call *-0xe8(%ebx,%esi,4)
804866b: 83 c6 01 add $0x1,%esi
804866e: 39 f7 cmp %esi,%edi
8048670: 75 de jne 8048650 <__libc_csu_init+0x30>
8048672: 83 c4 0c add $0xc,%esp
8048675: 5b pop %ebx
8048676: 5e pop %esi
8048677: 5f pop %edi
8048678: 5d pop %ebp
8048679: c3 ret

0804867a <__i686.get_pc_thunk.bx>:
804867a: 8b 1c 24 mov (%esp),%ebx
804867d: c3 ret
804867e: 90 nop
804867f: 90 nop

08048680 <__do_global_ctors_aux>:
8048680: 55 push %ebp
8048681: 89 e5 mov %esp,%ebp
8048683: 53 push %ebx
8048684: 83 ec 04 sub $0x4,%esp
8048687: a1 fc 96 04 08 mov 0x80496fc,%eax
804868c: 83 f8 ff cmp $0xffffffff,%eax
804868f: 74 12 je 80486a3 <__do_global_ctors_aux+0x23>
8048691: 31 db xor %ebx,%ebx
8048693: ff d0 call *%eax
8048695: 8b 83 f8 96 04 08 mov 0x80496f8(%ebx),%eax
804869b: 83 eb 04 sub $0x4,%ebx
804869e: 83 f8 ff cmp $0xffffffff,%eax
80486a1: 75 f0 jne 8048693 <__do_global_ctors_aux+0x13>
80486a3: 83 c4 04 add $0x4,%esp
80486a6: 5b pop %ebx
80486a7: 5d pop %ebp
80486a8: c3 ret
80486a9: 90 nop
80486aa: 90 nop
80486ab: 90 nop
Disassembly of section .fini:

080486ac <_fini>:
80486ac: 55 push %ebp
80486ad: 89 e5 mov %esp,%ebp
80486af: 53 push %ebx
80486b0: 83 ec 04 sub $0x4,%esp
80486b3: e8 00 00 00 00 call 80486b8 <_fini+0xc>
80486b8: 5b pop %ebx
80486b9: 81 c3 2c 11 00 00 add $0x112c,%ebx
80486bf: e8 3c fd ff ff call 8048400 <__do_global_dtors_aux>
80486c4: 59 pop %ecx
80486c5: 5b pop %ebx
80486c6: c9 leave
80486c7: c3 ret

 重要的汇编代码:


从汇编代码中,我们容易发现: test调用了 getbuf方法,然后在 getbuf里面给 %eax赋值为 1,并返回并将 %eax的值传递给 val,最后将 val值以 16进制打印出来。这个结果不论如何就是 0x1.

从上面的分析我们可以看出,如果不改变程序逻辑的话,不论怎样都是会以 0x1的形式打印结果的。如果要打印 0xdeadbeef,就需要以非正常的顺序执行代码。

有如下思路:

  1. 在返回到 0x0804856f之前给 %eax的最后赋值为 0xdeadbeef

  2. 直接修改存储在 memory中的 val值,然后跳过 val的赋值语句直接打印结果;

  3. 等等。

我是以第一个思路来解题的,需要明确这些语句和代码必须利用存储在 buf中来达到目的。那么我们就需要考虑 buf的存储结构和与其相关的敏感数据位置:通过阅读汇编代码我们知道,虽然 buf长度为 12字节但是系统实际分配了 0x10 16个字节,然后在 buf %ebp之间插入了一个 %gs:0x14 4字节数据项。整体结构就成为:


 

从图的数据分布情况来看,我们可以大致了解到我们需要做的事情了。有余 getxs没有对字符串长度做判断,我们就可以通过加长输入的字符串来覆盖 buf上面的一些关键数据值。我们的主要目的是去修改“返回地址”,在修改做成中我们需要覆盖 %gs:0x14 %ebp。由于 %ebp涉及到 caller的帧地址,所以在修改时需要保证这个数据不被改变;至于那个 %gs:0x14是干什么的,我现在并不清楚,不过通过测试我发现如果它的数据发生变化就会报错,所以在修改时需要保证这个数据的完整性。

现在我们知道了需要去修改返回地址,那么我们需要返回到哪里、需要到那里去做什么呢?最开始已经说了,需要去修改 %eax的值,然后直接跳转到 0x0804856f。现在我先将需要做的事情的汇编代码和机器码写出来。

 

需要执行的汇编码 写道
mov $0xdeadbeef, %eax
mov $0x0804856f, %edx
jmp *%edx

至于机器码,你可以通过相同的编译器和反编译器来获得。

对应的机器码 写道
gcc –c show.s
objdump –d show.o
机器码 写道
show.o: file format elf32-i386
Disassembly of section .text:
00000000 <.text>:
0: b8 ef be ad de mov $0xdeadbeef,%eax
5: ba 6f 85 04 08 mov $0x804856f,%edx
a: ff e2 jmp *%edx

获得了这些基本的数据,那么就开始我们的溢出攻击设计吧!

前面生成的机器码刚好 12个字节,我们就将这些机器码放在 buf里面,然后在填补了不能修改的数据后,去修改返回地址到 buf的起始端。通过这样的修改,我们就引导程序到达了我们期望运行的代码段,在执行了我们的代码后有返回到正常的代码段中执行。整个流程是这样的,现在通过 gdb来实现这些操作。由于物理地址和虚拟地址的映射关系, buf的首地址、 %ebp的数据值都是变化的,需要在每次运行中去捕获。至于那个 %gs:0x14这个数据,经过反复测试是不变化的,不过大家同样可以通过调试来获取。

 

 

 


上面是一个完整的调试运行并最终出现结果的过程,在认真分析了思路之后很容易达到目的。在这里大家可以看到:从内存中读出的数据是要逆序排列的,而我们键入的机器码确实正常序排列的

 

 

参考文献 写道
 

 

 

 

 

你可能感兴趣的:(C++,c,虚拟机,linux,C#)