Привет, в общем мне надо пробежататься по списку всех модулей процесса в его АП и удалить некоторые ничего особенного, просто спортивный интерес. Значит что уже сделано, получаю список процессов , получаю их EPROCESS, сравниваю с CurrentProcess и если это не он ( дабы не убивать систему ) я аттачусь к процессу , затем иду до EPROCESS->Peb->Ldr а дальше лес гремучий =( Двухсвязанные списки...в общем вот что я набросал : Код (Text): void DeleteModulesFromProcess() { /* Пробегаеться по списку процессов и приаттачиваеться к ним, потом удаляет заданные модули в PEB этих процессов */ struct _SYSTEM_PROCESS *pBuff = NULL; struct _SYSTEM_PROCESS *pBuff2 = NULL; ULONG uBuffSize = 0x100000; NTSTATUS nStat; PEPROCESS peCurProc; PEPROCESS peProcess; PPEB_LDR_DATA pLdrData; PLIST_ENTRY pUserModuleListHead; PLIST_ENTRY pUserModuleListPtr; UNICODE_STRING usStr1; UNICODE_STRING usStr2; UNICODE_STRING usModuleName; ANSI_STRING szModuleName; ANSI_STRING process_name; ANSI_STRING szThisProcessName; char szMyModule[]="ntdll.dll"; // Получаем EPROCESS текущего процесса peCurProc = PsGetCurrentProcess(); // Переводим имя образа в верхний регистр RtlInitAnsiString(&szThisProcessName,peCurProc->ImageFileName); // UPCASE OUR PROCESSNAME RtlAnsiStringToUnicodeString(&usStr1,&szThisProcessName,TRUE); RtlInitUnicodeString(&usStr2,L""); RtlUpcaseUnicodeString(&usStr2,&usStr1,TRUE); RtlUnicodeStringToAnsiString(&szThisProcessName,&usStr2,TRUE); RtlFreeUnicodeString(&usStr2); RtlFreeUnicodeString(&usStr1); pBuff = ExAllocatePool(PagedPool,uBuffSize); nStat = ZwQuerySystemInformation(5,pBuff,uBuffSize,&uBuffSize); if (nStat == STATUS_SUCCESS || nStat == STATUS_INFO_LENGTH_MISMATCH) { pBuff2 = ExAllocatePool(PagedPool,uBuffSize); nStat = ZwQuerySystemInformation(5,pBuff2,uBuffSize,&uBuffSize); PrintStatus("ZwQuerySystemInformation",nStat); DbgPrint("%d",uBuffSize); if (NT_SUCCESS(nStat)) { struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)pBuff2; struct _SYSTEM_PROCESSES *prev = NULL; while(curr) { // UPCASE ALL PROCESSES NAMES RtlUnicodeStringToAnsiString(&process_name, &(curr->ProcessName), TRUE); RtlAnsiStringToUnicodeString(&usStr1,&process_name,TRUE); RtlUpcaseUnicodeString(&usStr2,&usStr1,TRUE); RtlFreeAnsiString(&process_name); RtlUnicodeStringToAnsiString(&process_name,&usStr2,TRUE); RtlFreeUnicodeString(&usStr1); RtlFreeUnicodeString(&usStr2); // Запущенный процесс szThisProcessName.Buffer // Процесс со списка process_name.Buffer //######################################################################################################################### if (strstr(process_name.Buffer,szThisProcessName.Buffer)) { DbgPrint("Dont Attach to our process"); } else { nStat = PsLookupProcessByProcessId((HANDLE)curr->ProcessId,&peProcess); if (NT_SUCCESS(nStat)) { __try { KeAttachProcess(peProcess); DbgPrint("0x0%X Ldr",&peProcess->Peb->Ldr); KeDetachProcess(); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("KeAttachProcess 0x%X",&peProcess->Peb); } } } //######################################################################################################################### RtlFreeAnsiString(&process_name); if(curr->NextEntryDelta) { ((char *)curr += curr->NextEntryDelta); } else { curr = NULL; } } ExFreePool(pBuff2); } } } Какие будут идеи ?
pEntry - указывает на элемент который тебе надо удалить из списка. Код (Text): (pEntry->Blink)->Flink = pEntry->Flink; (pEntry->Flink)->Blink = pEntry->Blink; Ну или воспользоваться стандартным макросом RemoveEntryList, код которого повто
это же элементарно по сравнению со всем остальным кодом =) главное четко себе представлять как они работают. Есть поле Flink, указывающее на следующий элемент (Forward link) и Blink, указывающее на предыдущий элемент (Backward link). Чтобы удалить элемент из списка, достаточно чтобы предыдущий и следующий элементы от удаляемого ссылались друг на друга. Это как раз делает приведенный n0name код.
Разберись со списками, они везде. Ручку с бумагой в зубы и фигачим рисуночки ) http://msk.nestor.minsk.by/kg/2004/39/kg43902.html http://beta.delta-z.com/index.php/archives/222 http://algolist.ncstu.ru/ds/basic/simple_list.php
Это понятно, я говорю где данные храняться ? =( Блин яд от этого хардкор кодинга чёто плохо себя чуствую :-(
ты показываешь базовую структуру LIST_ENTRY. Все системные списки выглядят примерно так: Код (Text): struct LIST { LIST_ENTRY List; void* data; }; Короче LIST_ENTRY содержит только указатели. А списочные структуры в себя её включают в качестве первого элемента. Если у тебя есть указатель на LIST* но в виде LIST_ENTRY* тебе надо сделать так: Код (Text): LIST_ENTRY* YourPointer; ((LIST*)YourPointer)->data // это будут данные Мой пример абстрактен, но ты должен был понять главное ) Ложки нет блин, меня понесло... короче ты понял надеюсь)
typedef struct _LDR_MODULE { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_MODULE, *PLDR_MODULE; Смотри - у тебя есть указатель на структуру _LDR_MODULE . InMemoryOrderModuleList - это и есть тот LIST_ENTRY, из которого ты получаешь предыдущую/следующую структуру. А остальные данные хранятся в самой _LDR_MODULE.
пойду убьюсь об стену...не лучше посплю...убьюсь и посплю...запутался что сначало ? убиться или поспать ?
мдя)) короче. LIST_ENTRY - это шаблонная мини-структурка. Она содержит только указатели вперед и назад. сами данные хранятся после этих указателей сразу же. Для удобства определяют "оберточные" структуры типа LDR_MODULE.
Вспомнилась знатная задача Лбиса Керолла. Предположим человек если человек не ел 7 суток, то он помирает, то же самое и для сна. Один человек не ел и не спал почти неделю. Что надо сделать сначала - поесть, или поспать?
Ну а я твоего поста не видел, когда писал. А стирать не хотелось. WIN32 Вот кое-что нашёл в одном из сорцов. И у MS_Rem-а в статьях про перехват вроде был код на делфи. Код (Text): GetAllModule proc assume fs:nothing mov eax, fs:[30h] mov eax, [eax+PEB.LoaderData] add eax, PEB_LDR_DATA.InLoadOrderModuleList xor edx,edx xor ecx,ecx mov eax,[eax] @1: push eax ;eax - óêàçàòåëü íà LDR_MODULE call InterceptAllFunctionInModule mov eax, [eax+LDR_MODULE.InLoadOrderModuleList.Flink] mov esi, [eax+LDR_MODULE.BaseAddress] cmp eax,edx jb last_module inc ecx mov edx,eax jmp @1 last_module: ret GetAllModule endp InterceptAllFunctionInModule proc LDR_:dword pushad mov eax,LDR_ lea edi,[eax+LDR_MODULE.BaseDllName] mov edi,[edi+UNICODE_STRING.Buffer] ;pointer on module name mov module_name_off,edi .......