Assembler для Windows

цветы сочи, доставка цветов сочи официальный источник заявляет: http://infomir.25mk.ru. | Игры, это и многое другое.



Глава 6. Исправление исполняемых модулей

Сразу скажу, что исправление исполняемых модулей - дело тонкое и требует не столько знаний, сколько навыков. Впрочем, без знания ассемблера Вам не обойтись. Но если Вы дошли до данной главы, то с этим, я думаю, все в порядке. В предисловии я уже обосновывал необходимость изучения методов изучения и исправления кода программ. Считаю, что общество и государство нуждается в специалистах и по защите, и по взлому компьютерных систем, как оно нуждается в профессиональной армии. В своей книге я лишь слегка касаюсь исправления модулей.

I

Сейчас мы рассмотрим простой57 пример, демонстрирующий некоторые приемы такого типа работы. Задача, которую ставим перед собой, не так сложна, и решить ее можно, воспользовавшись только дизассемблером W32Dasm.

Данная программа (Allscreen - программа, с помощью которой можно "снимать" окна и отдельные части экрана) попала ко мне как Shareware Release. Программа написана на Delphi, но мы увидим, что решить поставленную задачу можно, и не зная, на чем написана программа. При запуске ее на экране появляется окно, изображенное на Рис. 4.6.1. Ближе познакомившись с предметом, Вы убедитесь, что чаще всего приходится искать место в программе, соответствующее какому-либо визуальному эффекту: открытие окна, закрытие окна, вывод текста и т.п.

Рис. 4.6.1. Окно, появляющееся при запуске программы Allscreen.

При выборе кнопки "Accept" возникает задержка секунд в шесть (см. Рис. 4.6.2.). Далее программа работает нормально.

Рис. 4.6.2. Окно задержки.

После 15-ти запусков появляется окно Рис. 4.6.3 и происходит выход из программы.

Рис. 4.6.3. Сообщение об истечении времени работы программы.

Таким образом, следует решить две проблемы:

  1. Устранить весьма раздражающую задержку.
  2. Сделать так, чтобы программа работала при любом количестве запусков.

Рис. 4.6.2 являет собой явный "прокол" авторов программы. Дело в том, что окно и все его содержимое можно спрятать в ресурсы. Но когда на том же окне появляется новая запись - это уже программный код. Итак, запускаем W32Dasm и считываем туда программу All Screen. Запускаем окно SDR (String Data Reference), ищем строку Shareware Delay, дважды щелкаем по ней и, закрыв его, оказываемся в нужном месте программы. Вот этот фрагмент (Рис. 4.6.4.).

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004420BC(C)
|
:00442123 33D2 xor edx, edx
:00442125 8B83B0010000 mov eax, dword ptr [ebx+000001B0]
:0044212B E8541DFDFF call 00413E84
:00442130 33D2 xor edx, edx
:00442132 8B83B4010000 mov eax, dword ptr [ebx+000001B4]
:00442138 E8471DFDFF call 00413E84
:0044213D 33D2 xor edx, edx
:0044213F 8B83B8010000 mov eax, dword ptr [ebx+000001B8]
:00442145 E83A1DFDFF call 00413E84
:0044214A BA50000000 mov edx, 00000050
:0044214F 8B83BC010000 mov eax, dword ptr [ebx+000001BC]
:00442155 E8D618FDFF call 00413A30
* Possible StringData Ref from Code Obj ->"Shareware Delay"
:0044215A BAA8214400 mov edx, 004421A8
:0044215F 8B83BC010000 mov eax, dword ptr [ebx+000001BC]
:00442165 E8EE1DFDFF call 00413F58
:0044216A 33D2 xor edx, edx
:0044216C 8B83C0010000 mov eax, dword ptr [ebx+000001C0]
:00442172 E80D1DFDFF call 00413E84
:00442177 33D2 xor edx, edx
:00442179 8B83C4010000 mov eax, dword ptr [ebx+000001C4]
:0044217F E8001DFDFF call 00413E84
:00442184 33D2 xor edx, edx
:00442186 8B83C8010000 mov eax, dword ptr [ebx+000001C8]
:0044218C E8F31CFDFF call 00413E84
:00442191 8B83CC010000 mov eax, dword ptr [ebx+000001CC]
:00442197 E8E8D4FFFF call 0043F684
:0044219C 5B pop ebx
:0044219D C3 ret

