需要帮助拆解

时间:2011-09-05 22:03:23

标签: c assembly

我需要你的帮助。这是我的程序的源代码。我需要了解score1,score2,score3和score4函数正在进行哪些操作。

    1       #include <stdio.h>
    2       #include <string.h>
    3       #include <stdlib.h>
    4       #include <sys/types.h>
    5       #include <sys/stat.h>
    6       #include <pwd.h>
    7       #include <unistd.h>
    8
    9       #include "score.h"
    10
    (gdb)
    11      int main(int argc, char *argv[])
    12      {
    13        int i, j, k, l, s;
    14        struct passwd *pw;
    15        char cmd[1024];
    16
    17        /* Make sure that we have exactly 5 arguments: the name of the executable, and 4 numbers */
    18        if (argc != 5) {
    19          printf("Usage: %s i j k l\n   where i,j,k,l are integers.\n   Try to get as high a score as you can.\n", argv[0]);
    20          exit(8);
    (gdb)
    21        }
    22
    23        initialize();
    24
    25        /* Convert the inputs to ints */
    26        i = atoi(argv[1]);
    27        j = atoi(argv[2]);
    28        k = atoi(argv[3]);
    29        l = atoi(argv[4]);
    30
    (gdb)
    31        printf("You entered the integers %d, %d, %d, and %d.\n", i, j, k, l);
    32        s = score1(i) + score2(j) + score3(k) + score4(l);
    33
    34        printf("Your score is %d.\n", s);
    35        if (s > 0) {
    36          pw = getpwuid(getuid());
    37          
    38          printf("Thank you!\n");
    40          system(cmd);

我已经开始反汇编代码如下:

(gdb) disas score1
Dump of assembler code for function score1:
0x080488b0 <score1+0>:  push   %ebp
0x080488b1 <score1+1>:  mov    %esp,%ebp
0x080488b3 <score1+3>:  cmpl   $0xe1e4,0x8(%ebp)
0x080488ba <score1+10>: setne  %al
0x080488bd <score1+13>: movzbl %al,%eax
0x080488c0 <score1+16>: sub    $0x1,%eax
0x080488c3 <score1+19>: and    $0xa,%eax
0x080488c6 <score1+22>: pop    %ebp
0x080488c7 <score1+23>: ret

(gdb) disas score2
Dump of assembler code for function score2:
0x080488c8 <score2+0>:  push   %ebp
0x080488c9 <score2+1>:  mov    %esp,%ebp
0x080488cb <score2+3>:  mov    0x8049f88,%eax
0x080488d0 <score2+8>:  sub    $0x2,%eax
0x080488d3 <score2+11>: mov    %eax,0x8049f88
0x080488d8 <score2+16>: cmp    0x8(%ebp),%eax
0x080488db <score2+19>: setne  %al
0x080488de <score2+22>: movzbl %al,%eax
0x080488e1 <score2+25>: sub    $0x1,%eax
0x080488e4 <score2+28>: and    $0xa,%eax
0x080488e7 <score2+31>: pop    %ebp
0x080488e8 <score2+32>: ret

 (gdb) disas score3
    Dump of assembler code for function score3:
    0x080488e9 <score3+0>:  push   %ebp
    0x080488ea <score3+1>:  mov    %esp,%ebp
    0x080488ec <score3+3>:  mov    0x8(%ebp),%eax
    0x080488ef <score3+6>:  and    $0xf,%eax
    0x080488f2 <score3+9>:  mov    0x8048e00(,%eax,4),%eax
    0x080488f9 <score3+16>: pop    %ebp
    0x080488fa <score3+17>: ret

(gdb) disas score4
Dump of assembler code for function score4:
0x080488fb <score4+0>:  push   %ebp
0x080488fc <score4+1>:  mov    %esp,%ebp
0x080488fe <score4+3>:  push   %ebx
0x080488ff <score4+4>:  mov    0x8(%ebp),%eax
0x08048902 <score4+7>:  movzwl %ax,%edx
0x08048905 <score4+10>: mov    %eax,%ecx
0x08048907 <score4+12>: shr    $0x10,%ecx
0x0804890a <score4+15>: lea    0x0(,%edx,8),%eax
0x08048911 <score4+22>: sub    %edx,%eax
0x08048913 <score4+24>: cmp    %ecx,%eax
0x08048915 <score4+26>: jne    0x8048920 <score4+37>
0x08048917 <score4+28>: mov    $0x8000ffff,%ebx
0x0804891c <score4+33>: test   %edx,%ecx
0x0804891e <score4+35>: jne    0x8048940 <score4+69>
0x08048920 <score4+37>: mov    %ecx,%eax
0x08048922 <score4+39>: xor    %edx,%eax
0x08048924 <score4+41>: cmp    $0xf00f,%eax
0x08048929 <score4+46>: jne    0x804893b <score4+64>
0x0804892b <score4+48>: mov    %ecx,%eax
0x0804892d <score4+50>: or     %edx,%eax
0x0804892f <score4+52>: mov    $0xa,%ebx
0x08048934 <score4+57>: cmp    $0xf42f,%eax
---Type <return> to continue, or q <return> to quit---
0x08048939 <score4+62>: je     0x8048940 <score4+69>
0x0804893b <score4+64>: mov    $0x0,%ebx
0x08048940 <score4+69>: mov    %ebx,%eax
0x08048942 <score4+71>: pop    %ebx
0x08048943 <score4+72>: pop    %ebp
0x08048944 <score4+73>: ret

我开始检查得分2。 我所做的是:

gdb) x 0x8049f88
0x8049f88 <secret>:      "Чй"
(gdb) disas 0x8049f88
Dump of assembler code for function secret:
0x08049f88 <secret+0>:  dec    %dl
0x08049f8a <secret+2>:  add    %al,(%eax)
End of assembler dump.

我迷失在这里。

这是我认为到目前为止所发生的事情(见评论):

(gdb) disas score2
Dump of assembler code for function score2:
0x080488c8 <score2+0>:  push   %ebp
0x080488c9 <score2+1>:  mov    %esp,%ebp           'Copy %esp into %ebp
0x080488cb <score2+3>:  mov    0x8049f88,%eax      'executing: decrement and add
0x080488d0 <score2+8>:  sub    $0x2,%eax           ' subtract $0x2 from %eax (How can I figure out what $0x2
0x080488d3 <score2+11>: mov    %eax,0x8049f88 'Have no idea what this does
0x080488d8 <score2+16>: cmp    0x8(%ebp),%eax compare of %ebp to %eax (why %ebp has 0x8 preceding it?) 
0x080488db <score2+19>: setne  %al 'I have no idea what this does
0x080488de <score2+22>: movzbl %al,%eax
0x080488e1 <score2+25>: sub    $0x1,%eax
0x080488e4 <score2+28>: and    $0xa,%eax
0x080488e7 <score2+31>: pop    %ebp
0x080488e8 <score2+32>: ret

如果你能帮我理解score2对一个整数执行什么样的转换以及我可以在gdb中运行哪些命令可以帮助我,我会非常感激它并试图通过它来计算其余部分(得分1-3)我。我刚刚迷失在这里。

3 个答案:

答案 0 :(得分:2)

理解反汇编只需要知道两件事。您需要知道的第一件事是CPU支持的所有指令和寻址模式以及它们的工作方式。第二件事是汇编器/反汇编器使用的语法。如果不熟悉这些事情,你将无处可去。

对于“你将无处可去”的例子,这里是得分2:

0x080488c8 <score2+0>:  push   %ebp              ;Save EBP
0x080488c9 <score2+1>:  mov    %esp,%ebp         ;EBP = address of stack frame
0x080488cb <score2+3>:  mov    0x8049f88,%eax    ;EAX = the data at address 0x8049f88
0x080488d0 <score2+8>:  sub    $0x2,%eax         ;EAX = EAX - 2
0x080488d3 <score2+11>: mov    %eax,0x8049f88    ;The value at address 0x8049f88 = eax
0x080488d8 <score2+16>: cmp    0x8(%ebp),%eax    ;Compare the int at offset 8 in the stack frame with EAX
0x080488db <score2+19>: setne  %al               ;If the int at offset 8 in the stack frame wasn't equal to EAX, set AL to 0, otherwise set AL to 1
0x080488de <score2+22>: movzbl %al,%eax          ;Zero-extend AL to EAX (so EAX = 0 or 1)
0x080488e1 <score2+25>: sub    $0x1,%eax         ;Decrease EAX (so EAX = -1 or 0)
0x080488e4 <score2+28>: and    $0xa,%eax         ;EAX = EAX AND 0x0A (so EAX = 0xA or 0)
0x080488e7 <score2+31>: pop    %ebp              ;Restore previous EBP
0x080488e8 <score2+32>: ret                      ;Return

转换回C,这可能类似于:

int score2(int something) {
    some_global_int -= 2;
    if(some_global_int == something) return 0;
    else return 0x0A;
}

当然,我只在5分钟内拍了这个,并没有仔细检查任何东西或测试任何东西,所以可能是错的。

在阅读上述“score2”代码后,您是否更接近理解任何其他功能的反汇编?

根据您最初尝试评分得分2,您应该要求某人为您完成所有工作(并且什么都不学,并且无法知道该人是对还是错),或者要求最好的地方学习80x86汇编(和AT&amp; T语法)。

答案 1 :(得分:1)

我假设您已经获得了某种带有分数函数的编译库,并且您正试图将其作为某种功课项目进行逆向工程。在这种情况下,我建议您开始熟悉标准C调用约定cdecl

基本上,esp指向堆栈,函数的参数在被调用之前被推送到堆栈,因此C函数首先将esp移动到ebp,然后它可以通过从ebp中减去值并取消引用结果地址来访问参数。它使用ebp来实现此目的,因此它仍然可以修改esp,以便在堆栈中添加更多局部变量,而不会丢失存储参数的位置。

无论如何,这里是score2的概述,以帮助您入门:

(gdb) disas score2
Dump of assembler code for function score2:
0x080488c8 <score2+0>:  push   %ebp
0x080488c9 <score2+1>:  mov    %esp,%ebp  ; This just saves a copy of the top of our stack to read arguments with
0x080488cb <score2+3>:  mov    0x8049f88,%eax  ; Load a value from a memory location (the number is a memory address, probably to a global variable)
0x080488d0 <score2+8>:  sub    $0x2,%eax       ; Subtract 2
0x080488d3 <score2+11>: mov    %eax,0x8049f88  ; Store the new value into the same memory location
0x080488d8 <score2+16>: cmp    0x8(%ebp),%eax  ; Compare the first argument of the function to that value
0x080488db <score2+19>: setne  %al             ; Sets the lower byte of eax to 1 if they don't match
0x080488de <score2+22>: movzbl %al,%eax        ; Sets al to eax, zeroing the upper bytes so eax is just 1 or 0 now
0x080488e1 <score2+25>: sub    $0x1,%eax       ; Subtract 1 from eax
0x080488e4 <score2+28>: and    $0xa,%eax       ; eax = eax & 0xa
0x080488e7 <score2+31>: pop    %ebp           
0x080488e8 <score2+32>: ret                    ; Return eax

这意味着存在一些存储在0x8049f88的全局变量 (我们称之为x),得分2字面意思是:

int score2(int n) {
  x -= 2;
  if (n == x) 
    n = 1;
  else
    n = 0;
  n--;
  n = n & 0xa;
  return n;
}
编辑:Brendan的例子是一样的,但可能看起来更像原始代码。查看几次并将其与装配输出进行比较。

现在,下一步是查看变量0x8049f88中的内容。尝试在gdb中运行awatch *0x8049f88以使其在每次访问时停止,并print *0x8049f88以查看存储在那里的内容。

如果您对汇编语言不太熟悉,也应该运行set disassembly-flavor intel。然后语法将匹配您在Internet上更有可能找到的示例。

答案 2 :(得分:0)

我认为你无法访问这些功能的源代码,对于拼图或家庭作业,你应该尝试找到数字来获得大分。您可能应该编辑您的问题以显示score.h的内容,或者只是相关部分,如果它非常冗长。另请注意,0x8049f88处的反汇编没有意义。而是使用gdb的x命令显示该位置,并相应地进行编辑。

虽然您可以通过反汇编解决问题(如上所述),但您也可以尝试使用不同的主程序,报告单个分数?()调用的结果,并通过一系列值查找其中一些值很有价值。

使用score2(),main()内的循环将不起作用,因为score2()从内存中的单词中减去2。因此,如果您想尝试大量输入,则需要在shell代码循环中使用不同的参数调用该程序。例如,如果你使用bash:

for i in {1..1000}; do testScore2 $i; done

其中testScore2是一个主程序,只运行带有参数的score2()并报告结果。

当然,因为score2()只能产生两个不同的结果,正如之前两个答案中详细解释的那样,用两个以上的参数值测试score2()实际上没有意义。我展示了上面的shell代码,因为您可能希望将这种技术与其他一些得分函数一起使用。