Доброго всем времени суток. Я решил написать пример из книги Неббета. Пример 1.2, который должен выводить список дескрипторов указанного процесса. Собственно вот текст программы Код (Text): // head.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "ntdll.h" //#include "memory.cpp" #include <stdlib.h> #include <stdio.h> #include <vector> #include <map> #include <conio.h> #define WIN32_LEAN_AND_MEAN #pragma comment( lib, "ntdll" ) #pragma warning(disable:4786) struct OBJECTS_AND_TYPES{ std::map<ULONG, NT::PSYSTEM_OBJECT_TYPE_INFORMATION, std::less<ULONG> > types; std::map<PVOID, NT::PSYSTEM_OBJECT_INFORMATION, std::less<PVOID> > objects; }; std::vector<NT::SYSTEM_HANDLE_INFORMATION> GetHandles() { ULONG n; PULONG p = new ULONG[n = 0x100]; while( NT::ZwQuerySystemInformation(NT::SystemHandleInformation, p, n * sizeof *p, 0) == STATUS_INFO_LENGTH_MISMATCH) delete []p, p = new ULONG[n *= 2]; NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p+1); return std::vector<NT::SYSTEM_HANDLE_INFORMATION>(h, h + *p); } OBJECTS_AND_TYPES GetObjectsAndTypes() { ULONG n; PCHAR p = new CHAR[n = 0x1000]; while(NT::ZwQuerySystemInformation(NT::SystemObjectInformation, p, n * sizeof *p, 0) == STATUS_INFO_LENGTH_MISMATCH) { delete []p; p = new CHAR[n *= 2]; } OBJECTS_AND_TYPES oats; for(NT::PSYSTEM_OBJECT_TYPE_INFORMATION t = NT::PSYSTEM_OBJECT_TYPE_INFORMATION(p); ; t = NT::PSYSTEM_OBJECT_TYPE_INFORMATION(p + t->NextEntryOffset)) { oats.types[t->TypeNumber] = t; for(NT::PSYSTEM_OBJECT_INFORMATION o = NT::PSYSTEM_OBJECT_INFORMATION(PCHAR(t->Name.Buffer) + t->Name.MaximumLength); ; o = NT::PSYSTEM_OBJECT_INFORMATION(p + o->NextEntryOffset)) { oats.objects[o->Object] = o;// !!!! CRASH !!!! здесь происходит сбой if(o->NextEntryOffset == 0) break; } if(t->NextEntryOffset == 0) break; } delete []p; return oats; } int _tmain(int argc, _TCHAR* argv[]) { //if(argc == 1) return 0; //ULONG pid = strtoul(argv[1], 0, 0); ULONG pid = 344;// == DEBUG == std::vector<NT::SYSTEM_HANDLE_INFORMATION> handles = GetHandles(); OBJECTS_AND_TYPES oats = GetObjectsAndTypes(); NT::SYSTEM_OBJECT_INFORMATION defobj = {0}; printf("Object Hnd Access F1 Atr #H #P Type Name \n"); for(std::vector<NT::SYSTEM_HANDLE_INFORMATION>::iterator h = handles.begin(); h != handles.end(); h++) { if(h->ProcessId == pid) { NT::PSYSTEM_OBJECT_TYPE_INFORMATION t = oats.types[h->ObjectTypeNumber]; NT::PSYSTEM_OBJECT_INFORMATION o = oats.objects[h->Object]; if(o == 0) o = &defobj; printf("%p %04hx %61x %2x %3hx %3ld %4ld %-14.*S %.*S \n", h->Object, h->Handle, h->GrantedAccess, int(h->Flags), o->Flags, o->HandleCount, t->Name.Length, t->Name.Buffer, o->Name.Length, o->Name.Buffer); } } _getch(); return 0; } При выполнении программы в отладочной сборке выдается ошибка Unhandled exception at 0x00416b39 in tratata.exe: 0xC0000005: Access violation reading location 0xcdce9b9e. и я попадаю в тело процедуры GetObjectsAndTypes() на строку Код (Text): oats.objects[o->Object] = o; При выполнении программы в релизной сборке выпадает ошибка Инструкция по адресу "0x00402961" обратилась к памяти по адресу "0x00000004". Память не может быть "read". Собственно, как я это понимаю, происходит обращение к указателю на невыделенную память. Прогоняя программу в отладчике, я увидел что в процедуре GetObjectsAndTypes() цикл Код (Text): while(NT::ZwQuerySystemInformation(NT::SystemObjectInformation, p, n * sizeof *p, 0) == STATUS_INFO_LENGTH_MISMATCH) { delete []p; p = new CHAR[n *= 2]; } не выполняется ни разу, то есть не выделяется нужное количество памяти. ДЕло в том что программа полностью списана с книги. Может ли кто-нибудь объяснить, почему происходит такая ошибка и почему не выполняется цикл выделения памяти, хотя в процедуре GetHandles() такойже цикл выполняется. Заранее большое спасибо.
Цикл не выполняется если памяти достаточно с первой попытки или произошла ошибка отличная от STATUS_INFO_LENGTH_MISMATCH
Я это понимаю. Дополнительная проверка показывает, что ZwQuerySystemInformation возвращает значение STATUS_UNSUCCESSFUL (0xc0000001L). Почему такое может возникать?
Clerk Нет, у меня антивируса вообще на том компьютере не стоит n0name Точно. Должен быть установлен флаг FLG_MAINTAIN_OBJECT_TYPELIST Я в процедуру добавил следующий код Код (Text): ULONG k = 1; NTSTATUS status; NT::PSYSTEM_GLOBAL_FLAG sgf = new NT::SYSTEM_GLOBAL_FLAG[k]; while((status = NT::ZwQuerySystemInformation(NT::SystemGlobalFlag, sgf, k * sizeof *sgf, 0) ) == STATUS_INFO_LENGTH_MISMATCH) { delete []sgf; sgf = new NT::SYSTEM_GLOBAL_FLAG[k *= 2]; } if((sgf->GlobalFlag & NT::FLG_MAINTAIN_OBJECT_TYPELIST) == NT::FLG_MAINTAIN_OBJECT_TYPELIST) MessageBox(0,"GlobalFlags are OK","",0); else { sgf->GlobalFlag |= NT::FLG_MAINTAIN_OBJECT_TYPELIST; status = NT::ZwSetSystemInformation(NT::SystemGlobalFlag, sgf, k * sizeof *sgf); //delete []p; if(status != STATUS_SUCCESS) { delete []sgf; delete []p; MessageBox(0,"Error in set global flags","",0); exit(1); } } Код выполняется корректно (возвращает STATUSS_SUCCESS), но все равно на том же самом месте падает. Ничего не понимаю. PS. Пытался установить этот флаг через прогу Global Flags, но он почему-то не усновился. Никто не знает почему?
У меня установлен касперский. Установив в реестре в GlobalFlags бит FLG_MAINTAIN_OBJECT_TYPELIST и перезагрузившись, в ntos!NtGlobalFlag этот бит сброшен, в PEB.NtGlobalFlags также бит сброшен, твой инфокласс возвращает STATUS_UNSUCCESSFUL. Если налету установить ntos!NtGlobalFlag это ничего не меняет, также возвращается ошибка.