【问题标题】:How to convert from assembly into readable code in a higher level language?如何从汇编转换为更高级语言的可读代码?
【发布时间】:2019-02-01 03:42:10
【问题描述】:

我想了解一个用汇编程序编写的算法。 代码是这样的

 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 中的样子。

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

有人可以帮我吗?

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

【问题讨论】:

  • 这些指令的工作原理将在英特尔的手册中清楚地解释。例如NOTROL

标签: assembly reverse-engineering decompiling


【解决方案1】:

很难看出高级编程语言转换将如何帮助您,因为例如 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

如您所见,编译器正确理解了最初的两个ands 最终会产生等于not &lt;input_value&gt; 的值(*),所以最初的6 行被优化为两行,然后剩下的与原始代码相同(除了使用寄存器eax而不是ecx进行计算)。

*) 为什么相同的值?因为第一个AND EAX,0xBBD13D22 将只保留输入值中的一些位设置,而在not 之后这些位将变为“0”,所以这些可能会影响and ecx,eax 之后的ecx 值。但是将被 and 清零的位也在 ecx 中设置为 1(它是输入值的副本),并且在 not ecx 之后它们也变为零,所以基本上与 eax 的那部分没有'不对not &lt;input_value&gt; 计算做任何事情。

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

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


编辑:实际上ROL 在 C++ 中有点棘手,因为没有直接的操作,在 C++ 中只有移位可用,所以我确实自动编写了正确的位操作以获得与 @987654337 相同的结果@ 将产生(将值的一半向左移动 16 并将其用作结果的上 16b 部分,并将上半部分向下移动 16b 并通过 OR-ing 组合结果)。我什至没有想那么多,所以当语言不直接支持某些操作时,我没有意识到这实际上是我在上一段中谈论的那个东西。另外如您所见,该习语被编译器识别,而不是将其编译为两班,一班and和一班or,而是直接使用rol

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-03
    • 2013-11-21
    • 2017-06-17
    • 1970-01-01
    • 2011-05-30
    • 2011-01-11
    • 1970-01-01
    相关资源
    最近更新 更多