Рис. 4.6.4. Фрагмент кода, осуществляющего, в частности, задержку.

Я сразу взял несколько больше кода, захватив и несколько верхних строк. По сути дела, перед нами вся процедура задержки. Нет смысла пытаться понять, что означает та или иная команда call, хотя легко сообразить, что, например, call 00413E84 убирает строку с экрана.

Для того чтобы решить проблему задержки, достаточно "выключить" этот фрагмент из программы. Проще всего это можно сделать, поставив в начало команды pop ebx / ret, используя такой редактор, как HIEW. В результате задержка исчезает.

Перейдем теперь ко второй проблеме — ограничение на количество запусков. Уже из самого вида окна ясно, что оно формируется в самой программе. Следовательно, опять можно попытаться найти текст, который изображается на экране, в самой программе.

:00443326 8ВС0 mov eax, eax
:00443328 53 push ebx
:00443329 8BD8 mov ebx, eax
:0044332B 803DEC56440001 cmp byte ptr [004456EC], 01
:00443332 7546 jne 0044337A
:00443334 A124564400 mov eax, dword ptr [00445624]
:00443339 E84E2CFEFF call 00425F8C
:0044333E A1D8564400 mov eax, dword ptr [004456D8]
:00443343 E87816FEFF call 004249CO
:00443348 FF05F0564400 inc dword ptr [004456F0]
:0044334E C605EC56440000 mov byte ptr [004456EC], 00
:00443355 833DF05644000F cmp dword ptr [004456FO], 0000000F
:0044335C 7E1C jle 0044337A
:0044335E 6AOO push 00000000
:00443360 668BODB0334400 mov cx, word ptr [004433B0]
:00443367 B202 mov dl, 02
* Possible StringData Ref from Code Obj ->"This Software Has Been Used Over"
|
:00443369 B8BC334400 mov eax, 004433BC
:0044336E E8BDAEFEFF call 0042E230
:00443373 8BC3 mov eax, ebx
:00443375 E84214FEFF call 004247BC
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00443332(C), :0044335C(C)
:0044337A 33D2 xor edx, edx
:0044337C 8B83F4010000 mov eax, dword ptr [ebx+000001F4]
:00443382 E8A52DFFFF call 0043612C
:00443387 33D2 xor edx, edx
:00443389 8B83F8010000 mov eax, dword ptr [ebx+000001F8]
:0044338F E8982DFFFF call 0043612C
:00443394 33D2 xor edx, edx
:00443396 8B83FC010000 mov eax, dword ptr [ebx+000001FC]
:0044339C E88B2DFFFF call 0043612C
:004433A1 33D2 xor edx, edx
:004433A3 8B8314020000 mov eax, dword ptr [ebx+00000214]
:004433A9 E87E2DFFFF call 0043612C
:004433AE 5B pop ebx
:004433AF C3 ret

Рис. 4.6.5. Фрагмент кода проверки количества запусков.

Опять мы представляем весь необходимый фрагмент. Найденной выше ссылкой на искомую строку легко обнаруживаем "подозрительные" команды:

cmp dword ptr [004456F0], 0000000F
jle 0044337A

Вспомним, что программа перестает работать как раз после пятнадцати запусков. Проще всего исправить ситуацию, "забив" фрагмент программы с 0044335E по 00443375 командами NOP (90), используя редактор HIEW.

II

Поиск процедуры окна. Большая часть действий в программах для Windows происходит в окне. Поведение же окна определяется его функцией. Часто, чтобы изменить поведение программы, приходится искать нужную функцию окна и редактировать ее.

Для примера я взял программу FILES.EXE. Эта поисковая программа очень удобна для поиска информации в локальной сети. Выберем, например, одно из диалоговых окон данной программы и поставим цель найти функцию этого диалогового окна. Сделаем это двумя способами: с помощью отладочных средств программы W32Dasm и с помощью отладчика SoftIce. На Рис. 4.6.6. показаны несколько открытых диалоговых окон программы. Последнее диалоговое окно с заголовком "Название сетевого компьютера" и будет объектом нашего внимания.

