Опечатки в «Практическом обратном инжиниринге»? - PullRequest
1 голос
/ 18 июня 2020

Я только что начал книгу Практический обратный инжиниринг Брюса Данга и других, и меня смущает часть «пошагового руководства» в конце первой главы. Это соответствующая часть кода:

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: ...

И комментарий авторов:

«После выхода l oop выполнение возобновляется в строке 66. Строки 67– 68 сохраните совпадающие PROCESSENTRY32 th32ParentProcessID/th32ProcessID в EAX/ECX и продолжите выполнение на 73. Обратите внимание, что строка 66 также является целью перехода в строке 43. Строки 70–74 читают параметр fdwReason из DllMain ( EBP+C) и проверьте, равно ли оно 0 (DLL_PROCESS_DETACH). Если это так, возвращаемое значение устанавливается на 0 и возвращается; в противном случае оно переходит к строке 82 ».

Это это не то, как я интерпретировал код, когда читал его; наверняка любой переход к loc_10001d24 (строка 70) вызовет завершение функции с возвращением значения 0 безоговорочно , и не только если значение в ebp+0x0c равно 0? (Я предполагаю, что pop переход в esi не влияет на регистр eflags, и что переход в строке 76 влияет на результат cmp eax, ecx в строке 74?) Это также согласуется с более ранними частями в код, который переходит к loc_10001d24, если различные вызываемые функции возвращаются со значениями, указывающими на сбой.

Вдобавок я думал, что точка раздела, начинающегося со строки 66, должна также возвращать значение 0, если PROCESSENTRY32 ( структура, определенная ранее, начиная с позиции ebp-0x130 в памяти) имеет равные th32ParentProcessID (ebp-0x118 в памяти) и th32ProcessID (ebp-0x128 в памяти) записи; это верно? Комментарий авторов, похоже, не указывает на это.

В качестве более общего вопроса, даже в первой главе книги было довольно много опечаток; Кто-нибудь знает где-нибудь веб-страницу, собирающую исправления из книги?

Ответы [ 2 ]

3 голосов
/ 14 августа 2020

Это полный список. Это часть вредоносного ПО, обнаруженного в дикой природе:

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.

Я скажу, что в книге определенно не хватает правильной структуры, некоторые вещи книга воспринимает как должное, другие, возможно, мирские вещи подчеркиваются. Тем не менее, очень хороший ресурс.

Да ладно, кто сказал, что это было легко.

3 голосов
/ 18 июня 2020

Да, ECX и EAX загружаются из одного и того же места в памяти, поэтому, если что-то еще не имеет указатель на него и не изменяет его асинхронно, cmp x,x / jne всегда не будет использоваться. В отличие от чисел с плавающей запятой, любое возможное целое число равно самому себе.

И вы правы, pop не меняет EFLAGS, согласно руководствам Intel: https://www.felixcloutier.com/x86/pop.

Чтобы проверить, является ли ячейка памяти нулевой, вы можете загрузить ее в регистр для test eax,eax / jnz
или cmp dword ptr [ebp + 0xc], 0 / jne.

(JNE и JNZ - это одна и та же инструкция; различные мнемоники позволяют вам express семанти c значений равенства или прямого нулевого значения на основе ZF, установленного в соответствии с самим значением.)


Строки 70–74 читают параметр fdwReason DllMain (EBP + C) и проверяют, равен ли он 0 (DLL_PROCESS_DETACH)

Это подделка. Если в книге полно подобных вещей, это не похоже на хорошую книгу.

cmp eax,ecx имеет смысл только тогда, когда он доступен по пути, который загружал 2 разных значения. (И нельзя было использовать test для этого, x & y != 0 не говорит вам, были ли они равны.) Это вряд ли будет реальным выводом компилятора.

...