锁定老帖子 主题:《深入理解计算机系统》 家庭作业3.38
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-24
题目 写道
/* 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,就需要以非正常的顺序执行代码。 有如下思路:
我是以第一个思路来解题的,需要明确这些语句和代码必须利用存储在 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这个数据,经过反复测试是不变化的,不过大家同样可以通过调试来获取。
上面是一个完整的调试运行并最终出现结果的过程,在认真分析了思路之后很容易达到目的。在这里大家可以看到:从内存中读出的数据是要逆序排列的,而我们键入的机器码确实正常序排列的 。
参考文献 写道
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 4013 次