【问题标题】:Errata in "Practical Reverse Engineering"?“实用逆向工程”中的勘误表?
【发布时间】:2020-10-08 00:06:44
【问题描述】:

我刚刚开始阅读 Bruce Dang 等人撰写的 Practical Reverse Engineering 一书,我对第一章末尾的“演练”部分感到困惑。这是代码的相关部分:

65: ...
66: loc_10001d16:
67:     mov eax, [ebp-118h]
68:     mov ecx, [ebp-128h]
69:     jmp short loc_10001d2a (line 73)
70: loc_10001d24:
71:     mov eax, [ebp+0ch]
72:     mov ecx, [ebp+0ch]
73: loc_10001d2a:
74:     cmp eax, ecx
75:     pop esi
76:     jnz short loc_10001D38 (line 82)
77:     xor eax, eax
78:     pop edi
79:     mov esp, ebp
80:     pop ebp
81:     retn 0ch
82: ...

以及作者的评论:

"循环退出后,在第66行继续执行。第67-68行将匹配的PROCESSENTRY32th32ParentProcessID/th32ProcessID保存在EAX/ECX和 在 73 处继续执行。注意第 66 行也是第 43 行的跳转目标。 第 70-74 行读取 DllMain (EBP+C) 的 fdwReason 参数并检查 是否为 0 (DLL_PROCESS_DETACH)。如果是,则返回值设置为 0 并且 它返回;否则,转到第 82 行。”

这不是我阅读代码时的解释方式;当然,任何跳转到 loc_10001d24(第 70 行)都会导致函数以返回值 0 无条件地终止,而不仅仅是 ebp+0x0c 的值是 0? (我假设poping 到esi 不会影响eflags 寄存器,并且第76 行的跳转条件是第74 行cmp eax, ecx 的结果?)这也与前面的部分一致代码,如果各种被调用的函数返回指示失败的值,则跳转到loc_10001d24

此外,我认为如果PROCESSENTRY32(前面定义的结构,从内存中的ebp-0x130位置开始)等于th32ParentProcessID(@ 987654340@ 在内存中)和th32ProcessIDebp-0x128 在内存中)条目;它是否正确?作者的评论似乎没有表明这一点。

作为一个更普遍的问题,即使只是本书的第 1 章,似乎也有相当多的错别字;有谁知道任何地方都有从书中收集勘误表的网页?

【问题讨论】:

  • @PeterCordes 酷,你;我就是这么想的
  • 您可以在出版商的网站上找到一些勘误表,勘误部分:wiley.com/en-us/…

标签: windows assembly x86 reverse-engineering


【解决方案1】:

是的,ECX 和 EAX 都是从同一个内存位置加载的,所以除非其他东西有指向它的指针并且正在异步更改它,否则 cmp x,x / jne 将永远不会被占用。与浮点数不同,任何可能的整数都等于自身。

你是对的,pop 不会改变 EFLAGS,根据英特尔的手册:https://www.felixcloutier.com/x86/pop

要检查内存位置是否为零,可以将其加载到 test eax,eax / jnz 的 reg 中
cmp dword ptr [ebp + 0xc], 0 / jne

(JNE和JNZ是同一条指令,不同的助记符让你根据值本身设置ZF来表达相等或直接为零的语义。)


第70-74行读取DllMain(EBP+C)的fdwReason参数,检查是否为0(DLL_PROCESS_DETACH)

这是假的。如果这本书充满了这样的东西,那听起来就不是一本好书。

cmp eax,ecx 仅在从加载 2 个不同值的路径到达时才有意义。 (并且不能为此使用testx & y != 0 不会告诉您它们是否相等。)这似乎不太可能是真正的编译器输出。

