Операция “перехват”. Используем открытый сокет другого процесса.
Меня всегда интересовало, а можно ли похитить сокет другой программы и использовать его в своих целях? Еще как можно!
Обход фаервола, установка скрытых соединений, чтение конфиденциальных данных – это лишь немногое, что можно сделать, обладая сокетом.
Метод перехвата прост и широко обсуждаем в интернете. Нам не потребуется глубоких знаний Windows, потому что все осуществимо из User Mode (ring 3), но для понимания основы знать просто необходимо. RTFM Джеффри Рихтер “Windows для профессионалов: создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows”, глава 3
Метод заключатся в следующем
Код:
для получения списка открытых описателей, передав ей в качестве первого аргумента SystemHandleInformation
Для получения типа описателя функцию NtQueryObject (Native API)
Код:
c параметром ObjectTypeInformation (нам нужны только ‘File’) и с параметром ObjectNameInformation для получения имени описателя (нам нужны сокеты ‘\Device\Afd’). Эти функции находятся в библиотеке ntdll.dll
Копировать описатель – сокет в наш процесс мы будем функцией DuplicateHandle
Листинг кода (VS2008 Win32->Console Project), демонстрирующий описанный выше метод для вывода всех открытых сокетов в системе.
Код:
Полезные ссылки
Множество примеров использования Tool Help и ZwQuerySystemInformation
Недокументированные функции Windows NT/2K/XP/2003
P.S: впервые статья была опубликована мной 31.05.2009, 19:15 на ачате, а патом на хабрхабаре попала в песочницу, н инвайт мне так и не прислали
Обход фаервола, установка скрытых соединений, чтение конфиденциальных данных – это лишь немногое, что можно сделать, обладая сокетом.
Метод перехвата прост и широко обсуждаем в интернете. Нам не потребуется глубоких знаний Windows, потому что все осуществимо из User Mode (ring 3), но для понимания основы знать просто необходимо. RTFM Джеффри Рихтер “Windows для профессионалов: создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows”, глава 3
Метод заключатся в следующем
- Получить список описателей (хэндлов - handle) открытых нужным процессом
- Найти среди них сокеты
- Скопировать их в свой процесс
Код:
NTSTATUS ZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);
для получения списка открытых описателей, передав ей в качестве первого аргумента SystemHandleInformation
Для получения типа описателя функцию NtQueryObject (Native API)
Код:
NTSTATUS NtQueryObject( HANDLE ObjectHandle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG Length, PULONG ResultLength );
c параметром ObjectTypeInformation (нам нужны только ‘File’) и с параметром ObjectNameInformation для получения имени описателя (нам нужны сокеты ‘\Device\Afd’). Эти функции находятся в библиотеке ntdll.dll
Копировать описатель – сокет в наш процесс мы будем функцией DuplicateHandle
Листинг кода (VS2008 Win32->Console Project), демонстрирующий описанный выше метод для вывода всех открытых сокетов в системе.
Код:
#include "stdafx.h" #include#include // нужный заголовочек с полезными структурами #include // структура NTSTATUS // подключаем сокеты для использования функций преобразования IP адреса и порта #include #pragma comment(lib, "ws2_32.lib") #define BUF_SIZE 102400 // размер буффера под таблицу информации и имени описателя // http://msdn.microsoft.com/en-us/library/aa492492.aspx эх, у меня нет DDK typedef enum _POOL_TYPE { NonPagedPool = 0, PagedPool = 1, NonPagedPoolMustSucceed = 2, DontUseThisType = 3, NonPagedPoolCacheAligned = 4, PagedPoolCacheAligned = 5, NonPagedPoolCacheAlignedMustS = 6, MaxPoolType = 7, NonPagedPoolSession = 32, PagedPoolSession = 33, NonPagedPoolMustSucceedSession = 34, DontUseThisTypeSession = 35, NonPagedPoolCacheAlignedSession = 36, PagedPoolCacheAlignedSession = 37, NonPagedPoolCacheAlignedMustSSession = 38 } POOL_TYPE; // структура необходимая для получения имени описателя - NtQueryObject(ObjectNameInformation) typedef struct _OBJECT_NAME_INFORMATION { UNICODE_STRING Name; WCHAR NameBuffer[0]; } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; // структура необходимая для получения типа описателя - NtQueryObject(ObjectTypeInformation) typedef struct _OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; ULONG TotalNumberOfHandles; ULONG TotalNumberOfObjects; WCHAR Unused1[8]; ULONG HighWaterNumberOfHandles; ULONG HighWaterNumberOfObjects; WCHAR Unused2[8]; ACCESS_MASK InvalidAttributes; GENERIC_MAPPING GenericMapping; ACCESS_MASK ValidAttributes; BOOLEAN SecurityRequired; BOOLEAN MaintainHandleCount; USHORT MaintainTypeList; POOL_TYPE PoolType; ULONG DefaultPagedPoolCharge; ULONG DefaultNonPagedPoolCharge; } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; //используется в NtQueryObject typedef enum _OBJECT_INFORMATION_CLASS { ObjectBasicInformation, ObjectNameInformation, ObjectTypeInformation, ObjectAllInformation, ObjectDataInformation } OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS; //функции мы будем подключать динамически, поэтому их необохдимо описать :) // ZwQuerySystemInformation typedef NTSTATUS (CALLBACK *LPFNZwQuerySystemInformation)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); LPFNZwQuerySystemInformation ZwQuerySystemInformation; // NtQueryObject typedef NTSTATUS (CALLBACK *LPFNNtQueryObject)( HANDLE ObjectHandle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG Length, PULONG ResultLength ); LPFNNtQueryObject NtQueryObject; #define SystemHandleInformation 16 //недокументированый enum SYSTEM_INFORMATION_CLASS // структура используемая в ZwQuerySystemInformation typedef struct _SYSTEM_HANDLE_INFORMATION { USHORT ProcessId; USHORT CreatorBackTraceIndex; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; // Расширенная структура для получения информации о всех описателях typedef struct _SYSTEM_HANDLE_INFORMATION_EX { ULONG NumberOfHandles; SYSTEM_HANDLE_INFORMATION Information[1]; } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; int _tmain(int argc, _TCHAR* argv[]) { DWORD ret; NTSTATUS ss; PUNICODE_STRING us; POBJECT_TYPE_INFORMATION ot; int i,ress,rem_port,loc_port; char *remaddr,*locaddr; sockaddr_in sockname, locname; WSAData WSData; HANDLE hProcess,ObjHandle, hh; HINSTANCE hNTdll = LoadLibrary(L"Ntdll.dll"); if(!hNTdll) return 1; //ищем функции ZwQuerySystemInformation = (LPFNZwQuerySystemInformation) GetProcAddress(hNTdll, "ZwQuerySystemInformation"); NtQueryObject=(LPFNNtQueryObject) GetProcAddress(hNTdll, "NtQueryObject"); WSAStartup(MAKEWORD(2,2), &WSData); // стартуем winsock 2.2 printf("There are the following sockets opened on system:\n"); // Получение числа описателей в системе DWORD buffer_size = 0; SYSTEM_HANDLE_INFORMATION_EX temp_info; ss = ZwQuerySystemInformation( (SYSTEM_INFORMATION_CLASS)SystemHandleInformation, &temp_info, sizeof(temp_info), &buffer_size); // выделяем память под информацию о описателях и SYSTEM_HANDLE_INFORMATION_EX *system_handles =(SYSTEM_HANDLE_INFORMATION_EX*)malloc(buffer_size ); // если C++ можно и (new BYTE[buffer_size]) ss = ZwQuerySystemInformation( (SYSTEM_INFORMATION_CLASS)SystemHandleInformation, system_handles, buffer_size, &buffer_size); // выделяем память под сруктурки ot=(POBJECT_TYPE_INFORMATION)malloc(BUF_SIZE); us=(PUNICODE_STRING)malloc(BUF_SIZE); // информацию о всех описателях мы получили теперь пробежимся по ним... for(i=0;i NumberOfHandles;i++) { /* Тут можно вставить проверку на описатели определенного процесса, PID которого можно получить кучей разных способов (см. ссылки в конце статьи) */ hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, system_handles->Information[i].ProcessId); // открываем процесс с нужными правами доступа if (hProcess != INVALID_HANDLE_VALUE) { hh=(HANDLE)system_handles->Information[i].Handle; // у меня были проблемы с преобразованиями - для этого и завел новую переменную // теперь копируем описатель в адресное пространство своего процесса if(DuplicateHandle(hProcess,hh,INVALID_HANDLE_VALU E, &ObjHandle, DUPLICATE_SAME_ACCESS, 0, 0)) { // вытаскиваем информацию о типе описателя ss = NtQueryObject(ObjHandle,ObjectTypeInformation, ot, BUF_SIZE, &ret); if (ss == STATUS_SUCCESS) { //кстати таким образом можно перехватывать любые обьекты ядра заданые в таблице описателей процесса, if(lstrcmp(ot->TypeName.Buffer,L"File")==0){ // но нам нужен только File // вытаскиваем информацию о имени описателя ss=NtQueryObject(ObjHandle,ObjectNameInformation, us, BUF_SIZE, &ret); if(ss==STATUS_SUCCESS){ if(lstrcmp(us->Buffer,L"\\Device\\Afd")==0){ // если это сокет /* ================================================== =============================== Вот впринципе и все! мы нашли сокет и он уже находится во власти нашего процесса теперь мы можем делать с ним все, что захотим! ;) а я хочу вывысти информацию о нем и о том кому он пренадлежит. ================================================== =============================== */ ress = sizeof(sockaddr_in);//--- commenting this line would cause an 10014 error. getpeername((SOCKET)ObjHandle, (sockaddr *)&sockname, &ress); //--- определяем локальный IP и порт ress = sizeof(sockaddr_in);//--- commenting this line would cause an 10014 error. getsockname((SOCKET)ObjHandle, (sockaddr *)&locname, &ress); //--- коевертируем в понятные для глаза данные ) remaddr = inet_ntoa(sockname.sin_addr); rem_port = ntohs(sockname.sin_port); locaddr = inet_ntoa(locname.sin_addr); loc_port = ntohs(locname.sin_port); // выводим информацию wprintf(L"PID=%d; Local=%S:%d; Peer=%S:%d;\n",system_handles->Information[i].ProcessId,locaddr,loc_port,remaddr,rem_port); } } // --- name handle } } // --- type handle } // -- duplicate handle CloseHandle(hProcess); } } // --- for // освобождаем память free(ot); free(us); free(system_handles); WSACleanup(); // отключаемс сокеты FreeLibrary(hNTdll); // и выгружаем DLL getchar(); // а это так для паузы ) return 0; }
Полезные ссылки
Множество примеров использования Tool Help и ZwQuerySystemInformation
Недокументированные функции Windows NT/2K/XP/2003
P.S: впервые статья была опубликована мной 31.05.2009, 19:15 на ачате, а патом на хабрхабаре попала в песочницу, н инвайт мне так и не прислали
Комментарии
Отправить комментарий