Ручная троянизация приложений под windows

         

Системные вызовы и библиотечные функции


Бацилла (если это только не вещь в себе по типу океана Соляриса), должна как-то взаимодействовать с внешним миром: открывать файлы, устанавливать сетевые соединения, выводить ругательные сообщения и т.д. Обычно для этого используется прямой вызов API-функций. Но это не лучший вариант. Намного удобнее использовать высокоуровневые библиотечные функции, доставшиеся бацилле в наследство от дрозофилы. Согласитесь, намного удобнее открывать файл с помощью _fopen, чем CreateFile. Одних только аргументов в последнем случае потребуется миллион!

Библиотечные функции легко распознаются при помощи IDA Pro. Вот, например:

Рисунок 5 библиотечные функции, автоматически распознанные IDA Pro

Мы видим, что адрес функции _fopen равен 401988h, значит, ее вызов будет выглядеть приблизительно так:

push   aRb    ; "rb" указатель на строку с режимом открытия файла

push   aName  ; указатель на имя файла (аргументы заносятся справа налево)

call   401988h       l вызываем функции _fopen

add    esp, 8 ; удаляем аргументы из стека

Листинг 1 пример вызова стандартной библиотечной функции языка Си

Однако, использовать библиотечные функции можно только после того, как отработает Start-Up (стартовый код), иначе у нас ничего не получается. В этом нам вновь поможет IDA Pro, распознающая функцию main (WinMain) языков Си/Си++ и процедуру Begin на Паскаль. В notepad'е ее вызов расположен по адресу 1006571h. Здесь находится call 100299Eh, где 100299Eh – адрес WinMain. Для внедрения дрозофилы, достаточно изменить call 100299Eh на свой адрес, в смысле адрес свой бациллы.

Рисунок 6 функция WinMain в стартовом коде

А что делать, если библиотечные функции не распознаны или среди них нет той, что нужна нам? Тогда можно обратиться к импорту дрозофилы и поискать там. В IDA Pro это делается так: View à Open Subview à Imports:

Рисунок 7 функции, импортируемые из USER32.DLL

Вот, например, адрес функции MessageBoxW равен 01001204h. На самом деле, это еще не сам адрес, а только указатель на него, инициализируемый на стадии загрузки, а потому вызов функции будет выглядеть так:

xor    eax,eax                     ; обнуляем eax

push   30h                  ; uType

push   lpCaption            ; lpCaption

push   lpText               ; lpText



push   eax                  ; hWnd

call   dword [1001204h]     ; вызываем

функции MessageBoxW

Листинг 2 пример вызова API-функции из импорта дрозофилы

Но в некоторых случаях, в импорте искомой функции нет функции. Что тогда? Есть два пути: использовать связку LoadLibrary\GetProcAddress или сканировать импорт вручную. Оба этих способа уже рассматривались в статье "техника написания переносимого shell-кода", опубликованной в таком-то номере журнала, так что не будет здесь повторятся.



Содержание раздела