Как мне найти адрес указывающий внутрь ntdll сразу после того как загрузчик передал управление на мой EntryPoinnt. Можно ли мне гарантированно расчитывать, что в EDX будет указатель на KiFastSystemCallRet либо может в других регистрах или стеке находятся указатели на ntdll. Желательно, чтобы способ работал на всей линейке NT.
Я хочу вообще без импорта обойтись. Все API которые мне нужны я потом динамически подгружу через LdrLoadDll. Мне нужен гарантированный указатель внутрь ntdll.
Код (Text): static __declspec (naked) HMODULE GetNtdllBase() // x86 { __asm { mov eax, fs:[30h] mov eax, [eax + 0Ch] mov eax, [eax + 1Ch] mov eax, [eax + 8] ret } }
да, тем более, что ntdll.dll каким-то магическим образом может оказаться не на предполагаемом месте в списке... нужно для верности сравнивать имена библиотек с "ntdll.dll" или с ее хешом)
Код (Text): ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;функа GetModuleBase ;получение базы модулей (системных длл) через PEB ;ВХОД: ; push dword - размер строки (имя модуля) в unicode ; push dword - хэш от этой строки ;ВЫХОД: ; EAX - база нужного модуля ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx GetModuleBase: ;assume fs: flat pushad mov ebp, esp mov edx, dword ptr fs:[30h] ;get a pointer to the PEB mov edx, dword ptr [edx + 0Ch] ;get PEB->Ldr mov edx, dword ptr [edx + 14h] ;get the first module from the InMemoryOrder module list next_mod: mov esi, dword ptr [edx + 28h] ;get pointer to modules name (unicode string) push dword ptr [ebp + 28h] ;push down the length we want to check pop ecx ;set ecx to this length for the loop xor edi, edi ;clear edi which will store the hash of the module name loop_modname: xor eax, eax lodsb cmp al, 'a' ;some versions of Windows use lower case module names jl not_lowercase sub al, 20h ;if so normalise to uppercase not_lowercase: ror edi, 13 ;rotate right our hash value add edi, eax ;add the next byte of the name to the hash loop loop_modname ;loop until we have read enough cmp edi, dword ptr [ebp + 24h] ;compare the hash with that of module (kernel32.dll etc); mov ebx, dword ptr [edx + 10h] ;get this modules base address mov edx, dword ptr [edx] ;get the next module jne next_mod ;if it doesn't match, process the next module mov dword ptr [esp + 1Ch], ebx popad ret 04 * 2 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;конец функции GetModuleBase ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ;Для нтдлл.длл вызывать так: push 12h push 3CFA685Dh call GetModuleBase
Можно через сех: Код (Text): push ebp Call @f Safe: pop dword ptr fs:[0] lea esp,[esp + 2*4] pop ebp jmp Ip @@: Call @f ; ; Fast SEH. ; ; EXCEPTION_DISPOSITION ; (*PEXCEPTION_ROUTINE) ( // [esp] ~ nt!ExceptionHandler2() ; IN EXCEPTION_RECORD *ExceptionRecord, // [esp + 4] ; IN PVOID EstablisherFrame, // [esp + 2*4] ; IN OUT CONTEXT *ContextRecord, // [esp + 3*4] ; IN OUT PVOID DispatcherContext // [esp + 4*4] ; ); mov eax,dword ptr [esp] mov esp,dword ptr [esp + 2*4] jmp Safe @@: push dword ptr fs:[0] mov dword ptr fs:[0],esp hlt Ip: А если лодер нэйтивный, то адрес возврата будет в нтдлл, независимо от типа колбека.