Как я могу подключить функции Windows в C/C++?
Если у меня есть функция foo()
что windows реализован в kernel32.dll и всегда возвращает true, могу ли я иметь мою программу: "bar.exe" перехватывает / обходит эту функцию Windows и заставляет вместо нее возвращать false для всех процессов?
Так что, если мой svchost, например, звонит foo()
, он вернет ложь вместо истины. То же действие следует ожидать для всех других процессов, запущенных в настоящее время.
Если так, то как? Я думаю, я ищу общесистемный хук или что-то в этом роде.
5 ответов
Взгляните на Detours, он идеально подходит для такого рода вещей.
Для общесистемного перехвата прочитайте эту статью из MSDN.
Сначала создайте DLL, которая обрабатывает перехват функций. Этот пример ниже перехватывает функции отправки и получения сокета.
#include <windows.h>
#include <detours.h>
#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )
int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Send( s, buf, len, flags );
}
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Recv( s, buf, len, flags );
}
BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
switch ( dwReason ) {
case DLL_PROCESS_ATTACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourAttach( &(PVOID &)Real_Send, Mine_Send );
DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourDetach( &(PVOID &)Real_Send, Mine_Send );
DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
}
return TRUE;
}
Затем создайте программу для внедрения DLL в целевое приложение.
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>
void EnableDebugPriv() {
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );
CloseHandle( hToken );
}
int main( int, char *[] ) {
PROCESSENTRY32 entry;
entry.dwSize = sizeof( PROCESSENTRY32 );
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );
if ( Process32First( snapshot, &entry ) == TRUE ) {
while ( Process32Next( snapshot, &entry ) == TRUE ) {
if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {
EnableDebugPriv();
char dirPath[MAX_PATH];
char fullPath[MAX_PATH];
GetCurrentDirectory( MAX_PATH, dirPath );
sprintf_s( fullPath, MAX_PATH, "%s\\DllToInject.dll", dirPath );
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, entry.th32ProcessID );
LPVOID libAddr = (LPVOID)GetProcAddress( GetModuleHandle( "kernel32.dll" ), "LoadLibraryA" );
LPVOID llParam = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen( fullPath ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( hProcess, llParam, fullPath, strlen( fullPath ), NULL );
CreateRemoteThread( hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)libAddr, llParam, NULL, NULL );
CloseHandle( hProcess );
}
}
}
CloseHandle( snapshot );
return 0;
}
Этого должно быть более чем достаточно, чтобы вы начали!
EASYHOOK http://www.codeplex.com/easyhook
Доминируйте все вышеупомянутые методы в простоте, гибкости и функциональности.
Это не обсуждалось ранее и о процессах Крюка. Я прочитал все листы этой темы и с абсолютной уверенностью, EASYHOOK значительно выше. Неважно, используете ли вы C, C++, CLR, что угодно.
Я вставлю немного с домашней страницы Codeplex, чтобы обеспечить достаточное количество уроков.
Ниже приведен неполный список функций:
- Так называемый "Thread Deadlock Barrier" избавит от многих основных проблем при подключении неизвестных API; эта технология уникальна для EasyHook
- Вы можете написать управляемые обработчики ловушек для неуправляемых API
- Вы можете использовать все удобные управляемые коды, например NET Remoting, WPF и WCF.
- Документированный, чистый неуправляемый перехват API
- Поддержка 32- и 64-битного перехвата режима ядра (также проверьте мой обходной драйвер PatchGuard 3, который можно найти в списке релизов)
- В цели не осталось утечек ресурсов или памяти
- Экспериментальный механизм скрытого внедрения, который не привлечет внимания ни одного современного программного обеспечения AV.
- EasyHook32.dll и EasyHook64.dll являются чисто неуправляемыми модулями и могут использоваться без какой-либо установленной платформы NET!
- Все крючки устанавливаются и автоматически удаляются стабильно
- Поддержка Windows Vista SP1 x64 и Windows Server 2008 SP1 x64 с использованием полностью недокументированных API, позволяющих подключаться к любому терминальному сеансу.
- Трассировка стека управляемых / неуправляемых модулей внутри обработчика ловушек
- Получить вызов управляемого / неуправляемого модуля внутри обработчика перехвата
- Создавайте собственные трассировки стека в обработчике хука
- Вы сможете писать библиотеки инъекций и хост-процессы, скомпилированные для AnyCPU, что позволит вам внедрять свой код в 32- и 64-битные процессы из 64- и 32-битных процессов, используя во всех случаях одну и ту же сборку.
- EasyHook поддерживает перемещение по RIP-адресации для 64-битных целей.
- Не требуется распаковка / установка.
- Распространяемый Visual Studio не требуется.
Я счастлив, что моя проститутка по-прежнему знает несколько хитростей, которые заставляют меня держать их под рукой. Но чтобы быть уверенным, что когда вам нужен HOOK, 99 раз из 100, EASYHOOK'r поможет вам быстрее. И это довольно активно поддерживается.
Пожалуйста, дайте более подробную информацию о функции, которую вы хотите подключить! Есть несколько способов получить свой собственный код, вызываемый в таком случае, например:
Вы можете создать поддельную DLL с тем же именем, что и DLL, которая содержит функцию, которую вы хотите перехватить (и скопировать ее в папку
foo.exe
). Эта библиотека будет предоставлять точно такие же функции, как и исходная DLL. Каждая открытая функция просто обходит вызов исходной DLL, за исключением функции, которую вы хотите перехватить.Вы можете изменить таблицу указателей функций во время выполнения, например, с помощью (коммерческого) пакета Detour, который был упомянут "кухней". Тем не менее, выполнение такого перехвата может быть легко сделано самостоятельно, см. Эту статью, чтобы узнать, как это сделать.
Вы можете узнать, где конкретная функция вызывается в
foo.exe
и просто замените ассемблерный код, который вызывает функцию, на код, который "возвращаетtrue
". В основном, вы исправляете"foo.exe
"..Для определенных функций Windows предлагает автоматическое подключение, например, для клавиш и событий мыши. Проверьте функцию SetWindowsHook для этого.
Это в некоторой степени зависит от версии Windows, на которую вы хотите установить таргетинг. Тем не менее, если вы играете в Pre-Vista, вы можете просто использовать SetWindowsHookEx для внедрения вашей DLL в каждый запущенный процесс. Ваша DLL должна была бы затем подключить соответствующую функцию, используя Detours или подобное.
Если вы пишете свой хук в сборке и не используете Detours (по какой-либо причине), тогда вам нужна некоторая ключевая информация о возвращении FALSE:
- Win32, установите EAX на 0
- Win64, установите RAX на 0
Вам нужно установить EAX или RAX (в зависимости от платформы) в ноль как последнее, что делает функция, которую вы перехватываете. Это приведет к тому, что вызывающий код получит 0 в качестве возвращаемого значения (при условии, что они возвращают значение типа int или указателя).