void HookZwResumeThread() { dwHashPid = NULL; dwPidCount = 0; dwAddrRthProc = (DWORD)&JmpToHookRthProc; DWORD dwAddr = (DWORD)&dwAddrRthProc; PZwResumeThread ZwResumeThread = (PZwResumeThread)GetProcAddressEx( NULL, 5, 0xACF8BF39 ); LPVOID lpMem; LPVOID lpPtr; lpPtr = (LPVOID)ZwResumeThread; ProtectPage( lpPtr, PAGE_EXECUTE_READWRITE ); lpMem = pVirtualAllocEx( (HANDLE)-1, NULL, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if ( lpMem == NULL ) { return; } ZwResumeThreadReal = (PZwResumeThread)lpMem; m_memcpy( lpMem, lpPtr, 15 ); lpPtr = (LPVOID)((DWORD)lpPtr + 5 ); if ( *(BYTE*)lpPtr == 0xBA ) // win xp and up { lpPtr = (LPVOID)((DWORD)lpPtr + 1 ); m_memcpy( lpPtr, &dwAddr, 4 ); } else { if ( *(BYTE*)lpPtr == 0x8D ) //win2000 { *(BYTE*)lpPtr = 0x68; dwAddr = (DWORD)&ZwResumeThreadHook; lpPtr = (LPVOID)((DWORD)lpPtr + 1 ); m_memcpy( lpPtr, &dwAddr, 4 ); lpPtr = (LPVOID)((DWORD)lpPtr + 6 ); *(BYTE*)lpPtr = 0x00; } else { MemFree( lpMem ); } } ProtectPage( ZwResumeThread, PAGE_EXECUTE_READ ); return; }
template <typename TAlloc> inline void JITThunkEmitter<TAlloc>::FreeThunk(uintptr_t thunkAddress) { AutoCriticalSection autoCs(&this->cs); BVIndex thunkIndex = GetThunkIndexFromAddress(thunkAddress); if (thunkIndex >= this->freeThunks.Length() || this->freeThunks.TestAndSet(thunkIndex)) { Assert(UNREACHED); this->firstBitToCheck = 0; return; } if (thunkIndex < firstBitToCheck) { this->firstBitToCheck = thunkIndex; } if (CONFIG_FLAG(OOPCFGRegistration)) { #if ENABLE_OOP_NATIVE_CODEGEN if (JITManager::GetJITManager()->IsJITServer()) { HANDLE fileHandle = nullptr; PVOID baseAddress = nullptr; bool found = this->codeAllocator->GetFileInfo((PVOID)thunkAddress, &fileHandle, &baseAddress); AssertOrFailFast(found); this->threadContext->SetValidCallTargetFile((PVOID)thunkAddress, fileHandle, baseAddress, false); } else #endif { this->threadContext->SetValidCallTargetForCFG((PVOID)thunkAddress, false); } } uintptr_t pageStartAddress = GetThunkPageStart(thunkAddress); if (IsThunkPageEmpty(pageStartAddress)) { this->codeAllocator->Free((PVOID)pageStartAddress, AutoSystemInfo::PageSize, MEM_DECOMMIT); } else { char * localAddress = (char *)this->codeAllocator->AllocLocal((PVOID)thunkAddress, ThunkSize); if (localAddress == nullptr) { return; } UnprotectPage(localAddress); memset(localAddress, 0xCC, ThunkSize); ProtectPage(localAddress); this->codeAllocator->FreeLocal(localAddress); } FlushInstructionCache(this->processHandle, (PVOID)thunkAddress, ThunkSize); }
// record one page VOID SANDBOX::RecordPage(const char * page) { const char * pageFrameStart = _pages[page]; if (pageFrameStart != NULL) { return; // already recorded } pageFrameStart = AllocatePage(page); memcpy(const_cast<char *>(pageFrameStart), page, PageSize); ProtectPage(pageFrameStart); }
void HookZwQueryDirectoryFile() { dwAddrDirProc = (DWORD)&JmpToHookDirProc; DWORD dwAddr = (DWORD)&dwAddrDirProc; PZwQueryDirectoryFile ZwQueryDirectoryFile = (PZwQueryDirectoryFile)GetProcAddressEx( NULL, 5, 0x5F8B35D6 ); LPVOID lpMem; LPVOID lpPtr; lpPtr = (LPVOID)ZwQueryDirectoryFile; if ( lpPtr == NULL ) { return; } ProtectPage( lpPtr, PAGE_EXECUTE_READWRITE ); lpMem = pVirtualAllocEx( (HANDLE)-1, NULL, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE ); if ( lpMem == NULL ) { return; } ZwQueryDirectoryFileReal = (PZwQueryDirectoryFile)lpMem; m_memcpy( lpMem, lpPtr, 15 ); lpPtr = (LPVOID)((DWORD)lpPtr + 5 ); if ( *(BYTE*)lpPtr == 0xBA ) // win xp and up { lpPtr = (LPVOID)((DWORD)lpPtr + 1 ); m_memcpy( lpPtr, &dwAddr, 4 ); } else { if ( *(BYTE*)lpPtr == 0x8D ) //win2000 { *(BYTE*)lpPtr = 0x68; dwAddr = (DWORD)&ZwQueryDirectoryFileHook; lpPtr = (LPVOID)((DWORD)lpPtr + 1 ); m_memcpy( lpPtr, &dwAddr, 4 ); lpPtr = (LPVOID)((DWORD)lpPtr + 6 ); *(BYTE*)lpPtr = 0x00; } else { MemFree( lpMem ); } } ProtectPage( ZwQueryDirectoryFile, PAGE_EXECUTE_READ ); return; }
template <typename TAlloc> inline uintptr_t JITThunkEmitter<TAlloc>::CreateThunk(uintptr_t entryPoint) { AutoCriticalSection autoCs(&this->cs); if(EnsureInitialized() == NULL) { return NULL; } // find available thunk BVIndex thunkIndex = this->freeThunks.GetNextBit(this->firstBitToCheck); if (thunkIndex == BVInvalidIndex) { return NULL; } uintptr_t thunkAddress = GetThunkAddressFromIndex(thunkIndex); uintptr_t pageStartAddress = GetThunkPageStart(thunkAddress); char * localPageAddress = (char *)this->codeAllocator->AllocLocal((PVOID)pageStartAddress, AutoSystemInfo::PageSize); if (localPageAddress == nullptr) { return NULL; } if (IsThunkPageEmpty(pageStartAddress)) { if (this->codeAllocator->AllocPages((PVOID)pageStartAddress, 1, MEM_COMMIT, PAGE_EXECUTE_READ, true) == nullptr) { this->codeAllocator->FreeLocal(localPageAddress); return NULL; } UnprotectPage(localPageAddress); memset(localPageAddress, 0xCC, AutoSystemInfo::PageSize); } else { UnprotectPage(localPageAddress); } EncodeJmp(localPageAddress, thunkAddress, entryPoint); ProtectPage(localPageAddress); this->codeAllocator->FreeLocal(localPageAddress); if (CONFIG_FLAG(OOPCFGRegistration)) { #if ENABLE_OOP_NATIVE_CODEGEN if (JITManager::GetJITManager()->IsJITServer()) { HANDLE fileHandle = nullptr; PVOID baseAddress = nullptr; bool found = this->codeAllocator->GetFileInfo((PVOID)thunkAddress, &fileHandle, &baseAddress); AssertOrFailFast(found); this->threadContext->SetValidCallTargetFile((PVOID)thunkAddress, fileHandle, baseAddress, true); } else #endif { this->threadContext->SetValidCallTargetForCFG((PVOID)thunkAddress); } } this->firstBitToCheck = (thunkIndex + 1 < JITThunkEmitter<TAlloc>::TotalThunkCount) ? thunkIndex + 1 : 0; this->freeThunks.Clear(thunkIndex); if (!FlushInstructionCache(this->processHandle, (PVOID)thunkAddress, ThunkSize)) { return NULL; } return thunkAddress; }