【问题标题】:Can someone help make sense of this assembly code to try reverse engineer?有人可以帮助理解这个汇编代码来尝试逆向工程吗?
【发布时间】:2017-09-09 06:14:16
【问题描述】:

这是一个disas 的函数,它接受输入并阻止炸弹爆炸。

0x00000000004011ca <+0>:     sub    $0x8,%rsp                 #reserve 8 bytes on stack
0x00000000004011ce <+4>:     cmpb   $0x37,0x1(%rdi)           #compare 0x37 ('7') with second character of input
0x00000000004011d2 <+8>:     jne    0x4011df <phase_1+21>     #explode bomb if not equal
0x00000000004011d4 <+10>:    cmpb   $0x5d,0x2(%rdi)           #compare 0x5d (']') with third character of input
0x00000000004011d8 <+14>:    jne    0x4011df <phase_1+21>     #explode bomb if not equal
0x00000000004011da <+16>:    cmpb   $0x5a,(%rdi)              #compare 0x5a ('Z') with first character of input
0x00000000004011dd <+19>:    je     0x4011ed <phase_1+35>     #if all equal, skip bomb explosion
0x00000000004011df <+21>:    callq  0x401c01 <bomb_ignition>  #bomb explode
0x00000000004011e4 <+26>:    mov    $0xffffffffffffffff,%rax  #rax = -1
0x00000000004011eb <+33>:    jmp    0x401200 <phase_1+54>     #end 
0x00000000004011ed <+35>:    movsbl 0xf(%rdi),%eax            //need help here
0x00000000004011f1 <+39>:    add    $0x1b,%eax
0x00000000004011f4 <+42>:    movsbl 0xe(%rdi),%edx
0x00000000004011f8 <+46>:    cmp    %edx,%eax
0x00000000004011fa <+48>:    sete   %al
0x00000000004011fd <+51>:    movzbl %al,%eax
0x0000000000401200 <+54>:    add    $0x8,%rsp
0x0000000000401204 <+58>:    retq 

我已经用# 注释了我认为它在做什么。如果我在任何地方错了,请告诉我。我需要帮助来弄清楚它在第一个 movsbl 时和之后做了什么。从刚刚阅读来看,我认为它将%rdi 扩展了15,然后将其放入%eax。然后加 27。什么,我不知道。然后将%rdi 扩展14 并放入%edx。它比较,如果相等,则设置标志%al?然后将%al 移动到%eax。然后清理堆栈空间。然后返回。

我对任何事情的理解是否出错了?有人可以澄清movsbl 在这方面做了什么吗?任何帮助表示赞赏。谢谢

【问题讨论】:

  • @MitchWheat 我已经看到了,并且喜欢它。它们似乎都超出了我的想象,似乎并没有清楚地解释它的作用或为什么这些示例的行为方式(imo)。你介意解释一下,好像我是 5 岁
  • 如果写成mov 0xf(%rdi),%eax 对你来说更有意义吗?您不能(完全)这样写,因为源 (0xf(%rdi)) 是一个字节,而目标是一个 32 位整数 (eax)。由于目标长度为 32 位,因此您必须告诉汇编器如何处理其他 24 位。告诉它扩展符号位(即,如果字节为负,则使 int 为负)是一种方法。
  • movsbl 是从 8 位到 32 位的从内存中扩展符号的负载。

标签: c assembly


【解决方案1】:
movsbl 0xf(%rdi),%eax

movsbl 是使用 sign 扩展将字节移动到 long,因此 int8_t 被提升为 int32_t;即

int32_t eax = *((int8_t *)(rdi + 0xf));

这意味着signed value as interpreted according to the two's complement stays the same,所以如果int8_t 持有例如-1int32_t 也将持有 -1。但是,如果解释为无符号,则相应的值将是 0xFF0xFFFFFFFF,这显然是不一样的。未签名的促销将改为零扩展,因此在此处使用movzbl 会将0xFF 扩展到0x000000FF;零扩展确保扩展后的无符号值相同

那么另一个不那么明显的指令是

sete   %al

等于

uint8_t al = <previous comparison equal/set zero flag> ? 1: 0;

设置al 不会重置eaxrax 中的其余位,因此,指令

movzbl %al,%eax

使用 zero 扩展,即无符号提升将字节移动到长:

uint32_t eax = (uint8_t)al;

这实际上将rax 中的所有高位8-63 归零,因为设置eax 也会重置高位。

默认返回值在累加器中,因此该函数返回10 以及所有intN_tuintN_t 对于N of 8、16、32、64 的返回类型的工作方式相同在原型中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 2021-08-16
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2016-04-28
    相关资源
    最近更新 更多