Сношения с Идой Крис Касперски Хакер, номер #094, стр. 094-120-5 1260: dd offset loc_401311 Хм, выглядит вполне обычно, и все метки без исключения обнаруживаются простым контекстным поиском: $NORMAL_STATE$1535: mov ecx, dword_406428 … loc_4012AA: or [ebp+var_10], 0FFFFFFFFh … loc_4012C5: movsx eax, bl Почему же тогда ассемблерный транслятор их не видит?! Все дело в том, что IDA Pro неверно определила границы функции, поместив обращения к меткам за границы функции, в которой они упоминаются!!! А метки вообще-то локальны. Вот потому-то транслятор их и не находит! $NORMAL_STATE$1535: … loc_4012AA: … loc_4012C5: … loc_401311: … __output endp ; <-- конец функции off_401956 dd offset $NORMAL_STATE$1535 dd offset loc_4012AA dd offset loc_4012C5 dd offset loc_401311 Чтобы исправить ситуацию, необходимо переместить директиву «__output endp» за конец обращений к меткам. Так, чтобы они стали частью функции __output. После чего ассемблерный код будет выглядеть так: off_401956 dd offset $NORMAL_STATE$1535 dd offset loc_4012AA dd offset loc_4012C5 __output endp После ассемблирования количество ошибок тает буквально на глазах, и мы даже в порыве вдохновения едва удерживаемся от того, чтобы не закурить новый косяк: demo_3.asm(70) : error A2015: segment attributes cannot change : Alignment demo_3.asm(8064) : error A2189: invalid combination with segment alignment : 2048 demo_3.asm(12005) : error A2015: segment attributes cannot change : Alignment … demo_3.asm(2925) : error A2006: undefined symbol : loc_402480 demo_3.asm(3640) : error A2001: immediate operand not allowed demo_3.asm(4159) : error A2006: undefined symbol : loc_402D11 В глаза бросается пара уже известных нам ошибок типа «undefined symbol», первую из которых исправить достаточно легко: __NLG_Notify1: push ebx push ecx mov ebx, offset unk_406364 jmp short loc_402480 __NLG_Notify proc near push ebx push ecx mov ebx, offset unk_406364 mov ecx, [ebp+8] loc_402480: mov [ebx+8], ecx mov [ebx+4], eax mov [ebx+0Ch], ebp __NLG_Dispatch: pop ecx pop ebx retn 4 __NLG_Notify endp Достаточно «завести» подпрограмму __NLG_Notify1 под «retn 4» процедуры __NLG_Notyfy, но перед директивой __NLG_Notify endp, тогда метка будет распознаваться как надо! __NLG_Notify proc near push ebx push ecx mov ebx, offset unk_406364 mov ecx, [ebp+8] loc_402480: mov [ebx+8], ecx mov [ebx+4], eax mov [ebx+0Ch], ebp __NLG_Dispatch: pop ecx pop ebx retn 4 __NLG_Notify1: push ebx push ecx mov ebx, offset unk_406364 jmp short loc_402480 __NLG_Notify endp А вот со следующей ошибкой справиться уже сложнее, поскольку функция strcpy совершает прыжок в середину функции strcat: _strcpy proc near arg_0 = dword ptr 8 push edi mov edi, [esp+arg_0] jmp loc_402D11 _strcpy endp _strcat proc near arg_0 = dword ptr 4 arg_4 = dword ptr 8 mov ecx, [esp+arg_0] … loc_402D11: mov ecx, [esp+4+arg_4] test ecx, 3 jz loc_402D36 … retn _strcat endp Никакими ухищрениями у нас не получится перетасовать код так, чтобы метка loc_402D11 оказалась в границах видимости, но ведь как-то же это было запрограммировано?! Обратившись к исходным текстам библиотеки LIBC.LIB (они поставляются вместе с компилятором) мы обнаружим волшебный ключик. Чтобы метка была видна отовсюду, после нее должен стоят не один знак «:», а целых два — «::». |