对我来说,有时候我很难手动决定是否打开OEP。
特别是在不是以标准功能序言开头的情况下。

例如:
我发现了以下示例,该示例以PUSHAD指令开头。我逐步浏览代码的内容,直到到达POPAD。几行之后,我看到了一条JMP指令,该指令会导致CALL指令并调用一个函数。在执行完该功能之后,在下一行中,还有另一条JMP指令在此处结束:

    PUSH 58
    PUSH unbr002.014A22F8
    CALL unbr002.013CBD40#
    XOR ESI, ESI
    MOV DWORD PTR SS:[EBP-4], ESI
    LEA EAX, DWORD PTR SS:[EBP-68]
    PUSH EAX
    CALL DWORD PTR DS:[141409C]          kernel32.GetStartupInfoA
    ....
    ....
    ....
    ....
    POP ECX
    CALL DWORD PTR DS:[1414278]          kernel32.GetCommandLineA
    ....


所以,我在某处读到了“ GetCommandLineA –指示您已经达到了用Visual Studio 6编译的程序的入口点。“

我问自己是否有指标列表,以了解是否已经达到OEP。

最好的问候,

评论

什么是内存地址?最后一个JMP是转到原始内存页面,第一个映射到的页面还是第二个(通常是最终的)页面?如果在分配了2个内存之后,您发现进入最后分配的页面的JMP,通常是您跳到了OEP(这是转储和修复解压缩版本的好时机)。

#1 楼

即使包装程序将启动代码分成许多小段,并有大量跳转并“返回”到推入/交换的地址等,魔术常数有时也会有所帮助。

其中一个示例是用于VC ++启动代码的__security_init_cookie。 ,与32位代码中的常量0BB40E64Fh和64位与2B992DDFA232h有关。该函数通常是同时写入__security_cookie和__security_cookie_complement的唯一代码:

.text:00401F06 020           mov     edi, 0BB40E64Eh
; ... stuff involving GetCurrentThreadId(), GetCurrentProcessId() etc. pp. ...
.text:00401F79 020           mov     ___security_cookie, ecx
.text:00401F7F 020           not     ecx
.text:00401F81 020           mov     ___security_cookie_complement, ecx
...
.data:00404000     ___security_cookie dd 0BB40E64Eh
.data:00404004     ___security_cookie_complement dd 44BF19B1h


由于___security_cookie的独特作用(与魔术无关),它的位置也很容易识别。常数。它直接将您带到__security_init_cookie(),这通常是OEP调用的第一个函数,甚至在__tmainCRTStartup()之前。相比之下,导入的函数(CRT dll,Windows API)有时会被打乱,因此很难识别。

那里有一些垃圾软件可以通过如下方式自动分散恒定负载:

1441285DB           mov     edx, 0E6FFA20Fh                           
...
1441285E3           lea     edx, [rdx+19005DF2h]                      


在这个例子中,混淆常数当然是1。其他拆分也是可能的,例如涉及算术运算或位运算,而不是LEA。签名属性是一个常量,用于修改驻留在寄存器中的常量(在基本块内部,不涉及重定位),所有自重编译器都将对此进行优化。