Как я могу подключить функции Windows в C / C ++? - PullRequest
30 голосов
/ 17 мая 2009

Если у меня есть функция foo(), которую windows реализовал в kernel32.dll, и она всегда возвращает true, могу ли я иметь мою программу: «bar.exe» перехватывает / отклоняет эту функцию Windows и заставляет ее возвращать false для всех процессов вместо этого?

Итак, если мой svchost, например, вызовет foo(), он вернет false вместо true. То же действие следует ожидать для всех других процессов, запущенных в настоящее время.

Если так, то как? Наверное, я ищу общесистемный хук или что-то в этом роде.

Ответы [ 5 ]

35 голосов
/ 17 мая 2009

Взгляните на Объезд , он идеально подходит для такого рода вещей.


Для общесистемного перехвата прочитайте эту статью из 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;
}

Этого должно быть более чем достаточно, чтобы начать!

11 голосов
/ 17 мая 2009

EASYHOOK http://www.codeplex.com/easyhook

Доминируйте все вышеупомянутые методы в простоте, гибкости и функциональности.

Это не обсуждалось ранее и для процессов хука . Я прочитал все листы этой темы, и с абсолютной уверенностью, EASYHOOK значительно выше. Неважно, используете ли вы C, C ++, CLR, что угодно.

Я вставлю немного с домашней страницы Codeplex, чтобы обеспечить достаточное количество уроков.

Ниже приведен неполный список функций:

  1. Так называемый "Thread Deadlock Barrier" избавит от многих основных проблем при подключении неизвестных API; эта технология уникальна для EasyHook
  2. Вы можете написать управляемые обработчики ловушек для неуправляемых API
  3. Вы можете использовать все удобные управляемые коды, такие как NET Remoting, WPF и WCF, например,
  4. Документированный, чистый неуправляемый перехват API
  5. Поддержка перехвата режима ядра в 32- и 64-битном режиме (также ознакомьтесь с моим драйвером обхода PatchGuard 3, который можно найти в списке выпусков)
  6. Нет ресурсов или утечек памяти у цели
  7. Экспериментальный механизм скрытой инъекции, который не привлечет внимания ни одного современного программного обеспечения AV
  8. EasyHook32.dll и EasyHook64.dll являются чисто неуправляемыми модулями и могут использоваться без установленного NET Framework!
  9. Все крючки устанавливаются и автоматически стабильно снимаются
  10. Поддержка Windows Vista с пакетом обновления 1 x64 и Windows Server 2008 с пакетом обновления 1 x 64 с использованием полностью недокументированных API, которые по-прежнему позволяют подключаться к любому терминальному сеансу.
  11. Трассировка стека управляемых / неуправляемых модулей в обработчике хука
  12. Получение вызова управляемого / неуправляемого модуля внутри обработчика перехвата
  13. Создание пользовательских трассировок стека внутри обработчика крюка
  14. Вы сможете писать библиотеки инъекций и хост-процессы, скомпилированные для AnyCPU, что позволит вам внедрять свой код в 32- и 64-битные процессы из 64- и 32-битных процессов, используя одну и ту же сборку во всех случаев.
  15. EasyHook поддерживает перемещение адресации по RIP для 64-битных целей.
  16. Не требуется распаковка / установка.
  17. Распространяемый Visual Studio не требуется.

Я рад, что моя проститутка все еще знает несколько уловок по сравнению, которые заставляют меня держать их рядом. Но чтобы быть уверенным, что когда вам нужен HOOK, 99 раз из 100, EASYHOOK'r поможет вам быстрее. И это довольно активно поддерживается.

8 голосов
/ 17 мая 2009

Пожалуйста, дайте более подробную информацию о функции, которую вы хотите подключить! Есть несколько способов получить свой собственный код, вызываемый в таком случае, например:

  • Вы можете создать поддельную DLL с тем же именем, что и DLL, которая содержит функцию, которую вы хотите подключить (и скопировать ее в папку foo.exe). Эта библиотека будет предоставлять точно такие же функции, как и исходная DLL. Каждая открытая функция просто обходит вызов исходной DLL, за исключением функции, которую вы хотите перехватить.

  • Вы можете изменить таблицу указателей функций во время выполнения, например, с помощью (коммерческого) пакета Detour, который упоминается как «кухня». Тем не менее, выполнение такого перехвата может быть легко выполнено вашим собственным, см. эту статью , чтобы узнать, как это сделать.

  • Вы можете узнать, где конкретная функция вызывается в foo.exe, и просто заменить код сборки, который вызывает функцию, на код, который "возвращает true". По сути, вы исправляете "foo.exe" ..

  • Для определенных функций Windows предлагает автоматическое подключение, например, для ключей и событий мыши. Для этого проверьте функцию SetWindowsHook .

3 голосов
/ 16 июля 2009

Это зависит от версии Windows, на которую вы хотите установить таргетинг. Тем не менее, если вы играете в Pre-Vista, вы можете просто использовать SetWindowsHookEx для внедрения вашей DLL в каждый запущенный процесс. Затем вашей DLL нужно будет перехватить соответствующую функцию, используя Detours или аналогичный.

0 голосов
/ 07 апреля 2010

Если вы пишете свой хук в сборке и не используете Detours (по какой-либо причине), то вам нужна некоторая ключевая информация о возвращении FALSE:

  • Win32, установите EAX на 0
  • Win64, установите RAX на 0

Вам нужно установить EAX или RAX (в зависимости от платформы) в ноль, как последнее, что делает функция, которую вы перехватываете. Это приведет к тому, что вызывающий код получит 0 в качестве возвращаемого значения (при условии, что они возвращают значение типа int или указателя).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...