如何将汇编语言转换为高级语言的可读代码?

时间:2018-08-26 09:58:35

标签: assembly reverse-engineering decompiling

我想了解一种用汇编器编写的算法。 代码看起来像这样

 MOV EAX,DWORD PTR SS:[ESP]   - Put Value, entered into EAX
 Mov ECX, EAX                 - Copy value from EAX to ECX
 AND EAX,0xBBD13D22           - add ???
 NOT ECX                      - ???
 NOT EAX                      - ???
 AND ECX,EAX                  - ???
 IMUL ECX,ECX,0x74ACD16       - multiply ECX with &H74ACD16 and put result to ECX - but it's DWORD ???????
 ROL ECX,0x10                 - Rotate Left, but ????
 IMUL ECX,ECX,0xBBB38D0       - result ???

请任何人向我解释,这段代码看起来像Visual Basic。

这是一个数学运算,但是我对汇编程序知之甚少。

请有人帮我吗?

对不起,我的英语不好,但是还在学习。

1 个答案:

答案 0 :(得分:2)

很难看到高级编程语言转换将如何为您提供帮助,因为例如C ++变体看起来几乎是相同的(对于经验丰富的asm程序员):

int32_t someCalculation(int32_t input_value) {
    int32_t ecxL4 = ~input_value;                   // ecx after "NOT ecx" (line 4)
    int32_t eaxL5 = ~(input_value & 0xBBD13D22);    // eax after "NOT eax" (line 5)
    int32_t ecxL6 = ecxL4 & eaxL5;
    int32_t ecxL7 = ecxL6 * 0x74ACD16;              // IMUL ECX,ECX,0x74ACD16
    int32_t ecxL8 = (ecxL7<<16) | ((ecxL7>>16)&0xFFFF); // ROL ecx,0x10
    return ecxL8 * 0xBBB38D0;                       // IMUL ECX,ECX,0xBBB38D0
}

使用gcc 8.2针对32位目标进行了编译,如下所示:

    mov     eax, DWORD PTR [esp+4]
    not     eax
    imul    eax, eax, 122342678
    rol     eax, 16
    imul    eax, eax, 196819152
    ret

如您所见,编译器正确地理解了最初的两个and最终将产生等于not <input_value>的值(*),因此最初的前6行被优化为两个,则其余部分与原始代码相同(除了使用寄存器eax而非ecx进行计算之外)。

*)为什么值相同?因为第一个AND EAX,0xBBD13D22将仅保留输入值中的一些位,并且这些位将在not之后变为“ 0”,因此这些值可能会影响ecx之后的and ecx,eax值。但是将由and归零的位也被设置为ecx中的一(它是输入值的副本),并且在not ecx之后它们也已归零,因此从本质上讲, eax的部分对not <input_value>的计算没有任何作用。

IMO,您更需要使用这些数学函数进行一些练习,还观察值的二进制表示,并弄清楚这些操作是如何在位级别上实现的,因此C ++源代码与原始程序集基本相同,所以我不看不到这会对您有什么帮助。

我无法生成Visual Basic变体,因为我不知道……呃……编程语言? ...但是它很可能以类似于C ++的方式结束(即,与汇编基本相同),或者您将遇到某些32位整数不直接可用的操作,那么您将不得不破解这32位截断/ ranges自己进行位级数学计算。


edit:实际上,ROL在C ++中有些棘手,因为没有直接操作,在C ++中只有移位可用,所以我确实自动编写了正确的位操作来获得与ROL将产生(将值的一半向左移动16并将其用作结果的上半部分16b并将上半部分向下移动16b并通过对它们进行或运算来组合结果)。我什至没有考虑太多,所以我没有意识到当语言不直接支持某些操作时,实际上是我在上一段中所说的。就像您看到的那样,该习惯用法被编译器识别,而不是将其编译为两个移位,一个and和一个or,而是直接使用rol