Не совсем понятно почему значения LDR_DATA_TABLE_ENTRY.SizeOfImage и ZwQueryVirtualMemory!MEMORY_BASIC_INFORMATION.RegionSize отличаются друг от друга.. Например у ntdll: RegionSize - 69000h SizeOfImage - af000h И есть-ли третий способ получения размера памяти занимаемого модулем.. ?
LDR_DATA_TABLE_ENTRY.SizeOfImage содержит полный размер спроецированного модуля. MEMORY_BASIC_INFORMATION.RegionSize возвращает размер блока памяти, в котором страницы имеют ожинаковые атрибуты, чтобы получить полный размер нужно перечислять в цикле блоки памяти последовательно, пока MEMORY_BASIC_INFORMATION.AllocationBase одинаково.
Вроди сделал как описал.. Код (Text): start proc local buffer[1024]:byte local ReturnLength:dword local MemoryInformation:MEMORY_BASIC_INFORMATION local ImageBase:dword local RegionLenght:dword assume fs:nothing mov ebx,fs:[TEB.Peb] mov ebx,PEB.Ldr[ebx] mov ebx,PEB_LDR_DATA.InLoadOrderModuleList.Flink[ebx] mov ebx,LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink[ebx] mov edi,LDR_DATA_TABLE_ENTRY.SizeOfImage[ebx] mov esi,LDR_DATA_TABLE_ENTRY.DllBase[ebx] mov RegionLenght,0 mov ImageBase,0 @@: invoke ZwQueryVirtualMemory,-1,esi,MemoryBasicInformation,addr MemoryInformation,sizeof MEMORY_BASIC_INFORMATION,addr ReturnLength or eax,eax jnz @F mov eax,MemoryInformation.RegionSize add RegionLenght,eax add esi,eax mov eax,MemoryInformation.AllocationBase .if ImageBase == 0 mov ImageBase,eax jmp @B .endif cmp ImageBase,eax je @B @@: invoke wsprintfA,addr buffer,$CTA0("RegionSize: 0%08xh\nSizeOfImage: 0%08xh\n"),RegionLenght,edi invoke MessageBox,0,addr buffer,$CTA0("SizeOfImage"),0 invoke ExitProcess,0 start endp А результаты суравно не идентичны RegionSize: 001b10000h SizeOfImage: 0000af000h Откуда надежнее брать эту инфу ? А то байтом меньще или байтом больще - могет привести к весьма печальным последствиям
Flasher Если столь кривая реализация, это не значит что кривой алгоритм На последнем проходе, когда следующий блок берётся за образом модуля ты добавляешь его размер к результату и только потом проверяешь базу, нужно наоборот.
Flasher Модуль в памяти понятие расплывчатое, если он не меняетсо, то лучше юзоть чтение блоков памяти, в идеале считать с диска модуль и размер определить, реально защита может выполнить хитрые манипуляции с проекцией, поэтому нужно знать зачем понадобилось определять его размер.
Clerk Код (Text): KiFastSystemCall -> ZwProtectVirtualMemory проверка mov eax,(второй параметор) mov eax,dword ptr [eax] .if eax > (начальный адрес модуля) && eax < (конечный адрес модуля) jmp _ne_xorosho .endif Т.е. таким макаром противодействовать хуку внутри процесса.
Flasher Бесполезно, мало того что обычно это из другого процесса делоют, но если даже в текущем процессе, то вызов ведь через прерывание сервиса, KiFastSystemCallRet в таком случае не будет исполнена.
Flasher Может стоит бряков поставить там, где есть вероятность что сплайснут, а в хэндлере исключений исполнять инструкцию оригинальную и возвращатьсо ? В таком случае либо не удасться сплайснуть, либо будет останов в коде перехватчика.
Clerk, вероятных точек сплайсинга через чур много, поэтому нуны более универсальные методы. Еще была идея в самом начале получить чексум модуля в памяти, а потом в цикле проверять, но не сработало, как оказалось - контрольная суммая все время меняется.
Вопрос из той же оперы: Можно ли изменять размеры памяти, занимаегого модулем? Есть например у меня свой модуль, я хочу чтобы каждый раз когда его вызывают, он занимал не статистический размер памяти, а динамический. Можно конечно найти в ldr свой модуль, генерить рандомное число и прибавить к SizeOfImage, но могет есть другие пути решения задачи?