【讨论】:

    【解决方案2】:

    这是完整列表。它是在野外发现的恶意软件的一部分:

    01:    ; BOOL __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    02:                _DllMain@12 proc near                 
    03: 55               push    ebp
    04: 8B EC            mov     ebp, esp
    05: 81 EC 30 01 00+  sub     esp, 130h
    06: 57               push    edi
    07: 0F 01 4D F8      sidt    fword ptr [ebp-8] 
    08: 8B 45 FA         mov     eax, [ebp-6] 
    09: 3D 00 F4 03 80   cmp     eax, 8003F400h 
    10: 76 10            jbe     short loc_10001C88 (line 18) 
    11: 3D 00 74 04 80   cmp     eax, 80047400h
    12: 73 09            jnb     short loc_10001C88 (line 18) 
    13: 33 C0            xor     eax, eax 
    14: 5F               pop     edi 
    15: 8B E5            mov     esp, ebp 
    16: 5D               pop     ebp 
    17: C2 0C 00         retn    0Ch 
    18:                loc_10001C88:                         
    19: 33 C0            xor     eax, eax 
    20: B9 49 00 00 00   mov     ecx, 49h 
    21: 8D BD D4 FE FF+  lea     edi, [ebp-12Ch] 
    22: C7 85 D0 FE FF+  mov     dword ptr [ebp-130h], 0 
    23: 50               push    eax
    24: 6A 02            push    2
    25: F3 AB            rep stosd 
    26: E8 2D 2F 00 00   call    CreateToolhelp32Snapshot
    27: 8B F8            mov     edi, eax 
    28: 83 FF FF         cmp     edi, 0FFFFFFFFh
    29: 75 09            jnz     short loc_10001CB9 (line 35)
    30: 33 C0            xor     eax, eax
    31: 5F               pop     edi
    32: 8B E5            mov     esp, ebp
    33: 5D               pop     ebp
    34: C2 0C 00         retn    0Ch
    35:                loc_10001CB9:
    36: 8D 85 D0 FE FF+  lea     eax, [ebp-130h] 
    37: 56               push    esi
    38: 50               push    eax 
    39: 57               push    edi
    40: C7 85 D0 FE FF+  mov     dword ptr [ebp-130h], 128h 
    41: E8 FF 2E 00 00   call    Process32First
    42: 85 C0            test    eax, eax
    43: 74 4F            jz      short loc_10001D24 (line 70)
    44: 8B 35 C0 50 00+  mov     esi, ds:_stricmp
    45: 8D 8D F4 FE FF+  lea     ecx, [ebp-10Ch] 
    46: 68 50 7C 00 10   push    10007C50h
    47: 51               push    ecx
    48: FF D6            call    esi 
    49: 83 C4 08         add     esp, 8
    50: 85 C0            test    eax, eax
    51: 74 26            jz      short loc_10001D16 (line 66)
    52:                loc_10001CF0:
    53: 8D 95 D0 FE FF+  lea     edx, [ebp-130h]
    54: 52               push    edx
    55: 57               push    edi 
    56: E8 CD 2E 00 00   call    Process32Next
    57: 85 C0            test    eax, eax
    58: 74 23            jz      short loc_10001D24 (line 70)
    59: 8D 85 F4 FE FF+  lea     eax, [ebp-10Ch] 
    60: 68 50 7C 00 10   push    10007C50h
    61: 50               push    eax 
    62: FF D6            call    esi 
    63: 83 C4 08         add     esp, 8
    64: 85 C0            test    eax, eax
    65: 75 DA            jnz     short loc_10001CF0 (line 52)
    66:                loc_10001D16: 
    67: 8B 85 E8 FE FF+  mov     eax, [ebp-118h] 
    68: 8B 8D D8 FE FF+  mov     ecx, [ebp-128h] 
    69: EB 06            jmp     short loc_10001D2A (line 73)
    70:                loc_10001D24: 
    71: 8B 45 0C         mov     eax, [ebp+0Ch] 
    72: 8B 4D 0C         mov     ecx, [ebp+0Ch] 
    73:                loc_10001D2A: 
    74: 3B C1            cmp     eax, ecx
    75: 5E               pop     esi
    76: 75 09            jnz     short loc_10001D38 (line 82) 
    77: 33 C0            xor     eax, eax
    78: 5F               pop     edi
    79: 8B E5            mov     esp, ebp
    80: 5D               pop     ebp
    81: C2 0C 00         retn    0Ch
    82:                loc_10001D38: 
    83: 8B 45 0C         mov     eax, [ebp+0Ch] 
    84: 48               dec     eax
    85: 75 15            jnz     short loc_10001D53 (line 93) 
    86: 6A 00            push    0 
    87: 6A 00            push    0 
    88: 6A 00            push    0 
    89: 68 D0 32 00 10   push    100032D0h 
    90: 6A 00            push    0 
    91: 6A 00            push    0 
    92: FF 15 20 50 00+  call    ds:CreateThread
    93:                loc_10001D53: 
    94: B8 01 00 00 00   mov     eax, 1
    95: 5F               pop     edi
    96: 8B E5            mov     esp, ebp
    97: 5D               pop     ebp
    98: C2 0C 00         retn    0Ch
    99:                _DllMain@12 endp
    

    所以第 70-74 行本身没有意义,但确实服务于最初的目的 - 如果 Process32First()/Process32Next() 返回 FALSE 然后代码跳转到这里并最终以 0 退出。 如果找到所需的进程,则将 eax/ecx 分别设置为 ParentProcessID/ProcessID,以便函数继续运行。


    不管怎样,书中还提到了第 83-85 行:

    ...lpStartAddress 为 0x100032D0。这个块可以反编译如下:

    if (fdwReason == DLL_PROCESS_DETACH) { return FALSE; }
    if (fdwReason == DLL_THREAD_ATTACH || fdwReason == DLL_THREAD_DETACH) { return TRUE; }
    CreateThread(0, 0, (LPTHREAD_START_ROUTINE) 0x100032D0, 0, 0, 0);
    return TRUE;
    

    第 83-85 行实际上检查 fdwReason 是否等于 DLL_PROCESS_ATTACH(如果不是,则绕过对 CreateThread 的调用,这很有意义),DLL_PROCESS_DETACH 没有特殊情况。

    我会说这本书确实缺乏适当的结构,有些东西是书认为理所当然的,而另一些可能是世俗的东西是强调的。还是很好的资源。

    哦,谁说这很容易。

    【讨论】:

    • 嘿@Assaf Levy,很抱歉迟到了回复!好久没上SO了。非常感谢您的详细回答,非常有帮助。
    猜你喜欢
    • 2012-08-26
    • 2017-04-08
    • 2021-09-29
    • 2010-10-21
    • 2015-08-15
    • 1970-01-01
    • 2021-02-07
    • 2012-05-01
    • 1970-01-01
    相关资源
    最近更新 更多