Да вот дело в том, что когда я сплайсом хукал и хуки ставил на свой код - то управление передавалось и код не падал именно так, по крайней мере его можно было потрасиировать. А тут через экспорт хукаю - и падает. Clerk контекст в данном случае это что? Состояние всех регистров?
значит так. Бряк на выполнение ставлю след. образом: Код (Text): kd> ba e 1 0x30004 дальше бряк срабатывает и я смотрю PTE Код (Text): Breakpoint 3 hit 001b:00030004 8bec mov ebp,esp kd> !pte 0x30004 VA 00030004 PDE at C0600000 PTE at C0000180 contains 0000000020631867 contains 800000001FEAA867 pfn 20631 ---DA--UWEV pfn 1feaa ---DA--UW-V Дальше нажимаю F11 и попадаю почему то сюда: Код (Text): kd> t ntdll!KiUserExceptionDispatcher+0x1: 001b:77ba6449 8b4c2404 mov ecx,dword ptr [esp+4] Интересно, почему именно KiUserExceptionDispatcher+0x1 а не просто KiUserExceptionDispatcher ? дальше смотрю стек вызова Код (Text): kd> k ChildEBP RetAddr 0015fbc0 00030004 ntdll!KiUserExceptionDispatcher+0x1 WARNING: Frame IP not in any known module. Following frames may be wrong. 0015fb3c 0086dd9e 0x30004 0015fbc0 0086e479 winlogon!WinMain+0x40 0015fc50 77351194 winlogon!_initterm_e+0x1a1 0015fc5c 77bbb495 kernel32!BaseThreadInitThunk+0xe 0015fc9c 77bbb468 ntdll!__RtlUserThreadStart+0x70 0015fcb4 00000000 ntdll!_RtlUserThreadStart+0x1b смотрю регистры Код (Text): kd> r eax=0015fbb0 ebx=00000001 ecx=00000065 edx=00000004 esi=001e186c edi=00000000 eip=77ba6449 esp=0015f838 ebp=0015fbc0 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!KiUserExceptionDispatcher+0x1: 001b:77ba6449 8b4c2404 mov ecx,dword ptr [esp+4] ss:0023:0015f83c=0015f85c пробую Код (Text): kd> .lastevent Last event: <no event> kd> .exr -1 Last event was not an exception kd> .ecxr Unable to get exception context, HRESULT 0x8000FFFF Что то он толи этот эксепщен не отлавливает, толи не эксепшен это вовсе. Подскажите.
Код (Text): PDE at C0600000 PTE at C0000180 contains 0000000020631867 contains 800000001FEAA867 pfn 20631 ---DA--UWEV pfn 1feaa ---DA--UW-V ---DA--UW-V так страница же не исполняемая. Судя по всему, исключение происходит из-за этого.
Код (Text): kd> .exr 0026FA9C ExceptionAddress: 00030004 ExceptionCode: c0000005 (Access violation) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000008 Parameter[1]: 00030004 Attempt to execute non-executable address 00030004 kd> .cxr 0026FAB8 eax=0026fdb8 ebx=001cb144 ecx=003f1ec8 edx=77b664f4 esi=003f1ec8 edi=00000000 eip=00030004 esp=0026fd9c ebp=0026fdc8 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010302 001b:00030004 8bec mov ebp,esp Уже вижу что память не исполняемая. Как это поправить?
Аа у вас PAE. Тогда старший бит в PTE. Можно попробовать MmProtectMdlSystemAddress(), хотя мб с пользовательским ап работать не будет.
совершенно верно, MmProtectMdlSystemAddress уже попробовал - БСОДит. Полазил по форумам и нашел кодес тут http://www.rootkit.com/board.php?thread=8073&did=edge0&disp=8073 Код (Text): NTSTATUS ChangePageProtection(PVOID BaseAddress, CLIENT_ID TargetClientId) { HANDLE ProcessHandle = 0; PEPROCESS TargetProcess; OBJECT_ATTRIBUTES ObjectAttributes; PMDL pMdl = NULL; MDL_DATA_PAGE_PROTECTION Mdl_Data; PMDL_DATA_PAGE_PROTECTION pMdl_Data; // KAPC_STATE ApcState; ////////////////////////////////////////////////// __try { /***************************************************** // THIS CODE ISN'T USED BUT CAN BE IF YOU WANT TO ATTACH // Retrieve the EPROCESS structure for the target process if(!NT_SUCCESS(PsLookupProcessByProcessId( (ULONG) TargetClientId.UniqueProcess, // ULONG ProcessId &TargetProcess))) // OUT PEPROCESS *EProcess { return 0; } // Attach to the process KeStackAttachProcess ( &TargetProcess->Pcb, // PKPROCESS Process &ApcState // OUT PKAPC_STATE ApcState ); *****************************************************/ // Prepare OBJECT_ATTRIBUTES structure InitializeObjectAttributes( &ObjectAttributes, // OUT POBJECT_ATTRIBUTES NULL, // PUNICODE_STRING ObjectName OBJ_KERNEL_HANDLE || OBJ_CASE_INSENSITIVE, // ULONG Attributes NULL, // HANDLE RootDirectory NULL // PSECURITY_DESCRIPTOR SecurityDescriptor ); // Get a process handle // Do not use ZwClose on an active process handle // The return definition for XP / Win2k will be // INVALID_KERNEL_HANDLE / STATUS_HANDLE_NOT_CLOSABLE ZwOpenProcess(&ProcessHandle, PROCESS_ALL_ACCESS, &ObjectAttributes, &TargetClientId); /*****************************************************/ RtlZeroMemory(&Mdl_Data, sizeof MDL_DATA_PAGE_PROTECTION); // Allocate an MDL large enough to hold our temporary // MDL_DATA_PAGE_PROTECTION structure pMdl = IoAllocateMdl( &Mdl_Data, // PVOID VirtualAddress sizeof MDL_DATA_PAGE_PROTECTION, // ULONG Length FALSE, // BOOLEAN SecondaryBuffer FALSE, // BOOLEAN ChargeQuota NULL // IN OUT PIRP Irp OPTIONAL ); if (!pMdl) return STATUS_UNSUCCESSFUL; // Lock the physical pages mapped by the virtual address range into memory MmProbeAndLockPages ( pMdl, // IN OUT PMDL MemoryDescriptorList KernelMode, // KPROCESSOR_MODE AccessMode IoWriteAccess // LOCK_OPERATION Operation ); // Map the pages into the process pMdl_Data = (PMDL_DATA_PAGE_PROTECTION) MmMapLockedPagesSpecifyCache( pMdl, // PMDL MemoryDescriptorList UserMode, // KPROCESSOR_MODE AccessMode MmCached, // MEMORY_CACHING_TYPE CacheType NULL, // PVOID BaseAddress FALSE, // ULONG BugCheckOnFailure NormalPagePriority // MM_PAGE_PRIORITY Priority ); /*****************************************************/ ////////////////////////////////////////////////// // Change the protection on the region // from PAGE_EXECUTE_WRITECOPY to PAGE_EXECUTE_READWRITE pMdl_Data->BaseAddress = BaseAddress; pMdl_Data->ProtectSize = PAGE_SIZE; // Not exported by Win2K ntoskrnl, obtain address by // parsing export directory of Ntdll. pZwProtectVirtualMemory( ProcessHandle, // IN HANDLE ProcessHandle &pMdl_Data->BaseAddress, // IN OUT PVOID *BaseAddress &pMdl_Data->ProtectSize, // IN OUT PULONG ProtectSize PAGE_EXECUTE_READWRITE, // IN ULONG NewProtect &pMdl_Data->OldProtect // OUT PULONG OldProtect ); ////////////////////////////////////////////////// ////////////////////////////////////////////////// // CLEANUP: // Unmap the pages and free the MDL MmUnmapLockedPages(pMdl_Data, pMdl); MmUnlockPages(pMdl); IoFreeMdl(pMdl); /***************************************************** // THIS CODE ISN'T USED BUT CAN BE IF YOU WANT TO ATTACH // Dereference from PsLookupProcessByProcessId ObDereferenceObject(TargetProcess); // Detach from the process KeUnstackDetachProcess ( &ApcState // PKAPC_STATE ApcState ); *****************************************************/ //============================================================= } __except (EXCEPTION_EXECUTE_HANDLER) { DbgPrint ("\n ERROR ExceptionCode: %x\n", GetExceptionCode() ); return STATUS_UNSUCCESSFUL; } // end __try{ return STATUS_SUCCESS; } но после вызва pZwProtectVirtualMemory с BaseAddress=0x30000 возвращается статус STATUS_CONFLICTING_ADDRESSES В чем может быть проблема снова?
ntcdm Для работы с пользовательским ап есть соответствующие сервисы. Во первых менеджер памяти манипулирует VAD для приватной памяти. Выделять пользовательскую память через мдл это изврат.
Во многих статьях, в частности вот тут Starting a Process from KernelMode именно через MDL и выделяется и на XP у меня чудненько работает. Кстати, может сейчас рискну выделить память через ZwAllocateVirtualMemory. о результатах отпишу
ntcdm Не верная инфа расползается по инету как зараза. Если на разных ресурсах написано одно и тоже, это не значит что оно верно.
Ну что же, выделив память след. образом: Код (Text): SIZE_T nRegionSize = PAGE_SIZE; ZwAllocateVirtualMemory( NtCurrentProcess(), (PVOID*)&pVirtualMemory, NULL, &nRegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); Я смог выделить память в нужном мне процессе так, что уже ексепшен не вываливается !!! тоесть мой код отрабатывает нормально!!! спасибо Клерку за подсказку!!!!! Зато еще у меня осталась проблема с тем, что пропатчив экспорт библиотеки msvcrt.dll она поменялась в других процессах. патчу таблицу экспорта след. образом: Код (Text): PIMAGE_DOS_HEADER dosHeader; PIMAGE_NT_HEADERS pNTHeader; DWORD exportsStartRVA; dosHeader = (PIMAGE_DOS_HEADER) ImageInfo->ImageBase; pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew ); // First, verify that the e_lfanew field gave us a reasonable // pointer, then verify the PE signature. if ( pNTHeader->Signature == IMAGE_NT_SIGNATURE ) { exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (exportsStartRVA) { PIMAGE_EXPORT_DIRECTORY pExportDirectory = MakePtr( PIMAGE_EXPORT_DIRECTORY, dosHeader, exportsStartRVA ); PDWORD pdwAddressOfNames = MakePtr(PDWORD, dosHeader, pExportDirectory->AddressOfNames); PDWORD pdwAddressOfFunctions = MakePtr(PDWORD, dosHeader, pExportDirectory->AddressOfFunctions); PWORD pdwAddressOfOrdinals = MakePtr(PWORD, dosHeader, pExportDirectory->AddressOfNameOrdinals); //WORD dwOrdinalBase = pExportDirectory->Base; ULONG i=0; PCHAR pcName; PDWORD pFunc; while(i<pExportDirectory->NumberOfNames) { if (pdwAddressOfNames[i] != 0 ) { pcName = MakePtr(PCHAR, dosHeader, pdwAddressOfNames[i]); if (_stricmp(pcName, "memset") == 0) { WORD funcIndex = pdwAddressOfOrdinals[i]; pFunc = MakePtr(PDWORD, dosHeader, pdwAddressOfFunctions[funcIndex]); BYTE* ptrmem = (BYTE*)g_pVirtualMemory+4; int i; for (i=0;i<0x52;i++) { if (*(DWORD*)ptrmem == 0x0AABBCCDD) //marker for old caller { *(DWORD*)ptrmem = (DWORD)pFunc; } ptrmem++; } DWORD CR0Reg; __asm{ mov eax,CR0 mov CR0Reg,eax and eax,0FFFEFFFFh mov CR0,eax } pdwAddressOfFunctions[funcIndex] = (PBYTE)g_pVirtualMemory+4 - (PBYTE)dosHeader; __asm { mov eax,CR0Reg mov CR0,eax } } } i++; } Клерк, ты писал что файловые проекции не разделяемы. Почему же у меня меняется эта ДЛЛ-ка в других процессах. Какие будут предложения чтобы исправить?
Использую показанный кодес в нотификаторе Image Load Notify Routine. Сначала отслеживаю загрузку winlogon.exe и выделяю память в нем. Затем отслеживаю загрузку msvcrt.dll в процесс Winlogon.exe и делаю патч таблицы экспорта. Эта библиотека грузится в другие процессы но в других процессах я ее уже не патчу. Код (Text): VOID ImageLoadNotifyRoutine(IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId, IN PIMAGE_INFO ImageInfo) { DBGPRINT(("ImageLoadNotifyRoutine name: %wZ at base %X\r\n", FullImageName, ImageInfo->ImageBase)); // Setup the name of the DLL to target if (safe_wcsstr(FullImageName, L"winlogon.exe" ) != NULL) { if (g_nWinlogonProcessId == 0) { DbgBreakPoint(); g_nWinlogonProcessId = (ULONG)ProcessId; g_pWinlogonImageBase = ImageInfo->ImageBase; DBGPRINT(("ImageLoadNotifyRoutine Winlogon found with pid=%d, Session=%d\r\n", ProcessId, PsGetCurrentProcessSessionId())); //PMDL pMdl = NULL; BYTE *pVirtualMemory = NULL; PHYSICAL_ADDRESS phBegin,phEnd,phSkip; phBegin.QuadPart = 0; phEnd.QuadPart = (LONGLONG)-1; phSkip.QuadPart = PAGE_SIZE; DWORD dwAllocationSize; __try { dwAllocationSize = PAGE_SIZE; { { pVirtualMemory = NULL; SIZE_T nRegionSize = PAGE_SIZE; ZwAllocateVirtualMemory( NtCurrentProcess(), (PVOID*)&pVirtualMemory, NULL, &nRegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if (pVirtualMemory) { *((DWORD*)pVirtualMemory) = 1; memcpy(pVirtualMemory + 4, my_memset2, 0x52); g_pVirtualMemory = pVirtualMemory; BYTE* ptrmem = pVirtualMemory+4; //(*(PDWORD) (pCode + i + 1)) = (DWORD)ptrmem; for (int i=0;i<0x52;i++) { if ( *(DWORD*)ptrmem == 0x0EEFFCCBB) //marker for variable { *(DWORD*)ptrmem = (DWORD)pVirtualMemory; } else if (*(DWORD*)ptrmem == 0x0AABBCCDD) //marker for old caller { //*(DWORD*)ptrmem = (DWORD)pOldFunction; } ptrmem++; } } } } __except(EXCEPTION_EXECUTE_HANDLER) { DBGPRINT(("ImageLoadNotifyRoutine woops! exception 1 %X\r\n", GetExceptionCode())); } } } else if ((ULONG)ProcessId == g_nWinlogonProcessId && safe_wcsstr(FullImageName, L"msvcrt.dll" ) != NULL) { DBGPRINT(("ImageLoadNotifyRoutine loading dll name %wZ for winlogon with pid=%d, Session=%d\r\n", FullImageName, g_nWinlogonProcessId, PsGetCurrentProcessSessionId())); DbgBreakPoint(); PIMAGE_DOS_HEADER dosHeader; PIMAGE_NT_HEADERS pNTHeader; DWORD exportsStartRVA; dosHeader = (PIMAGE_DOS_HEADER) ImageInfo->ImageBase; pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew ); // First, verify that the e_lfanew field gave us a reasonable // pointer, then verify the PE signature. if ( pNTHeader->Signature == IMAGE_NT_SIGNATURE ) { exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (exportsStartRVA) { PIMAGE_EXPORT_DIRECTORY pExportDirectory = MakePtr( PIMAGE_EXPORT_DIRECTORY, dosHeader, exportsStartRVA ); PDWORD pdwAddressOfNames = MakePtr(PDWORD, dosHeader, pExportDirectory->AddressOfNames); PDWORD pdwAddressOfFunctions = MakePtr(PDWORD, dosHeader, pExportDirectory->AddressOfFunctions); PWORD pdwAddressOfOrdinals = MakePtr(PWORD, dosHeader, pExportDirectory->AddressOfNameOrdinals); //WORD dwOrdinalBase = pExportDirectory->Base; ULONG i=0; PCHAR pcName; PDWORD pFunc; while(i<pExportDirectory->NumberOfNames) { if (pdwAddressOfNames[i] != 0 ) { pcName = MakePtr(PCHAR, dosHeader, pdwAddressOfNames[i]); if (_stricmp(pcName, "memset") == 0) { WORD funcIndex = pdwAddressOfOrdinals[i]; pFunc = MakePtr(PDWORD, dosHeader, pdwAddressOfFunctions[funcIndex]); BYTE* ptrmem = (BYTE*)g_pVirtualMemory+4; int i; for (i=0;i<0x52;i++) { if (*(DWORD*)ptrmem == 0x0AABBCCDD) //marker for old caller { *(DWORD*)ptrmem = (DWORD)pFunc; } ptrmem++; } DWORD CR0Reg; __asm{ mov eax,CR0 mov CR0Reg,eax and eax,0FFFEFFFFh mov CR0,eax } pdwAddressOfFunctions[funcIndex] = (PBYTE)g_pVirtualMemory+4 - (PBYTE)dosHeader; __asm { mov eax,CR0Reg mov CR0,eax } } } i++; } } } } } Затем ставлю бряк на точку ba e 1 0x30000 - он нормально отрабатывает в процессе winlogon.exe, тут все хорошо. Но!!! затем бряк по виртуальному адресу 0x30000 срабатывает в разных процессах - lsass, csrss, и других, в которых я памать не выделял. Естесвенно процессы падают. С чем это может быть связано?
ntcdm Не знаю как это происходит. Измените вручную таблицу экспорта, или вобще любой байт в пределах страницы и помотрите изменится ли он в другом процессе.