Рис. 4.6.6. Будем искать функцию последнего диалогового окна.

И так обратимся вначале к программе W32Dasm. Имеется последовательность шагов поиска:

  1. Загрузим туда программу FILES.EXE.
  2. Затем обратимся к пункту Debug\Load Process и выходим в отладчик.
  3. Запускаем программу при помощи клавиши F9 и выходим на нужное окно.
  4. Теперь решающий момент. Нажимаем клавишу "Terminate Process" и снова оказываемся в окне дизассемблера.
  5. Глянув чуть выше, Вы обнаружите вызов API-функции DialogBoxParam. На Рис. 4.6.7 изображен нужный фрагмент.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004156BE(C)
|
:004156CA FF7508 push [ebp+08]
:004156CD E8369EFFFF call 0040F508
:004156D2 59 pop ecx
:004156D3 6A00 push 00000000
:004156D5 68019C4000 push 00409C01
:004156DA FF7508 push [ebp+08]
* Possible StringData Ref from Data Obj ->"DIAL3000"
|
:004156DD 6896904300 push 00439096
:004156E2 FF3548CA4300 push dword ptr [0043CA48]
* Reference To: USER32.DialogBoxParamA, Ord:0000h
|
:004156E8 E85FOD0200 call 0043644C
:004156ED 8A153C324D00 mov dl, byte ptr [004D323C]

Рис. 4.6.7. Фрагмент с вызовом функции DialogBoxParam.

Вспомним параметры функции DialogBoxParam. Четвертый параметр как раз представляет собой адрес процедуры окна. Итак, получаем адрес 00409C01. Обратимся к этому адресу (см. Рис. 4.6.8).

:00409C01 55 push ebp
:00409C02 8BEC mov ebp, esp
:00409C04 8B450C mov eax, dword ptr [ebp+0C]
:00409C07 2D10010000 sub eax, 00000110
:00409COC 7413 je 00409C21
:00409COE 48 dec eax
:00409COF OF84EB000000 je 00409D00
:00409C15 2D01020000 sub eax, 00000201
:00409C1A 7444 je 00409C60
:00409C1C E969010000 jmp 00409D8A

Рис. 4.6.7. Начало функции окна.

Взглянув на Рис. 4.6.8, можно убедиться, что это действительно начало некоторой функции. Для того чтобы быть уверенным, что это нужная функция, необходимо сделать некие изменения и проверить результат.

Поставим теперь себе цель, найти ту же самую функцию, но отладчиком SoftIce.

  1. Загружаем загрузчиком LOADER32.EXE программу FILES.EXE в отладчик SoftIce.
  2. Далее Ctrl-D, и мы имеем запущенную программу.
  3. Запускаем диалоговые окна, кроме последнего диалогового окна.
  4. Перед тем как вызвать последнее диалоговое окно, снова войдем в отладчик и установим точку останова на функцию DialogBoxParamA:
    ВРХ DialogBoxParamA
    
  5. Снова входим в программу, запускаем нужное диалоговое окно, при этом происходит автоматический выход в отладчик: сработала точка останова.
  6. Далее нажмем клавишу F11, при этом окажемся в точке вызова либо сразу, либо после закрытия диалогового окна (опять происходит выход в отладчик).
  7. Посмотрев на вызов функции DialogBoxParam, мы легко определим адрес процедуры окна. Разумеется, он совпадает с тем, который мы нашли ранее, с помощью отладчика программы W32Dasm (см. Рис. 4.6.7).

Продолжая разговор об отладчике SoftIce, замечу, что выход на функцию окна можно проделать и другим способом. При помощи команды HWND можно определить дескрипторы запущенных окон. Далее можно поставить точку останова на содержимое первого параметра, который как раз должен быть равен дескриптору окна. Поставить точку останова можно, например, такой командой

ВРХ EIP IF(EBP+8==N)
здесь N - найденный ранее дескриптор окна. После этого остается только проделать что-то с окном, чтобы на функцию его пришло какое-нибудь сообщение.
57 Простой с точки зрения возможных проблем, возникающих при исправлении исполняемых модулей.