assembly 无法理解此汇编代码

kupeojn6  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(223)

我是一个新手与组装,我明白一些事情,但它仍然是非常复杂和困难的时刻,我。
我想在GDB中查看一个二进制代码,但有一段代码我一辈子都搞不清楚它在做什么。我知道它可能在做什么,但我不确定。
让我不爽的是:

Dump of assembler code for function main:
   0x08048647 <+0>:     lea    0x4(%esp),%ecx
   0x0804864b <+4>:     and    $0xfffffff0,%esp
   0x0804864e <+7>:     pushl  -0x4(%ecx)
   0x08048651 <+10>:    push   %ebp
   0x08048652 <+11>:    mov    %esp,%ebp
   0x08048654 <+13>:    push   %ebx
   0x08048655 <+14>:    push   %ecx
=> 0x08048656 <+15>:    sub    $0x10,%esp
   0x08048659 <+18>:    mov    %ecx,%ebx
   0x0804865b <+20>:    movb   $0x0,-0x9(%ebp)
   0x0804865f <+24>:    sub    $0xc,%esp
   0x08048662 <+27>:    push   $0x0
   0x08048664 <+29>:    call   0x8048400 <time@plt>
   0x08048669 <+34>:    add    $0x10,%esp
   0x0804866c <+37>:    sub    $0xc,%esp
   0x0804866f <+40>:    push   %eax
   0x08048670 <+41>:    call   0x8048460 <srand@plt>
   0x08048675 <+46>:    add    $0x10,%esp
   0x08048678 <+49>:    call   0x8048480 <rand@plt>
   0x0804867d <+54>:    mov    %eax,%ecx
   0x0804867f <+56>:    mov    $0x51eb851f,%edx
   0x08048684 <+61>:    mov    %ecx,%eax
   0x08048686 <+63>:    imul   %edx
   0x08048688 <+65>:    sar    $0x5,%edx
   0x0804868b <+68>:    mov    %ecx,%eax
   0x0804868d <+70>:    sar    $0x1f,%eax
   0x08048690 <+73>:    sub    %eax,%edx
   0x08048692 <+75>:    mov    %edx,%eax
   0x08048694 <+77>:    imul   $0x64,%eax,%eax
   0x08048697 <+80>:    sub    %eax,%ecx
   0x08048699 <+82>:    mov    %ecx,%eax
   0x0804869b <+84>:    mov    %al,-0x9(%ebp)
...
...

我认为它是用时间作为随机数生成器的种子,然后生成一个随机数,但还有一个类似$0x51eb851f的局部变量,看起来也像一个时间,然后在底部,看起来像是通过使用% al将随机数截断为8位。
谁能帮我把这个分解一下吗?

  • part 2* -等效的C代码是什么样子的?
pinkon5k

pinkon5k1#

看来汇编代码为:

char s = 0;
 srand(time(NULL));
 s = rand() % 100;

当对一段汇编代码进行逆向工程(或询问它)时,总是值得将它拆开并对每一段进行注解。
第一部分应明确:

lea    0x4(%esp),%ecx       ;ecx = esp + 4 = ptr to return addr + 4
and    $0xfffffff0,%esp     ;align the stack
pushl  -0x4(%ecx)           ;push return address

push   %ebp         
mov    %esp,%ebp            ;frame pointer

push   %ebx
push   %ecx                 ;preserved reg

sub    $0x10,%esp           ;allocate 16B
mov    %ecx,%ebx            ;ebx = esp at entry + 4

movb   $0x0,-0x9(%ebp)      ;s = 0

sub    $0xc,%esp            ;Keep the stack aligned at the call site
push   $0x0                 ;NULL
call   0x8048400 <time@plt> ;time(NULL)
add    $0x10,%esp           ;cdecl cleaning

sub    $0xc,%esp            ;alignment
push   %eax                 ;eax = time(NULL)
call   0x8048460 <srand@plt>;eax = srand(time(NULL))
add    $0x10,%esp           ;cdecl

call   0x8048480 <rand@plt> ;rand()
mov    %eax,%ecx            ;ecx = rand()

下一部分有点混乱,除非你已经遇到了this compiler trick
它是通过定点倒数 * 1/d * 除以 * d *,使用了一个技巧来提高精度(参见this)。

  • 1/d * 首先表示为一个32位定点数,点位于最左边的数字之前(这是一种奇特的说法,我们将位的权重视为2的负幂,* 从左到右 *,就像我们通常对十进制数所做的那样)。

将这个数乘以一个整数将生成一个64位的定点数,点在中间(左边32位,右边32位)。由于我们只对整数部分感兴趣,所以我们只取高32位。
为了提高精度,* 1/d * 的浮点表示中的所有前导零都通过向 * 左 * 移位来移除,然后必须通过向 * 右 * 移位来补偿结果。
最后,如果被除数为负,结果可能会相差1,因此我们可能需要加1。
让我们看看代码:

mov    %eax,%ecx        ;ecx = rand() [from previous block]

mov    $0x51eb851f,%edx ;edx = 1/d (shifted)
mov    %ecx,%eax        ;eax = dividend
imul   %edx             ;edx:eax = dividend * (1/d) (shifted)
                        ;edx = integer part, eax = fractional part
sar    $0x5,%edx        ;undo the shift, edx = integer part of dividend * (1/d)
mov    %ecx,%eax        ;eax = dividend
sar    $0x1f,%eax       ;eax = 0xff..f = -1 if dividend negative else 0
sub    %eax,%edx        ;edx = dividend * (1/d) - (-1 if dividend negative else 0) 
mov    %edx,%eax        ;eax = dividend / d

若要找出除数0x51eb851f5的移位表示什么,您可以:
1.求移位后的除数0x51eb851f/0x100000000(与0.99 = 99/100完全相同),在本例中为0.32,然后将其除以2^5,得到:0.32/32 = 0.01 = 1/100。
1.取一个大的光滑数(一个有很多小素数除数的数),比如2310000,乘以0x51eb851f,然后将结果右移32 + 5位。(2310000 * 0x51eb851f) >> 37 = 23100,这样你就可以看到结果是被除数的1/100。这里你需要记住整数除法不是单射的。
You can always check with godbolt.org
我们现在可以完成逆向工程:

mov    $0x51eb851f,%edx
mov    %ecx,%eax
imul   %edx
sar    $0x5,%edx        
mov    %ecx,%eax        
sar    $0x1f,%eax       
sub    %eax,%edx        
mov    %edx,%eax            ;eax = rand() / 100

imul   $0x64,%eax,%eax      ;eax = (rand() / 100) * 100

sub    %eax,%ecx            ;ecx = rand() - (rand() / 100) * 100 = rand() % 100
mov    %ecx,%eax            ;eax = rand() % 100

mov    %al,-0x9(%ebp)       ;s = rand() % 100

相关问题