Тема: Хук Com winApi
Показать сообщение отдельно
  #5  
Старый 20.03.2013, 21:52
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

1) Я бы все-таки нашел место в программе, которое можно безболезненно пропатчить, и вместо него вставил бы LoadLibrary; в DLLMain загружаемой библы поставил бы те действия, что стер из-за лоадлибрари.
2) Я ж уже написал: CreateFile, ReadFile, WriteFile, CloseHandle. Ввод-вывод в любое устройство все равно сводится к этим функциям, только обычно это обернуто в другие функции или компоненты. Бряк на CreateFileA, и ждешь, пока первым параметром не передадут строку 'COM4' или че-то в этом роде (например, '\\.\COM4\'). Потом смотрим, куда адрес возврата - получаем место, откуда ком-порт открывается. Его надо патчить, хотя бы чтобы сохранить хендл у себя (можно ессно попробовать нарыть глобальную переменную хендла, но если в проге юзалась какая-то обертка над ком-портом или много ООП - то задолбаться искать).
3) Менять аргументы не нужно. Вызовы ReadFile/WriteFile можно поменять на свои функции из DLL, описанные по соответствующему шаблону из МСДН:
Код:
int __stdcall newCreateFile(char *name, DWORD access, DWORD share, void *attrs, DWORD disp, DWORD flags, DWORD temp);
И все в таком духе.
Меняется код очень просто - если адрес функции в константе (call ds:CreateFileA), то меняем константу. Если относительный (конструкция вида call _CreateFileA | _CreateFileA: jmp ds:CreateFileA как любит делать студия) - то меняем прямо в опкоде адрес. Адрес вычисляется в этом случае относительный, то есть <адрес_новой_функции> - <адрес команды CALL + 5>. Менять проще всего динамически в DLLMain подгружаемой библиотеки (не забудь, что DLLMain должно вернуть НЕ НОЛЬ, иначе библа выгрузится). Разумеется, чтобы менять код, надо сделать VirtualProtect и снять с нужной страницы флаг READ_ONLY.
Сам код функций - любой, только в конце обязательно вызов оригинальной функции.
Пример:
Код:
int __stdcall newCreateFile(char *name, DWORD access, DWORD share, void *attrs, DWORD disp, DWORD flags, DWORD temp)
{
    FILE *f = fopen("log.txt", "a");
    fprintf(f, "File opened: %s", name);
    fclose(f);
    CreateFileA(name, access, share, attrs, disp, flags, temp);
}
Так можно снимать лог открытых файлов/портов из конкретного места кода. Также можно мониторить и менять при необходимости гоняемые туда-сюда данные через порт, поменяв ReadFile.

Вообще, без патча CreateFile можно обойтись, если работа с портом идет из отдельного места, а не через общий интерфейс для файлов и порта. Тогда можно пропатчить конкретный вызов ReadFile и юзать хендл, приходящий туда. Однако в общем случае может понадобиться сохранение хендла порта.

ЗЫЖ: есть еще один наркоманский вариант, который я один раз использовал - проходиться по стеку вызовов ReadFile вверх на какой-то уровень, и если там определенный адрес, то подменять, иначе вызывать стандартный ReadFile. Вылезал так на 3 функции вверх, обходил STL-ные операции с файлами.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием