/*++ Routine Description: Replace the function pointer in a module's IAT. Parameters: Module - Module to use IAT from. ImportedModuleName - Name of imported DLL from which function is imported. ImportedProcName - Name of imported function. AlternateProc - Function to be written to IAT. OldProc - Original function. Return Value: S_OK on success. (any HRESULT) on failure. --*/ HRESULT PatchIat(HMODULE Module, PSTR ImportedModuleName, PSTR ImportedProcName, PVOID AlternateProc, PVOID *OldProc) { PIMAGE_DOS_HEADER DosHeader = ( PIMAGE_DOS_HEADER ) Module; PIMAGE_NT_HEADERS NtHeader; PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor; UINT Index; // _ASSERTE( Module ); // _ASSERTE( ImportedModuleName ); // _ASSERTE( ImportedProcName ); // _ASSERTE( AlternateProc ); NtHeader = ( PIMAGE_NT_HEADERS ) PtrFromRva( DosHeader, DosHeader->e_lfanew ); if( IMAGE_NT_SIGNATURE != NtHeader->Signature ) { return HRESULT_FROM_WIN32( ERROR_BAD_EXE_FORMAT ); } ImportDescriptor = ( PIMAGE_IMPORT_DESCRIPTOR ) PtrFromRva( DosHeader, NtHeader->OptionalHeader.DataDirectory [ IMAGE_DIRECTORY_ENTRY_IMPORT ].VirtualAddress ); // // Iterate over import descriptors/DLLs. // for ( Index = 0; ImportDescriptor[ Index ].Characteristics != 0; Index++ ) { PSTR dllName = ( PSTR ) PtrFromRva( DosHeader, ImportDescriptor[ Index ].Name ); if ( 0 == _strcmpi( dllName, ImportedModuleName ) ) { // // This the DLL we are after. // PIMAGE_THUNK_DATA Thunk; PIMAGE_THUNK_DATA OrigThunk; if ( ! ImportDescriptor[ Index ].FirstThunk || ! ImportDescriptor[ Index ].OriginalFirstThunk ) { return E_INVALIDARG; } Thunk = ( PIMAGE_THUNK_DATA ) PtrFromRva( DosHeader, ImportDescriptor[ Index ].FirstThunk ); OrigThunk = ( PIMAGE_THUNK_DATA ) PtrFromRva( DosHeader, ImportDescriptor[ Index ].OriginalFirstThunk ); for ( ; OrigThunk->u1.Function != NULL; OrigThunk++, Thunk++ ) { if ( OrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG ) { // // Ordinal import - we can handle named imports // ony, so skip it. // continue; } PIMAGE_IMPORT_BY_NAME import = ( PIMAGE_IMPORT_BY_NAME ) PtrFromRva( DosHeader, OrigThunk->u1.AddressOfData ); if ( 0 == strcmp( ImportedProcName, ( char* ) import->Name ) ) { // // Proc found, patch it. // DWORD junk; MEMORY_BASIC_INFORMATION thunkMemInfo; // // Make page writable. // VirtualQuery( Thunk, &thunkMemInfo, sizeof( MEMORY_BASIC_INFORMATION ) ); if ( ! VirtualProtect( thunkMemInfo.BaseAddress, thunkMemInfo.RegionSize, PAGE_EXECUTE_READWRITE, &thunkMemInfo.Protect ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } // // Replace function pointers (non-atomically). // if ( OldProc ) { *OldProc = ( PVOID ) ( DWORD_PTR ) Thunk->u1.Function; } #ifdef _WIN64 Thunk->u1.Function = ( ULONGLONG ) ( DWORD_PTR ) AlternateProc; #else Thunk->u1.Function = ( DWORD ) ( DWORD_PTR ) AlternateProc; #endif // // Restore page protection. // if ( ! VirtualProtect( thunkMemInfo.BaseAddress, thunkMemInfo.RegionSize, thunkMemInfo.Protect, &junk ) ) { return HRESULT_FROM_WIN32( GetLastError() ); } return S_OK; } } // // Import not found. // return HRESULT_FROM_WIN32( ERROR_PROC_NOT_FOUND ); } } // // DLL not found. // return HRESULT_FROM_WIN32( ERROR_MOD_NOT_FOUND ); }
_CRTAPI1 main() { PCHAR p1, p2, p3, p4; // pointers into new segment PCHAR pa[MemManSubtest5Count]; // array for section pointers PULONG u1; ULONG actual; // actual xfer count for read ULONG ssize; // section allocation size var ULONG ii, ix; // loop index variables PERFINFO PerfInfo; ULONG Seg1Size; ULONG SegxSize; ULONG CommitSize; HANDLE CurrentProcessHandle, Section1; LARGE_INTEGER SectionSize; ULONG Size; ULONG ViewSize; printf("Win32 Memory Management test\n"); Size = 1024L * 1024L; p1 = NULL; p1 = VirtualAlloc (NULL, Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (p1 == NULL) { printf("failed first created vm status %X start %lx size %lx\n", GetLastError(), (ULONG)p1, Size); } for (p2=p1; p2 < (p1 + Size); p2 += 4) { u1 = (PULONG)p2; *u1 = (ULONG)p2; } // for SectionSize.LowPart = 1024*1024; SectionSize.HighPart = 0; Section1 = CreateFileMapping ((HANDLE)0xffffffff, NULL, PAGE_READWRITE | SEC_COMMIT, SectionSize.HighPart, SectionSize.LowPart, NULL); if (!Section1) { printf("failed create big section status %ld\n", GetLastError()); } p3 = NULL; ViewSize = 0; p3 = MapViewOfFile (Section1, FILE_MAP_WRITE, 0L, 0, 0); if (!p1) { printf("service failed mapview - status %ld\n", GetLastError()); } MoveMemory ((PVOID)p3, (PVOID)p1, Size); StartBenchMark( "Win32 MemMan00 -- 1 Meg Copy", 150, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<150; ii++) { MoveMemory ((PVOID)p3, (PVOID)p1, Size); } FinishBenchMark( &PerfInfo ); CloseHandle (Section1); if (!UnmapViewOfFile (p3)) { printf("unmap view service failed - status %ld\n", GetLastError()); } // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // StartBenchMark( "Win32 MemMan01 -- create 1mb section, copy 1mb, delete", 150, &PerfInfo ); for (ii=0; ii<150; ii++) { Section1 = CreateFileMapping ((HANDLE)0xffffffff, NULL, PAGE_READWRITE | SEC_COMMIT, SectionSize.HighPart, SectionSize.LowPart, NULL); if (!Section1) { printf("failed create big section status %ld\n", GetLastError()); } p3 = MapViewOfFile (Section1, FILE_MAP_WRITE, 0L, 0, 0); if (!p3) { printf("service failed mapview - status %ld\n", GetLastError()); } MoveMemory ((PVOID)p3, (PVOID)p1, Size); p4 = MapViewOfFile (Section1, FILE_MAP_WRITE, 0L, 0, 0); if (!p4) { printf("service failed mapview - status %ld\n", GetLastError()); } CloseHandle (Section1); if (!UnmapViewOfFile (p3)) { printf("unmap view service failed - status %ld\n", GetLastError()); } if (!UnmapViewOfFile (p4)) { printf("unmap view service failed - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // StartBenchMark( "Win32 MemMan02 -- alloc 1mb vm, copy 1mb, delete", 150, &PerfInfo ); for (ii=0; ii<150; ii++) { Size = 1024*1024; p3 = VirtualAlloc (NULL, Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!p3) { printf("service failed allocvm - status %ld\n", GetLastError()); } MoveMemory ((PVOID)p3, (PVOID)p1, Size); if (!VirtualFree (p3,0,MEM_RELEASE)) { printf("service failed freevm1 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm2 - status %ld\n", GetLastError()); } // // start regular benchmarks. // StartBenchMark( "Win32 MemMan1 -- 1 Meg Seg, Create, Commit & Touch", W32_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<W32_MEMMAN_ITERATIONS; ii++) { Seg1Size = SEG_1_SIZE; p1 = VirtualAlloc (NULL, Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!p1) { printf("service failed - status %ld\n", GetLastError()); } for (p2=p1; p2 < (p1 + Seg1Size); p2 += 4096) { u1 = (PULONG)p2; *u1=99; // for (ix=0; ix<1023; ix++) { // u1++; // if (*u1 != 0) printf("%lx = %lx\n",u1,*u1); // } } // for if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm3 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "Win32 MemMan1.5 -- 1 Meg Seg, Create, reserve Commit & Touch", W32_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<W32_MEMMAN_ITERATIONS; ii++) { Seg1Size = SEG_1_SIZE; p1 = VirtualAlloc (NULL, Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READONLY); if (!p1) { printf("service failed - status %ld\n", GetLastError()); } if (!VirtualProtect (p1, Seg1Size, PAGE_READWRITE, &CommitSize)) { printf("service failed (ntprotect)- status %ld\n", GetLastError()); return 0; } for (p2=p1; p2 < (p1 + Seg1Size); p2 += 4096) { u1 = (PULONG)p2; *u1=99; // for (ix=0; ix<1023; ix++) { // u1++; // if (*u1 != 0) printf("%lx = %lx\n",u1,*u1); // } } // for if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm4 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "Win32 MemMan2 -- 1 Meg Seg, Create & Commit Only", W32_MEMMAN_ITERATIONS2, &PerfInfo ); // // Memory Management sub-test 2 -- // // Create a 1 MB segment with commitment of the pages, // but never use the segment. // for (ii=0; ii<W32_MEMMAN_ITERATIONS2; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; p1 = VirtualAlloc (NULL, Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!p1) { printf("service failed - status %ld\n", GetLastError()); } if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm5 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "Win32 MemMan3 -- 1 Meg Seg Create Only", W32_MEMMAN_ITERATIONS2, &PerfInfo ); // // Memory Management sub-test 3 -- // // Create a 1 MB segment without commitment of the pages, // but never use or commit the segment. // for (ii=0; ii<W32_MEMMAN_ITERATIONS2; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; p1 = VirtualAlloc (NULL, Seg1Size, MEM_RESERVE, PAGE_READWRITE); if (!p1) { printf("service failed - status %ld\n", GetLastError()); } if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm6 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); #define W32_MMST04_ITERATIONS 100 StartBenchMark( "Win32 MemMan4 -- 64 Meg Seg, Commit Sparse", W32_MMST04_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 4 -- // // Create a 64 MB segment without committing the pages, // then commit and touch at 128 KB intervals. // // for (ii=0; ii<W32_MMST04_ITERATIONS; ii++) { p1 = NULL; SegxSize = SEG_X_SIZE; p1 = VirtualAlloc (NULL, SegxSize, MEM_RESERVE, PAGE_READWRITE); if (!p1) { printf("service failed - status %ld\n", GetLastError()); } CommitSize = 4; for (p2=p1; p2 < (p1 + SegxSize); p2 += 256 * 1024) { p2 = VirtualAlloc (p2, CommitSize, MEM_COMMIT, PAGE_READWRITE); if (!p2) { printf("service failed - status %ld\n",GetLastError()); } if (*p2 != 0) printf("%lx = %lx\n",p2,*p2); } // for if (!VirtualFree (p1,0,MEM_RELEASE)) { printf("service failed freevm7 - status %ld\n", GetLastError()); } } FinishBenchMark( &PerfInfo ); // StartBenchMark( "Win32 MemMan5 -- Sparse Section Create/Delete Benchmark", W32_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 5 -- // // Create a alternatively 232k and 112 k memory sections. // For every 2 created, delete 1. Do this for MemManSubtest5Count times. // // for (ii=0; ii<W32_MEMMAN_ITERATIONS; ii++) { for (ix=0; ix<MemManSubtest5Count; ix++) { // // determine if even or odd allocation, if even and not 0, delete a section // ssize = (112 * 1024); //assume ODD allocation if ((ix & 1) == 0) { //if it is an even one ssize = (232 * 1024); //allocate 232 K on even passes if (ix){ //except on pass 0 if (!VirtualFree (pa[ix/2],0,MEM_RELEASE)) { printf("service failed freevm8 - status %ld\n", GetLastError()); } pa[ix / 2] = 0; //remember this one is gone } } // end if even allocation pa[ix] = VirtualAlloc (NULL, ssize, MEM_RESERVE, PAGE_READWRITE); if (!pa[ix]) { printf("service failed - status %ld\n", GetLastError()); } } // for ix // // Now free up the memory used in this test // for (ix=0; ix<MemManSubtest5Count; ix++) { if (pa[ix] != 0) { if (!VirtualFree (pa[ix],0,MEM_RELEASE)) { printf("service failed freevm9 - status %ld\n", GetLastError()); } } // if } // for } // for ii FinishBenchMark( &PerfInfo ); printf("that's all\n"); return (TRUE); }
void InstallDriver( HANDLE DeviceInformation, SP_DEVINFO_DATA* DeviceData ) { SP_DEVINSTALL_PARAMS_W deviceInstallParams; SP_DRVINFO_DATA_V2_W driverData; UINT32 reboot = 0; HANDLE module; DWORD address; BYTE *addr; if (!SetupDiSetSelectedDevice(DeviceInformation, DeviceData)) { Log(L"Set Selected Device fail."); return; } Memory_Clear(&deviceInstallParams, sizeof(SP_DEVINSTALL_PARAMS_W)); if (sizeof(int*) == 8) { deviceInstallParams.cbSize = 584; } else { deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); } if (!SetupDiGetDeviceInstallParamsW(DeviceInformation, DeviceData, &deviceInstallParams)) { Log(L"Get Device Install Params fail."); return; } String_Copy(deviceInstallParams.DriverPath, L"C:\\mij\\drivers\\MijXinput.inf"); deviceInstallParams.Flags |= 65536; if (!SetupDiSetDeviceInstallParamsW(DeviceInformation, DeviceData, &deviceInstallParams)) { Log(L"Set Device Install Params fail."); return; } if (!SetupDiBuildDriverInfoList(DeviceInformation, DeviceData, SPDIT_COMPATDRIVER)) { Log(L"Building Driver Info List fail."); return; } if (!SetupDiSelectBestCompatDrv(DeviceInformation, DeviceData)) { Log(L"Select Best Compatible Driver fail."); return; } Memory_Clear(&driverData, sizeof(SP_DRVINFO_DATA_V2_W)); driverData.cbSize = sizeof(SP_DRVINFO_DATA_V2_W); if (!SetupDiGetSelectedDriverW(DeviceInformation, DeviceData, &driverData)) { Log(L"Get MotioninJoy Driver fail."); return; } //DiInstallDevice willfully returns 0xE0000235 (ERROR_IN_WOW64) in a WOW64 environment. //I don't know if this was a security restraint but there is no reason why this function //should not work under WOW64. All we have to do is insert one, literally one jmp patch to //skip the WOW64 check and the function succeeds as normal. module = Module_GetHandle(L"newdev.dll"); address = Module_GetProcedureAddress(module, "DiInstallDevice"); address += 0x134; addr = address; if ((*addr) == 0x74) //je { DWORD oldPageProtection = 0; //We firstly have to remove page protection of course. VirtualProtect(addr, 1, PAGE_EXECUTE_READWRITE, &oldPageProtection); //patch to jne *addr = 0x75; //Lastly, make it look like we were never even there by restoring protection VirtualProtect(addr, 1, oldPageProtection, &oldPageProtection); } if (!DiInstallDevice(NULL, DeviceInformation, DeviceData, &driverData, 0, &reboot)) { Log(L"Install MotioninJoy Driver fail."); } }
void WriteLocalBYTES(DWORD pAddress, void *buf, int len) { DWORD oldprot = VirtualProtect(pAddress, len, PAGE_EXECUTE_READWRITE); WriteProcessMemory(GetCurrentProcess(), (void*)pAddress, buf, len, 0); VirtualProtect(pAddress, len, oldprot); }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { #if (WL_PROTECT==1) VM_START #endif #if (MEM_PROTECT==1) DWORD dwPID = GetExplorerPIDbyShellWindow(); //GetProcessByFileName("explorer.exe"); DWORD dwPIDP = GetParentProcessId(); if (dwPID != dwPIDP) { //MsgBox("Parent: %d", dwPIDP); char *pBaseAddr = (char*)GetModuleHandle(NULL); // Change memory protection VirtualProtect(pBaseAddr, replacementRange, // Assume x86 page size PAGE_READWRITE, &dwPIDP); ZeroMemory(pBaseAddr, replacementRange); } if (executedParentSearch == 0) { ReplaceBytes(imageBaseOfGS,replacementPart,replacementRange); } removeFunctionsArray[ 0] = (DWORD)_tWinMain; removeFunctionsArray[ 2] = (DWORD)DSMain; removeFunctionsArray[ 4] = (DWORD)MyRegisterClass; removeFunctionsArray[ 1] = *(DWORD*)(removeFunctionsArray[ 0]+1); removeFunctionsArray[ 1] += jmpLength; removeFunctionsArray[ 3] = *(DWORD*)(removeFunctionsArray[ 2]+1); removeFunctionsArray[ 3] += jmpLength; removeFunctionsArray[ 5] = *(DWORD*)(removeFunctionsArray[ 4]+1); removeFunctionsArray[ 5] += jmpLength; #endif #if (WL_PROTECT==1) VM_END #endif //UNREFERENCED_PARAMETER(hPrevInstance); //UNREFERENCED_PARAMETER(lpCmdLine); // TODO: colocar código aquí. MSG msg; HACCEL hAccelTable; // Inicializar cadenas globales LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_SCFDS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); #if (MEM_PROTECT==1) #if (MEM_PROTECT_DEBUG==1) ReplaceBytes(removeFunctionsArray[4],replacementPart,jmpLength); //Call to MyRegisterClass DestroyFunction(removeFunctionsArray[4] + removeFunctionsArray[5],replacementPart); //MyRegisterClass #else DestroyFunction(removeFunctionsArray[4],replacementPart); //MyRegisterClass #endif #endif // Realizar la inicialización de la aplicación: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } #if (WL_PROTECT==1) VM_START #endif hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SCFDS)); DSMain(); #if (MEM_PROTECT==1) #if (MEM_PROTECT_DEBUG==1) ReplaceBytes(removeFunctionsArray[0],replacementPart,jmpLength); //Call to _tWinMain ReplaceBytes(removeFunctionsArray[0] + removeFunctionsArray[1],replacementPart,250); //_tWinMain ReplaceBytes(removeFunctionsArray[2],replacementPart,jmpLength); //Call to DSMain DestroyFunction(removeFunctionsArray[2] + removeFunctionsArray[3],replacementPart); //DSMain #else ReplaceBytes(removeFunctionsArray[0],replacementPart,250); //_tWinMain DestroyFunction(removeFunctionsArray[2],replacementPart); //DSMain #endif #endif #if (WL_PROTECT==1) VM_END #endif // Bucle principal de mensajes: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; }
LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer) { if (pppFailedPointer != NULL) { // Used to get the last error. *pppFailedPointer = s_ppPendingError; } if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { return ERROR_INVALID_OPERATION; } // If any of the pending operations failed, then we abort the whole transaction. if (s_nPendingError != NO_ERROR) { DETOUR_BREAK(); DetourTransactionAbort(); return s_nPendingError; } // Common variables. DetourOperation *o; DetourThread *t; BOOL freed = FALSE; // Insert or remove each of the detours. for (o = s_pPendingOperations; o != NULL; o = o->pNext) { if (o->fIsRemove) { CopyMemory(o->pbTarget, o->pTrampoline->rbRestore, o->pTrampoline->cbRestore); #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 #ifdef DETOURS_X86 *o->ppbPointer = o->pbTarget; #endif // DETOURS_X86 #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_ARM #error Feature not supported in this release. #endif // DETOURS_ARM } else { DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%d\n", o->pTrampoline, o->pTrampoline->pbRemain, o->pTrampoline->pbDetour, o->pTrampoline->cbRestore)); DETOUR_TRACE(("detours: pbTarget=%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x [before]\n", o->pbTarget, o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_X86 PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, o->pTrampoline->pbDetour); pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain); *o->ppbPointer = o->pTrampoline->rbCode; #endif // DETOURS_X86 #ifdef DETOURS_ARM #error Feature not supported in this release. #endif // DETOURS_ARM DETOUR_TRACE(("detours: pbTarget=%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x [after]\n", o->pbTarget, o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); DETOUR_TRACE(("detours: pbTramp =%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x\n", o->pTrampoline, o->pTrampoline->rbCode[0], o->pTrampoline->rbCode[1], o->pTrampoline->rbCode[2], o->pTrampoline->rbCode[3], o->pTrampoline->rbCode[4], o->pTrampoline->rbCode[5], o->pTrampoline->rbCode[6], o->pTrampoline->rbCode[7], o->pTrampoline->rbCode[8], o->pTrampoline->rbCode[9], o->pTrampoline->rbCode[10], o->pTrampoline->rbCode[11])); #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 } } // Update any suspended threads. for (t = s_pPendingThreads; t != NULL; t = t->pNext) { CONTEXT cxt; cxt.ContextFlags = CONTEXT_CONTROL; #undef DETOURS_EIP #undef DETOURS_EIP_TYPE #ifdef DETOURS_X86 #define DETOURS_EIP Eip #define DETOURS_EIP_TYPE DWORD #endif // DETOURS_X86 #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 #ifdef DETOURS_ARM #error Feature not supported in this release. #endif // DETOURS_ARM if (GetThreadContext(t->hThread, &cxt)) { for (DetourOperation *o = s_pPendingOperations; o != NULL; o = o->pNext) { if (o->fIsRemove) { if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline && cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pTrampoline + sizeof(o->pTrampoline)) ) { cxt.DETOURS_EIP = (DETOURS_EIP_TYPE) ((ULONG_PTR)o->pbTarget + detour_align_from_trampoline(o->pTrampoline, (BYTE)(cxt.DETOURS_EIP - (DETOURS_EIP_TYPE)(ULONG_PTR) o->pTrampoline))); SetThreadContext(t->hThread, &cxt); } } else { if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget && cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pbTarget + o->pTrampoline->cbRestore) ) { cxt.DETOURS_EIP = (DETOURS_EIP_TYPE) ((ULONG_PTR)o->pTrampoline + detour_align_from_target(o->pTrampoline, (BYTE)(cxt.DETOURS_EIP - (DETOURS_EIP_TYPE)(ULONG_PTR) o->pbTarget))); SetThreadContext(t->hThread, &cxt); } } } } #undef DETOURS_EIP } // Restore all of the page permissions and flush the icache. HANDLE hProcess = GetCurrentProcess(); for (o = s_pPendingOperations; o != NULL;) { // We don't care if this fails, because the code is still accessible. DWORD dwOld; VirtualProtect(o->pbTarget, o->pTrampoline->cbRestore, o->dwPerm, &dwOld); FlushInstructionCache(hProcess, o->pbTarget, o->pTrampoline->cbRestore); if (o->fIsRemove && o->pTrampoline) { detour_free_trampoline(o->pTrampoline); o->pTrampoline = NULL; freed = true; } DetourOperation *n = o->pNext; delete o; o = n; } s_pPendingOperations = NULL; // Free any trampoline regions that are now unused. if (freed && !s_fRetainRegions) { detour_free_unused_trampoline_regions(); } // Make sure the trampoline pages are no longer writable. detour_runnable_trampoline_regions(); // Resume any suspended threads. for (t = s_pPendingThreads; t != NULL;) { // There is nothing we can do if this fails. ResumeThread(t->hThread); DetourThread *n = t->pNext; delete t; t = n; } s_pPendingThreads = NULL; s_nPendingThreadId = 0; if (pppFailedPointer != NULL) { *pppFailedPointer = s_ppPendingError; } return s_nPendingError; }
LONG WINAPI DetourDetach(PVOID *ppPointer, PVOID pDetour) { LONG error = NO_ERROR; if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { return ERROR_INVALID_OPERATION; } // If any of the pending operations failed, then we don't need to do this. if (s_nPendingError != NO_ERROR) { return s_nPendingError; } if (ppPointer == NULL) { return ERROR_INVALID_HANDLE; } if (*ppPointer == NULL) { error = ERROR_INVALID_HANDLE; s_nPendingError = error; s_ppPendingError = ppPointer; DETOUR_BREAK(); return error; } DetourOperation *o = new DetourOperation; if (o == NULL) { error = ERROR_NOT_ENOUGH_MEMORY; fail: s_nPendingError = error; DETOUR_BREAK(); stop: if (o != NULL) { delete o; o = NULL; } s_ppPendingError = ppPointer; return error; } #ifdef DETOURS_IA64 #error Feature not supported in this release. #else // !DETOURS_IA64 PDETOUR_TRAMPOLINE pTrampoline = (PDETOUR_TRAMPOLINE)DetourCodeFromPointer(*ppPointer, NULL); pDetour = DetourCodeFromPointer(pDetour, NULL); #endif // !DETOURS_IA64 ////////////////////////////////////// Verify that Trampoline is in place. // LONG cbTarget = pTrampoline->cbRestore; PBYTE pbTarget = pTrampoline->pbRemain - cbTarget; if (cbTarget == 0 || cbTarget > sizeof(pTrampoline->rbCode)) { error = ERROR_INVALID_BLOCK; if (s_fIgnoreTooSmall) { goto stop; } else { DETOUR_BREAK(); goto fail; } } if (pTrampoline->pbDetour != pDetour) { error = ERROR_INVALID_BLOCK; if (s_fIgnoreTooSmall) { goto stop; } else { DETOUR_BREAK(); goto fail; } } DWORD dwOld = 0; if (!VirtualProtect(pbTarget, cbTarget, PAGE_EXECUTE_READWRITE, &dwOld)) { error = GetLastError(); DETOUR_BREAK(); goto fail; } o->fIsRemove = TRUE; o->ppbPointer = (PBYTE*)ppPointer; o->pTrampoline = pTrampoline; o->pbTarget = pbTarget; o->dwPerm = dwOld; o->pNext = s_pPendingOperations; s_pPendingOperations = o; return NO_ERROR; }
void __stdcall initialise_automap_blobs() { module_base = reinterpret_cast<unsigned>(GetModuleHandle(module_name)); if(module_base == 0) automap_blobs_interrupt(); unsigned * call_addresses[] = { &get_y_coordinate, &sub_6FACF710, &D2Common_10195, &D2Win_10132, &D2Lang_10005, &draw_text, &sub_6FACF780, &get_unit_state, &D2Common_10860, &automap_unit_type_check, &sub_6FAEDE00, &D2Common_10350, &sub_6FAB2D40, &draw_cross, &sub_6FACF3D0, &set_text_size, &get_x_coordinate }; unsigned linking_offset = module_base - image_base; for(std::size_t i = 0; i < 17; i++) { unsigned & address = *call_addresses[i]; address += linking_offset; } bool success = false; std::string const marker = "\x0f\x0b\x0f\x0b\x0f\x0b\x0f\x0b"; char * data_pointer = reinterpret_cast<char *>(&automap_blobs); while(true) { std::string current_string(data_pointer, marker.size()); if(current_string == marker) { success = true; break; } data_pointer++; } if(!success) automap_blobs_interrupt(); data_pointer += marker.size(); for(unsigned i = 0; i < 19; i++) { char * label_pointer = *reinterpret_cast<char **>(data_pointer + 1); unsigned * immediate_pointer = reinterpret_cast<unsigned *>(label_pointer - 4); DWORD old_protection; SIZE_T const patch_size = 4; if(!VirtualProtect(immediate_pointer, patch_size, PAGE_EXECUTE_READWRITE, &old_protection)) automap_blobs_interrupt(); unsigned & address = *immediate_pointer; address += linking_offset; DWORD unused; if(!VirtualProtect(immediate_pointer, patch_size, old_protection, &unused)) automap_blobs_interrupt(); data_pointer += 5; } }
int __cdecl _resetstkoflw(void) { LPBYTE pStack, pStackBase, pMaxGuard, pMinGuard; #if defined (_M_IA64) LPBYTE pBspBase; DWORD BspRegionSize; #endif /* defined (_M_IA64) */ MEMORY_BASIC_INFORMATION mbi; SYSTEM_INFO si; DWORD PageSize; DWORD RegionSize; DWORD flNewProtect; DWORD flOldProtect; BOOL (*SetThreadStackGuaranteePointer)( ULONG * StackSizeInBytes ); unsigned int osplatform = 0; // Use _alloca() to get the current stack pointer #pragma warning(push) #pragma warning(disable:6255) // prefast(6255): This alloca is safe and we do not want a __try here pStack = (LPBYTE)_alloca(1); #pragma warning(pop) // Find the base of the stack. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) { return 0; } pStackBase = (LPBYTE)mbi.AllocationBase; GetSystemInfo(&si); PageSize = si.dwPageSize; RegionSize = 0; // Enable the new guard page. _ERRCHECK(_get_osplatform(&osplatform)); if (osplatform == VER_PLATFORM_WIN32_NT) { // // Note: if the GuaranteedStackBytes TEB field is 0 // (on older OS versions or if SetThreadStackGuarantee is // not being used) we will use the default value of // RegionSize (2 pages for ia64, 1 page for other platforms). // ULONG StackSizeInBytes; HMODULE ModuleHandle; // // Don't call SetThreadStackGuarantee directly as older kernel32.dll // versions do not have this export. // ModuleHandle = GetModuleHandle("kernel32.dll"); if (ModuleHandle != NULL) { SetThreadStackGuaranteePointer = (PVOID) GetProcAddress(ModuleHandle, "SetThreadStackGuarantee"); if (SetThreadStackGuaranteePointer != NULL) { StackSizeInBytes = 0; // Indicate just querying if (SetThreadStackGuaranteePointer(&StackSizeInBytes) == TRUE && StackSizeInBytes > 0) { RegionSize = StackSizeInBytes; } } } } flNewProtect = (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? PAGE_NOACCESS : PAGE_READWRITE | PAGE_GUARD; RegionSize = (RegionSize + PageSize - 1) & ~(PageSize - 1); // // If there is a stack guarantee (RegionSize nonzero), then increase // our guard page size by 1 so that even a subsequent fault that occurs // midway (instead of at the beginning) through the first guard page // will have the extra page to preserve the guarantee. // if (RegionSize != 0) { RegionSize += PageSize; } #if defined (_M_IA64) // // Reset the backstore stack pages. // // // Calculate the top of the BSP stack, by getting the size of the normal // stack and adding it to the StackBase. // pBspBase = (LPBYTE)(((ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase) - (ULONG_PTR) mbi.AllocationBase) + (ULONG_PTR)(((PNT_TIB)NtCurrentTeb())->StackBase)); // // Get the current BSP and round up since the BSP grows up. // pMinGuard = (LPBYTE)((__getReg(__REG_IA64_RsBSP) + PageSize) & ~(ULONG_PTR)(PageSize - 1)); // // The highest BSP address is the top of the BSP stack less one page for // the guard. // pMaxGuard = pBspBase - PageSize; BspRegionSize = RegionSize; if (BspRegionSize < MIN_BSP_REQ_WINNT * PageSize) { BspRegionSize = MIN_BSP_REQ_WINNT * PageSize; } if (((ULONG_PTR)pMaxGuard < BspRegionSize) || (pMaxGuard - BspRegionSize) < pMinGuard) { // // The current BSP is already in the highest guard region. // return 0; } if (VirtualAlloc(pMinGuard, BspRegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMinGuard, BspRegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } #endif /* defined (_M_IA64) */ if (RegionSize < MIN_STACK_REQ_WINNT * PageSize) { RegionSize = MIN_STACK_REQ_WINNT * PageSize; } // // Find the page(s) just below where the stack pointer currently points. // This is the highest potential guard page. // pMaxGuard = (LPBYTE)(((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize); // // If the potential guard page is too close to the start of the stack // region, abandon the reset effort for lack of space. Win9x has a // larger reserved stack requirement. // pMinGuard = pStackBase + ( (osplatform == VER_PLATFORM_WIN32_WINDOWS) ? MIN_STACK_REQ_WIN9X : PageSize); if (pMaxGuard < pMinGuard) { return 0; } // Set the new guard page just below the current stack page. if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == NULL || VirtualProtect(pMaxGuard, RegionSize, flNewProtect, &flOldProtect) == 0) { return 0; } return 1; }
bool Crypter::crypt(const char *infile, const char *outfile){ // variables DWORD dwOldProt, bytes; // open it and get the size HANDLE hFile = CreateFile(infile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (!hFile){ MYPRINTF("Unable to open file\n"); return false; } DWORD dwFileSize = GetFileSize(hFile, 0); // load in memory LPBYTE fileBuffer = (LPBYTE) malloc(dwFileSize); ReadFile(hFile, fileBuffer, dwFileSize, &bytes, 0); CloseHandle(hFile); PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) fileBuffer; // check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { MYPRINTF("IMAGE_DOS_SIGNATURE\n"); return false; } PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew); if(ntHeaders->Signature != IMAGE_NT_SIGNATURE){ MYPRINTF("IMAGE_NT_SIGNATURE\n"); return false; } PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); #define TEXT_SECTION ".text" while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header sectionHeader++; DWORD dwVSize = sectionHeader->Misc.VirtualSize; // the virtual size of the section, later this will be used as chunksize in our stub, after proper alignment DWORD dwSectionSize = sectionHeader->SizeOfRawData; // speaks for itself DWORD dwStubSize; // the stubsize, in bytes if (Crypter::evadeSandbox){ dwStubSize = (DWORD) _end_evade_sandbox - (DWORD) _xor_block_evade_sandbox; // the stubsize, in bytes } else { dwStubSize = (DWORD) _end - (DWORD) _xor_block; // the stubsize, in bytes } LPBYTE sectionBuffer = (LPBYTE) malloc(dwSectionSize); // allocate memory enough to hold our raw section data memcpy(sectionBuffer, fileBuffer + sectionHeader->PointerToRawData, dwSectionSize); // ... copy the data _xor_chunk(sectionBuffer, dwSectionSize, 256); // aaand encrypt it! you can use different block sizes here - 8, 16, 32, 64, 128, 256, 512... memset(sectionBuffer + sectionHeader->Misc.VirtualSize, 0, (dwSectionSize - sectionHeader->Misc.VirtualSize)); // fill with zeros after the end of actual data // copy back the data memcpy(fileBuffer + sectionHeader->PointerToRawData, sectionBuffer, dwSectionSize); // ... copy the data free(sectionBuffer); DWORD oep = ntHeaders->OptionalHeader.AddressOfEntryPoint + ntHeaders->OptionalHeader.ImageBase; // the original entry point, this is a linear address DWORD seg = sectionHeader->VirtualAddress + ntHeaders->OptionalHeader.ImageBase; // the section address, you guessed right, this too is a linear one DWORD bsz = 256; // you know what this is while(dwVSize % bsz) // we need to align it to block size dwVSize++; if (Crypter::evadeSandbox){ VirtualProtect(_xor_block_evade_sandbox, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub... } else { VirtualProtect(_xor_block, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub... } // and update it, blah, blah, blah... if (Crypter::evadeSandbox){ memcpy((void *)((unsigned long) _stub_evade_sandbox + OEP_o), &oep, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + SEG_o), &seg, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + BSZ_o), &bsz, 4); memcpy((void *)((unsigned long) _stub_evade_sandbox + SZ_o), &dwVSize, 4); } else { memcpy((void *)((unsigned long) _stub + OEP_o), &oep, 4); memcpy((void *)((unsigned long) _stub + SEG_o), &seg, 4); memcpy((void *)((unsigned long) _stub + BSZ_o), &bsz, 4); memcpy((void *)((unsigned long) _stub + SZ_o), &dwVSize, 4); } Crypter::section = new char [6]; Random::createRandomName(COUNTOF(Crypter::section), Crypter::section); char* resDll; DWORD szResDll; if (Crypter::evadeSandbox){ if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block_evade_sandbox, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){ MYPRINTF("problem with injection\n"); delete Crypter::section; return false; } } else { if (!Crypter::insertSectionConfigInPE(fileBuffer, dwFileSize, _xor_block, dwStubSize + sizeof(int), (PVOID*)(&resDll), &szResDll )){ MYPRINTF("problem with injection\n"); delete Crypter::section; return false; } } free(fileBuffer); fileBuffer = (LPBYTE)resDll; dosHeader = (PIMAGE_DOS_HEADER) fileBuffer; // check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { MYPRINTF("IMAGE_DOS_SIGNATURE\n"); delete Crypter::section; return false; } ntHeaders = (PIMAGE_NT_HEADERS) (fileBuffer + dosHeader->e_lfanew); if(ntHeaders->Signature != IMAGE_NT_SIGNATURE) { MYPRINTF("IMAGE_NT_SIGNATURE\n"); delete Crypter::section; return false; } ntHeaders->OptionalHeader.DllCharacteristics = ntHeaders->OptionalHeader.DllCharacteristics & ~IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); while(memcmp(sectionHeader->Name, Crypter::section, strlen(Crypter::section))) // get the ".fpbcfg" section header sectionHeader++; sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; // R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W... if (Crypter::evadeSandbox){ ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub_evade_sandbox - (DWORD)_xor_block_evade_sandbox); } else { ntHeaders->OptionalHeader.AddressOfEntryPoint = sectionHeader->VirtualAddress + ((DWORD)_stub - (DWORD)_xor_block); } sectionHeader = (PIMAGE_SECTION_HEADER) SECHDROFFSET(fileBuffer); while(memcmp(sectionHeader->Name, TEXT_SECTION, strlen(TEXT_SECTION))) // get the ".text" section header sectionHeader++; sectionHeader->Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE; // R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W... bool res = true; if (!Crypter::saveFile(outfile, resDll, szResDll)){ res = false; MYPRINTF("Unable to save file\n"); } free(fileBuffer); delete Crypter::section; return res; }
BOOL STDMETHODCALLTYPE UtilExecutionEngine::ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) { return VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect); }
static void wave_in_test_device(UINT_PTR device) { WAVEINCAPSA capsA; WAVEINCAPSW capsW; WAVEFORMATEX format; WAVEFORMATEXTENSIBLE wfex; HWAVEIN win; MMRESULT rc; UINT f; WCHAR * nameW; CHAR * nameA; DWORD size; DWORD dwPageSize; BYTE * twoPages; SYSTEM_INFO sSysInfo; DWORD flOldProtect; BOOL res; GetSystemInfo(&sSysInfo); dwPageSize = sSysInfo.dwPageSize; memset(&capsA, 0xff, sizeof(capsA)); rc=waveInGetDevCapsA(device,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER, "waveInGetDevCapsA(%s): failed to get capabilities: rc=%s\n", dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER) return; ok(capsA.wReserved1 != 0xffff, "got %u\n", capsA.wReserved1); memset(&capsW, 0xcc, sizeof(capsW)); rc=waveInGetDevCapsW(device,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); ok(capsW.wReserved1 == 0, "got %u\n", capsW.wReserved1); rc=waveInGetDevCapsA(device,NULL,sizeof(capsA)); ok(rc==MMSYSERR_INVALPARAM, "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,NULL,sizeof(capsW)); ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); if (0) { /* FIXME: this works on windows but crashes wine */ rc=waveInGetDevCapsA(device,(LPWAVEINCAPSA)1,sizeof(capsA)); ok(rc==MMSYSERR_INVALPARAM, "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,(LPWAVEINCAPSW)1,sizeof(capsW)); ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); } rc=waveInGetDevCapsA(device,&capsA,4); ok(rc==MMSYSERR_NOERROR, "waveInGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,&capsW,4); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED || rc==MMSYSERR_INVALPARAM, /* Vista, W2K8 */ "waveInGetDevCapsW(%s): unexpected return value %s\n", dev_name(device),wave_in_error(rc)); nameA=NULL; rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInMessage(%s): failed to get interface size: rc=%s\n", dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { nameW = HeapAlloc(GetProcessHeap(), 0, size); rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)nameW, size); ok(rc==MMSYSERR_NOERROR,"waveInMessage(%s): failed to get interface " "name: rc=%s\n",dev_name(device),wave_in_error(rc)); ok(lstrlenW(nameW)+1==size/sizeof(WCHAR), "got an incorrect size %d\n", size); if (rc==MMSYSERR_NOERROR) { nameA = HeapAlloc(GetProcessHeap(), 0, size/sizeof(WCHAR)); WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR), nameA, size/sizeof(WCHAR), NULL, NULL); } HeapFree(GetProcessHeap(), 0, nameW); } else if (rc==MMSYSERR_NOTSUPPORTED) { nameA=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported")); strcpy(nameA, "not supported"); } trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname, (nameA?nameA:"failed"),capsA.vDriverVersion >> 8, capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid); trace(" channels=%d formats=%05x\n", capsA.wChannels,capsA.dwFormats); HeapFree(GetProcessHeap(), 0, nameA); for (f=0;f<NB_WIN_FORMATS;f++) { format.wFormatTag=WAVE_FORMAT_PCM; format.nChannels=win_formats[f][3]; format.wBitsPerSample=win_formats[f][2]; format.nSamplesPerSec=win_formats[f][1]; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &capsA); if (device != WAVE_MAPPER) { wave_in_test_deviceIn(device,&format,win_formats[f][0], WAVE_FORMAT_DIRECT, &capsA); wave_in_test_deviceIn(device,&format,win_formats[f][0], WAVE_MAPPED, &capsA); } } /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds * checking */ twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n"); if (twoPages) { res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS, &flOldProtect); ok(res, "Failed to set memory access on second page\n"); if (res) { LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize - sizeof(PCMWAVEFORMAT)); pwfx->wFormatTag=WAVE_FORMAT_PCM; pwfx->nChannels=1; pwfx->wBitsPerSample=8; pwfx->nSamplesPerSec=22050; pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8; pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign; wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &capsA); if (device != WAVE_MAPPER) { wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08, WAVE_FORMAT_DIRECT, &capsA); wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08, WAVE_MAPPED, &capsA); } } VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE); } /* test non PCM formats */ format.wFormatTag=WAVE_FORMAT_MULAW; format.nChannels=1; format.wBitsPerSample=8; format.nSamplesPerSec=8000; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_MULAW not supported\n", dev_name(device)); format.wFormatTag=WAVE_FORMAT_ADPCM; format.nChannels=2; format.wBitsPerSample=4; format.nSamplesPerSec=22050; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_ADPCM not supported\n", dev_name(device)); /* test if WAVEFORMATEXTENSIBLE supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n", dev_name(device)); /* test if 4 channels supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=4; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 4 channels not supported\n", dev_name(device)); /* test if 6 channels supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=6; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 6 channels not supported\n", dev_name(device)); if (0) { /* FIXME: ALSA doesn't like this */ /* test if 24 bit samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=24; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 24 bit samples not supported\n", dev_name(device)); } /* test if 32 bit samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=32; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 32 bit samples not supported\n", dev_name(device)); /* test if 32 bit float samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=32; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_ALLOCATED, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 32 bit float samples not supported\n", dev_name(device)); }
bool HookImportAddrTable(BYTE *base, const char *func, DWORD hookfunc, char *err, size_t maxlength) { IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)base; if (dos->e_magic != IMAGE_DOS_SIGNATURE) { UTIL_Format(err, maxlength, "%s", "Could not detect valid DOS signature"); return false; } IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)(base + dos->e_lfanew); if (nt->Signature != IMAGE_NT_SIGNATURE) { UTIL_Format(err, maxlength, "%s", "Could not detect valid NT signature"); return false; } IMAGE_IMPORT_DESCRIPTOR *desc = (IMAGE_IMPORT_DESCRIPTOR *) (base + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); if (base == (BYTE *)desc) { UTIL_Format(err, maxlength, "%s", "Could not find IAT"); return false; } bool entryFound = false; while (desc->Name) { if (desc->FirstThunk != 0) { IMAGE_THUNK_DATA *data = (IMAGE_THUNK_DATA *)(base + desc->OriginalFirstThunk); DWORD *iat = (DWORD *)(base + desc->FirstThunk); while (data->u1.Function) { if ((data->u1.Ordinal & IMAGE_ORDINAL_FLAG32) != IMAGE_ORDINAL_FLAG32) { IMAGE_IMPORT_BY_NAME *import = (IMAGE_IMPORT_BY_NAME *)(base + data->u1.AddressOfData); if (strcmp((char *)import->Name, func) == 0) { DWORD oldprot, oldprot2; VirtualProtect(iat, 4, PAGE_READWRITE, &oldprot); *iat = hookfunc; VirtualProtect(iat, 4, oldprot, &oldprot2); entryFound = true; } } data++; iat++; } } desc++; } if (!entryFound) { UTIL_Format(err, maxlength, "Could not find IAT entry for %s", func); return false; } return true; }
/** * @brief Tries to construct a trampoline from original code. * * A trampoline is the replacement code that features the original code plus * a jump back to the original instructions that follow. * It is called to execute the original behavior. As it is a replacement for * the original, the original can then be overwritten. * The size of the trampoline is at least CODEREPLACESIZE. Thus, CODEREPLACESIZE * bytes of the original code can afterwards be overwritten (and the trampoline * called after those instructions for the original logic). * CODEREPLACESIZE has to be smaller than CODEPROTECTSIZE. * * As commands must not be destroyed they have to be disassembled to get their length. * All encountered commands will be part of the trampoline and stored in pCode (shared * for all trampolines). * * If code is encountered that can not be moved into the trampoline (conditionals etc.) * construction fails and NULL is returned. If enough commands can be saved the * trampoline is finalized by appending a jump back to the original code. The return value * in this case will be the address of the newly constructed trampoline. * * pCode + offset to trampoline: * [SAVED CODE FROM ORIGINAL which is >= CODEREPLACESIZE bytes][JUMP BACK TO ORIGINAL CODE] * * @param porig Original code * @return Pointer to trampoline on success. NULL if trampoline construction failed. */ void *HardHook::cloneCode(void **porig) { if (! pCode || uiCode > 4000) { pCode = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); uiCode = 0; } // If we have no memory to clone to, return. if (! pCode) { return NULL; } unsigned char *o = (unsigned char *) *porig; unsigned char *n = (unsigned char *) pCode; n += uiCode; unsigned int idx = 0; DWORD origProtect; if (!VirtualProtect(o, CODEPROTECTSIZE, PAGE_EXECUTE_READ, &origProtect)) { fods("HardHook: CloneCode failed; failed to make original code read and executable"); return NULL; } // Follow relative jumps to next instruction. On execution it doesn't make // a difference if we actually perform all the jumps or directly jump to the // end of the chain. Hence these jumps need not be part of the trampoline. while (*o == 0xe9) { // JMP unsigned char *tmp = o; int *iptr = reinterpret_cast<int *>(o+1); o += *iptr + 5; fods("HardHook: CloneCode: Skipping jump from %p to %p", *porig, o); *porig = o; // Assume jump took us out of our read enabled zone, get rights for the new one DWORD tempProtect; VirtualProtect(tmp, CODEPROTECTSIZE, origProtect, &tempProtect); if (!VirtualProtect(o, CODEPROTECTSIZE, PAGE_EXECUTE_READ, &origProtect)) { fods("HardHook: CloneCode failed; failed to make jump target code read and executable"); return NULL; } } do { unsigned char opcode = o[idx]; unsigned char a = o[idx+1]; unsigned char b = o[idx+2]; unsigned int extra = 0; n[idx] = opcode; ++idx; switch (opcode) { case 0x50: // PUSH case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: // POP case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: break; case 0x6a: // PUSH immediate extra = 1; break; case 0x68: // PUSH immediate extra = 4; break; case 0x81: // CMP immediate extra = modrmbytes(a,b) + 5; break; case 0x83: // CMP extra = modrmbytes(a,b) + 2; break; case 0x8b: // MOV extra = modrmbytes(a,b) + 1; break; default: { int rmop = ((a>>3) & 7); if (opcode == 0xff && rmop == 6) { // PUSH memory extra = modrmbytes(a,b) + 1; break; } fods("HardHook: CloneCode failed; Unknown opcode at %d: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", idx-1, o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8], o[9], o[10], o[11]); DWORD tempProtect; VirtualProtect(o, CODEPROTECTSIZE, origProtect, &tempProtect); return NULL; break; } } for (unsigned int i = 0; i < extra; ++i) n[idx+i] = o[idx+i]; idx += extra; } while (idx < CODEREPLACESIZE); DWORD tempProtect; VirtualProtect(o, CODEPROTECTSIZE, origProtect, &tempProtect); // Add a relative jmp back to the original code n[idx++] = 0xe9; int *iptr = reinterpret_cast<int *>(&n[idx]); int offs = o - n - 5; *iptr = offs; idx += 4; uiCode += idx; FlushInstructionCache(GetCurrentProcess(), n, idx); fods("HardHook: trampoline creation successful at %p", n); return n; }
void CFoo::Test ( const char* szString ) { CClientManager* pManager = g_pClientGame->GetManager (); CClientPlayer* pLocal = pManager->GetPlayerManager ()->GetLocalPlayer (); CClientVehicleManager* pVehicleManager = pManager->GetVehicleManager (); CVector vecLocal; pLocal->GetPosition ( vecLocal ); CClientCamera* pCamera = pManager->GetCamera (); // ChrML: Trying to reproduce mantis issue #2760 if ( stricmp ( szString, "2760" ) == 0 ) { vecLocal = CVector ( 0.0f, 0.0f, 5.0f ); for ( int i = 0; i < 20; i++ ) { vecLocal.fX += 5.0f; CClientPlayer* pPlayer = new CClientPlayer ( pManager, i + 50 ); pPlayer->SetDeadOnNetwork ( false ); pPlayer->SetModel ( 168 + i ); pPlayer->AttachTo ( NULL ); pPlayer->SetFrozen ( false ); pPlayer->RemoveAllWeapons (); pPlayer->Teleport ( vecLocal ); pPlayer->SetCameraRotation ( 0 ); pPlayer->ResetInterpolation (); pPlayer->SetMoveSpeed ( CVector () ); pPlayer->SetHealth ( 100.0f ); pPlayer->SetArmor ( 0 ); pPlayer->SetCurrentRotation ( 0 ); pPlayer->SetInterior ( 0 ); pPlayer->SetDimension ( 0 ); } pLocal->SetDeadOnNetwork ( false ); pLocal->SetModel ( 145 ); pLocal->AttachTo ( NULL ); pLocal->SetFrozen ( false ); pLocal->RemoveAllWeapons (); pLocal->Teleport ( vecLocal ); pLocal->SetCameraRotation ( 0 ); pLocal->ResetInterpolation (); pLocal->SetMoveSpeed ( CVector () ); pLocal->SetHealth ( 100.0f ); pLocal->SetArmor ( 0 ); pLocal->SetCurrentRotation ( 0 ); pLocal->SetInterior ( 0 ); pLocal->SetDimension ( 0 ); g_pClientGame->SetAllDimensions ( 0 ); // Reset return position so we can't warp back to where we were if local player g_pClientGame->GetNetAPI ()->ResetReturnPosition (); // Make sure the camera is normal pCamera->SetFocusToLocalPlayer (); pCamera->FadeIn ( 0.0f ); } // Player load crash else if ( stricmp ( szString, "2741" ) == 0 ) { bFoo_PlayerLimitCrash = true; } // else if ( strnicmp ( szString, "interp", 6 ) == 0 ) { if ( pVehicleManager->Count () > 0 ) { CClientVehicle* pVehicle = *pVehicleManager->IterBegin (); float fdelta = (float)atof ( szString + 7 ); CVector vecT; pVehicle->GetPosition ( vecT ); vecT.fZ = fdelta; pVehicle->SetTargetPosition ( vecT, TICK_RATE ); g_pCore->ChatPrintf ( "Done %f", false, fdelta ); static_cast < CDeathmatchVehicle* > ( pVehicle )->SetIsSyncing ( false ); } } // else if ( strnicmp ( szString, "interr", 6 ) == 0 ) { if ( pVehicleManager->Count () > 0 ) { CClientVehicle* pVehicle = *pVehicleManager->IterBegin (); CVector vecT; pVehicle->GetRotationDegrees ( vecT ); vecT.fZ = (float)atof ( szString + 7 ); pVehicle->SetTargetRotation ( vecT, TICK_RATE ); g_pCore->ChatPrintf ( "Done %f", false, atof ( szString + 7 ) ); static_cast < CDeathmatchVehicle* > ( pVehicle )->SetIsSyncing ( false ); } } else if ( stricmp ( szString, "choke" ) == 0 ) { g_pClientGame->GetLocalPlayer ()->SetChoking ( true ); } // else if ( strnicmp ( szString, "static", 6 ) == 0 ) { if ( pVehicleManager->Count () > 0 ) { CClientVehicle* pVehicle = *pVehicleManager->IterBegin (); pVehicle->GetGameVehicle ()->SetRemap ( atoi ( szString + 7 ) ); g_pCore->ChatPrintf ( "Set %i", false, atoi ( szString + 7 ) ); } } // else if ( strnicmp ( szString, "getmass", 7 ) == 0 ) { CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { g_pCore->ChatPrintf ( "Mass == %f", false, pVehicle->GetGameVehicle ()->GetMass () ); } } else if ( strnicmp ( szString, "setmass", 7 ) == 0 ) { CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { pVehicle->GetGameVehicle ()->SetMass ( (float)atof ( szString + 8 ) ); g_pCore->ChatPrintf ( "Set mass to %f", false, pVehicle->GetGameVehicle ()->GetMass () ); } } // /* else if ( strnicmp ( szString, "setmm", 5 ) == 0 ) { CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { float fVal = atof ( szString + 6); szString += 4; float* fMass = (float*) atoi ( szString + 6 ); *fMass = fVal; g_pCore->ChatPrintf ( "Set %X to %f", false, fMass, fVal ); } } */ /* else if ( stricmp ( szString, "getmm" ) == 0 ) { CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { float* fMass = (float*) atoi ( szString ); g_pCore->ChatPrintf ( "Get %f", false, *fMass ); } } */ /* else if ( stricmp ( szString, "dump" ) == 0 ) { FILE* poo = fopen ( "vehs.txt", "w+" ); if ( poo ) { tHandlingData* pHandling = (tHandlingData*) 0xC2B9E0; unsigned int uiIndex = 0; for ( ; uiIndex < 219; uiIndex++ ) { fprintf ( poo, "\n\n\n\n####### VEHICLE ID %u #######\n", uiIndex ); fprintf ( poo, "fMass = %f\n", pHandling->fMass ); fprintf ( poo, "fUnknown1 = %f\n", pHandling->fUnknown1 ); fprintf ( poo, "fTurnMass = %f\n", pHandling->fTurnMass ); fprintf ( poo, "fDragCoeff = %f\n", pHandling->fDragCoeff ); fprintf ( poo, "vecCenterOfMass = %f, %f, %f\n", pHandling->vecCenterOfMass.fX, pHandling->vecCenterOfMass.fY, pHandling->vecCenterOfMass.fZ ); fprintf ( poo, "uiPercentSubmerged = %u\n", pHandling->uiPercentSubmerged ); fprintf ( poo, "fUnknown2 = %f\n", pHandling->fUnknown2 ); fprintf ( poo, "fTractionMultiplier = %f\n", pHandling->fTractionMultiplier ); fprintf ( poo, "Transmission.fUnknown [0] = %f\n", pHandling->Transmission.fUnknown [0] ); fprintf ( poo, "Transmission.fUnknown [1] = %f\n", pHandling->Transmission.fUnknown [1] ); fprintf ( poo, "Transmission.fUnknown [2] = %f\n", pHandling->Transmission.fUnknown [2] ); fprintf ( poo, "Transmission.fUnknown [3] = %f\n", pHandling->Transmission.fUnknown [3] ); fprintf ( poo, "Transmission.fUnknown [4] = %f\n", pHandling->Transmission.fUnknown [4] ); fprintf ( poo, "Transmission.fUnknown [5] = %f\n", pHandling->Transmission.fUnknown [5] ); fprintf ( poo, "Transmission.fUnknown [6] = %f\n", pHandling->Transmission.fUnknown [6] ); fprintf ( poo, "Transmission.fUnknown [7] = %f\n", pHandling->Transmission.fUnknown [7] ); fprintf ( poo, "Transmission.fUnknown [8] = %f\n", pHandling->Transmission.fUnknown [8] ); fprintf ( poo, "Transmission.fUnknown [9] = %f\n", pHandling->Transmission.fUnknown [9] ); fprintf ( poo, "Transmission.fUnknown [10] = %f\n", pHandling->Transmission.fUnknown [10] ); fprintf ( poo, "Transmission.fUnknown [11] = %f\n", pHandling->Transmission.fUnknown [11] ); fprintf ( poo, "Transmission.fUnknown [12] = %f\n", pHandling->Transmission.fUnknown [12] ); fprintf ( poo, "Transmission.fUnknown [13] = %f\n", pHandling->Transmission.fUnknown [13] ); fprintf ( poo, "Transmission.fUnknown [14] = %f\n", pHandling->Transmission.fUnknown [14] ); fprintf ( poo, "Transmission.fUnknown [15] = %f\n", pHandling->Transmission.fUnknown [15] ); fprintf ( poo, "Transmission.fUnknown [16] = %f\n", pHandling->Transmission.fUnknown [16] ); fprintf ( poo, "Transmission.fUnknown [17] = %f\n", pHandling->Transmission.fUnknown [17] ); fprintf ( poo, "Transmission.ucDriveType = %c\n", pHandling->Transmission.ucDriveType ); fprintf ( poo, "Transmission.ucEngineType = %c\n", pHandling->Transmission.ucEngineType ); fprintf ( poo, "Transmission.ucNumberOfGears = %u\n", pHandling->Transmission.ucNumberOfGears ); fprintf ( poo, "Transmission.ucUnknown = %u\n", pHandling->Transmission.ucUnknown ); fprintf ( poo, "Transmission.uiHandlingFlags = 0x%X\n", pHandling->Transmission.uiHandlingFlags ); fprintf ( poo, "Transmission.fEngineAcceleration = %f\n", pHandling->Transmission.fEngineAcceleration ); fprintf ( poo, "Transmission.fEngineInertia = %f\n", pHandling->Transmission.fEngineInertia ); fprintf ( poo, "Transmission.fMaxVelocity = %f\n", pHandling->Transmission.fMaxVelocity ); fprintf ( poo, "Transmission.fUnknown2 [0] = %f\n", pHandling->Transmission.fUnknown2 [0] ); fprintf ( poo, "Transmission.fUnknown2 [1] = %f\n", pHandling->Transmission.fUnknown2 [1] ); fprintf ( poo, "Transmission.fUnknown2 [2] = %f\n", pHandling->Transmission.fUnknown2 [2] ); fprintf ( poo, "fBrakeDeceleration = %f\n", pHandling->fBrakeDeceleration ); fprintf ( poo, "fBrakeBias = %f\n", pHandling->fBrakeBias ); fprintf ( poo, "bABS = %u\n", pHandling->bABS ); fprintf ( poo, "fSteeringLock = %f\n", pHandling->fSteeringLock ); fprintf ( poo, "fTractionLoss = %f\n", pHandling->fTractionLoss ); fprintf ( poo, "fTractionBias = %f\n", pHandling->fTractionBias ); fprintf ( poo, "fSuspensionForceLevel = %f\n", pHandling->fSuspensionForceLevel ); fprintf ( poo, "fSuspensionDamping = %f\n", pHandling->fSuspensionDamping ); fprintf ( poo, "fSuspensionHighSpdDamping = %f\n", pHandling->fSuspensionHighSpdDamping ); fprintf ( poo, "fSuspensionUpperLimit = %f\n", pHandling->fSuspensionUpperLimit ); fprintf ( poo, "fSuspensionLowerLimit = %f\n", pHandling->fSuspensionLowerLimit ); fprintf ( poo, "fSuspensionFrontRearBias = %f\n", pHandling->fSuspensionFrontRearBias ); fprintf ( poo, "fSuspensionAntiDiveMultiplier = %f\n", pHandling->fSuspensionAntiDiveMultiplier ); fprintf ( poo, "fCollisionDamageMultiplier = %f\n", pHandling->fCollisionDamageMultiplier ); fprintf ( poo, "uiModelFlags = %X\n", pHandling->uiModelFlags ); fprintf ( poo, "uiHandlingFlags = %X\n", pHandling->uiHandlingFlags ); fprintf ( poo, "fSeatOffsetDistance = %f\n", pHandling->fSeatOffsetDistance ); fprintf ( poo, "uiMonetary = %u\n", pHandling->uiMonetary ); fprintf ( poo, "ucHeadLight = 0x%X\n", pHandling->ucHeadLight ); fprintf ( poo, "ucTailLight = 0x%X\n", pHandling->ucTailLight ); fprintf ( poo, "ucAnimGroup = 0x%X\n", pHandling->ucAnimGroup ); fprintf ( poo, "ucUnused = 0x%X\n", pHandling->ucUnused ); fprintf ( poo, "iUnknown7 = %f, %X\n", pHandling->iUnknown7, pHandling->iUnknown7 ); pHandling += 1; } g_pCore->ChatPrintf ( "Dumped", false ); fclose ( poo ); } } */ else if ( strnicmp ( szString, "moveug", 6 ) == 0 ) { if ( pVehicleManager->Count () > 0 ) { CClientVehicle* pVehicle = *pVehicleManager->IterBegin (); /* CClientPed* pModel = pVehicle->GetOccupant ( 0 ); if ( !pModel ) { CClientPlayer* pPlayer = new CClientPlayer ( g_pClientGame->GetManager (), 50 ); pModel = pPlayer->LoadModel ( 0 ); pModel->WarpIntoVehicle ( pVehicle ); } */ pVehicle->RemoveTargetPosition (); pVehicle->RemoveTargetRotation (); CVector vecT; pVehicle->GetPosition ( vecT ); vecT.fZ = (float)atof ( szString + 7 ); pVehicle->SetPosition ( vecT ); g_pCore->ChatPrintf ( "Done", false ); } } else if ( strnicmp ( szString, "nocol", 5 ) == 0 ) { if ( pVehicleManager->Count () > 0 ) { CClientVehicle* pVehicle = *pVehicleManager->IterBegin (); pVehicle->SetCollisionEnabled ( false ); g_pCore->ChatPrintf ( "Done", false ); } } else if ( stricmp ( szString, "resetdamage" ) == 0 ) { g_pClientGame->GetPlayerManager ()->GetLocalPlayer ()->GetGamePlayer ()->ResetLastDamage (); } else if ( strnicmp ( szString, "fuckveh", 7 ) == 0 ) { CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { pVehicle->SetTargetPosition ( CVector ( 0, 0, 0 ), TICK_RATE ); pVehicle->SetTargetRotation ( CVector ( 0, 0, 0 ), TICK_RATE ); g_pCore->ChatPrintf ( "Done", false ); } } else if ( stricmp ( szString, "ped" ) == 0 ) { CClientPed* pPed = new CClientPed ( g_pClientGame->GetManager (), INVALID_ELEMENT_ID, 9 ); vecLocal.fX += 5.0f; pPed->SetPosition ( vecLocal ); } else if ( strnicmp ( szString, "callit", 6 ) == 0 ) { FILE* pFile = fopen ( "C:/dump.txt", "w+" ); for ( int i = 0; i < 400; i++ ) { int iIndex = i; const char* szName = NULL; _asm { mov eax, 0x4D3A30 push iIndex call eax mov szName, eax add esp, 4 } fprintf ( pFile, "%i: %s\n", iIndex, szName ); } fclose ( pFile ); } else if ( strnicmp ( szString, "veh", 3 ) == 0 ) { int i = 600; FILE* p = fopen ( "C:/dump.txt", "w+" ); for ( int a = 0; a < 13; a++ ) { g_pGame->GetModelInfo ( i )->ModelAddRef ( BLOCKING, "CFoo::Test" ); CVehicle* pVehicle = g_pGame->GetPools ()->AddVehicle ( (eVehicleTypes)i, 5, 5 ); DWORD* dw2 = (DWORD*)(((DWORD)pVehicle->GetVehicleInterface ()) + 0xE1 * 4 ); DWORD dw = *dw2; dw = dw + 4; dw = dw - 0xC2B9E0; dw = dw / 224; fprintf ( p, "Array [%u] = %u;\n", i, dw ); g_pGame->GetPools ()->RemoveVehicle ( pVehicle ); fflush ( p ); g_pGame->GetModelInfo ( i )->RemoveRef ( ); i++; } fclose ( p ); } else if ( strnicmp ( szString, "groups", 6 ) == 0 ) { FILE* pFile = fopen ( "C:/dump.txt", "w+" ); int i = 0; for ( ; i < 139; i++ ) { fprintf ( pFile, "==%s [%s] (%i)==\n", pGroups [i].szGroupName, pGroups [i].szSomething, i ); uint i2 = 0; for ( ; i2 < pGroups [i].ulAnimCount; i2++ ) { const char* szAnimName = pGroups [i].pAnimNames [i2]; if ( szAnimName [0] ) { fprintf ( pFile, "''%i'': %s<br>\n", i2, szAnimName ); } } fprintf ( pFile, "\n" ); } fclose ( pFile ); } else if ( strnicmp ( szString, "getshot", 7 ) == 0 ) { if ( pLocal->GetGamePlayer ()->GetCanBeShotInVehicle () ) { g_pCore->ChatEcho ( "true" ); } else { g_pCore->ChatEcho ( "false" ); } } else if ( strnicmp ( szString, "gettest", 7 ) == 0 ) { if ( pLocal->GetGamePlayer ()->GetTestForShotInVehicle () ) { g_pCore->ChatEcho ( "true" ); } else { g_pCore->ChatEcho ( "false" ); } } else if ( strnicmp ( szString, "setshot", 7 ) == 0 ) { pLocal->GetGamePlayer ()->SetCanBeShotInVehicle ( true ); } else if ( strnicmp ( szString, "settest", 8 ) == 0 ) { pLocal->GetGamePlayer ()->SetTestForShotInVehicle ( true ); } else if ( stricmp ( szString, "applytest" ) == 0 ) { DWORD oldProt, oldProt2; VirtualProtect((LPVOID)0x5E8FFB,6,PAGE_EXECUTE_READWRITE,&oldProt); *(unsigned char*) (0x5E8FFB ) = 0x90; *(unsigned char*) (0x5E8FFC ) = 0x90; *(unsigned char*) (0x5E8FFD ) = 0x90; *(unsigned char*) (0x5E8FFE ) = 0x90; *(unsigned char*) (0x5E8FFF ) = 0x90; *(unsigned char*) (0x5E9000 ) = 0x90; VirtualProtect((LPVOID)0x5E8FFB,6,oldProt,&oldProt2); } }
void SetupHooks() { logInfo("Setting up hooks."); if(hooksSetup) return; HMODULE d3dMod = GetModuleHandle("d3d9.dll"); if(d3dMod == NULL) { ErrorMsg("GetModuleHandle(d3d9.dll)"); return; } HMODULE d3dxMod = LoadLibrary("d3dx9_43.dll"); if(d3dxMod == NULL) { ErrorMsg("LoadLibrary(d3dx9_43.dll)"); return; } HMODULE winmmMod = LoadLibrary("winmm.dll"); if(winmmMod == NULL) { ErrorMsg("LoadLibrary(winmm.dll)"); return; } D3DCreate = (pDirect3DCreate9)GetProcAddress(d3dMod, "Direct3DCreate9"); if(D3DCreate == NULL) { ErrorMsg("GetProcAddress(d3dMod, \"Direct3DCreate9\")"); return; } oPlaySound = (pPlaySoundA)GetProcAddress(winmmMod, "PlaySoundA"); if(oPlaySound == NULL) { ErrorMsg("GetProcAddress(winmmMod, \"PlaySoundA\")"); return; } oD3DXCreateFont = (pD3DXCreateFont)GetProcAddress(d3dxMod, "D3DXCreateFontA"); if(oD3DXCreateFont == NULL) { ErrorMsg("GetProcAddress(d3dxMod, \"D3DXCreateFontA\")"); return; } oD3DXCreateLine = (pD3DXCreateLine)GetProcAddress(d3dxMod, "D3DXCreateLine"); if(oD3DXCreateLine == NULL) { ErrorMsg("GetProcAddress(d3dxMod, \"D3DXCreateLine\")"); return; } // Create a dummy window to call CreateDevice on HWND hwnd; hwnd = CreateWindow("BUTTON", "APMAlertDummyWindow", 0, 0, 0, 27, 27, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { ErrorMsg("CreateWindow"); return; } //UpdateWindow(hwnd); IDirect3D9 *pD3D = D3DCreate(D3D_SDK_VERSION); if(pD3D == NULL) { ErrorMsg("Direct3DCreate9"); return; } D3DDISPLAYMODE d3ddm; HRESULT hRes = pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); if(FAILED(hRes)) { char errorMsg[512]; const char * dxErrorStr = DXGetErrorString(hRes); sprintf_s(errorMsg, 512, "GetAdapterDisplayMode returned 0x%08x: %s", hRes, dxErrorStr); logError(errorMsg); goto cleanup; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp)); d3dpp.Windowed = true; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = d3ddm.Format; IDirect3DDevice9 * ppD3DDevice; hRes = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_DISABLE_DRIVER_MANAGEMENT, &d3dpp, &ppD3DDevice); if(FAILED(hRes)) { char errorMsg[512]; const char * dxErrorStr = DXGetErrorString(hRes); sprintf_s(errorMsg, 512, "CreateDevice returned 0x%08x: %s", hRes, dxErrorStr); logError(errorMsg); goto cleanup; } // Get our function pointers from the virtual table // This pointer dereferencing works because the virtual table is the first item in memory // of the every object void ** vTable = *((void***)ppD3DDevice); // Access the function pointers we need addrEndScene = vTable[42]; // EndScene is the 43rd function (you can just count in the interface decl in the header) /* char path_d3d9_dll[MAX_PATH]; GetSystemDirectory(path_d3d9_dll, MAX_PATH); strncat_s(path_d3d9_dll, MAX_PATH, "\\d3d9.dll", 10); SIZE_T offset = (unsigned int)addrEndScene - (unsigned int)GetModuleHandle(path_d3d9_dll); printf("EndScene() Addr: 0x%08x -- SC2.exe!d3d9.dll+0x%x\n", addrEndScene, offset); */ DWORD oldProtect; // backup the top 6 bytes of each function if(VirtualProtect(addrEndScene, 6, PAGE_EXECUTE_READWRITE, &oldProtect) == FALSE) { ErrorMsg("VirtualProtect"); return; // make the address read/writable } memcpy(backup_EndScene, addrEndScene, 6); VirtualProtect(addrEndScene, 6, oldProtect, &oldProtect); // restore old protection // We are going to write over the top 6 bytes of every function we want to hook. // This way, whenever they are called, we can jump to our custom hook function and run our own stuff. // To maintain proper game functionality we will restore the backup code, run the function as it should be, // then restore our patch code at the top when it returns to our hook function. // create our 6 byte patch consisting of: push <addr_hook>; retn (essentially a call that doesn't disturb the stack) patch_EndScene[0] = 0x68; // PUSH *((DWORD *)(patch_EndScene+1)) = (DWORD)&hkEndScene; // value to push patch_EndScene[5] = 0xC3; // RETN hooksSetup = true; logInfo("Hooks setup and ready for use."); ppD3DDevice->Release(); ppD3DDevice = NULL; pD3D->Release(); pD3D = NULL; cleanup: if(pD3D != NULL) pD3D->Release(); // Destroy the dummy window DestroyWindow(hwnd); }
int CreateGeneralBridge(void **BridgePointer, void *fn, unsigned char *fill, int fill_len, int alignment, int create_stackframe) { HANDLE ProcessHeap; unsigned long OldProtection; unsigned char unused[5]; int offset; unsigned char *c_bridge; int size_desired; int i; size_desired = 5; if(create_stackframe) { size_desired += 5; } if(fill != NULL) { size_desired += 5; } // Create the bridge ProcessHeap = GetProcessHeap(); if (!ProcessHeap) return 0; *BridgePointer = HeapAlloc(ProcessHeap, HEAP_ZERO_MEMORY, size_desired); if (!*BridgePointer) return 0; // Make it executable if (!VirtualProtect(*BridgePointer, size_desired, PAGE_EXECUTE_READWRITE, &OldProtection)) { return 0; } offset = 0; // Restore the stackframe code if(create_stackframe && CREATE_FRAME_FIRST) { if (!CreateStackFrame(*BridgePointer, (alignment == WINDOWS_LIBRARY) )) { return 0; } offset += 5; } c_bridge = (unsigned char *)*BridgePointer; if(fill != NULL && alignment != WINDOWS_LIBRARY) { for(i=0; i < fill_len;i++) { c_bridge[offset+i] = fill[i]; } offset += fill_len; } if(create_stackframe && !CREATE_FRAME_FIRST) { if (!CreateStackFrame(&(c_bridge[offset]), (alignment == WINDOWS_LIBRARY))) { return 0; } offset += 5; } if(alignment == WINDOWS_LIBRARY) { if (!make_jmp( &(c_bridge[offset]) , ((unsigned char *) fn) + 5, unused, 5)) { return 0; } } else { if (!make_jmp( &(c_bridge[offset]) , ((unsigned char *) fn) + alignment + 5, unused, 5)) { return 0; } } return 1; }
static inline void fix_permissions(void *addr, size_t size) { DWORD protect_val; VirtualProtect(addr, size, PAGE_EXECUTE_READWRITE, &protect_val); }
LONG WINAPI DetourAttachEx(PVOID *ppPointer, PVOID pDetour, PDETOUR_TRAMPOLINE *ppRealTrampoline, PVOID *ppRealTarget, PVOID *ppRealDetour) { LONG error = NO_ERROR; if (ppRealTrampoline != NULL) { *ppRealTrampoline = NULL; } if (ppRealTarget != NULL) { *ppRealTarget = NULL; } if (ppRealDetour != NULL) { *ppRealDetour = NULL; } if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId)); return ERROR_INVALID_OPERATION; } // If any of the pending operations failed, then we don't need to do this. if (s_nPendingError != NO_ERROR) { DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError)); return s_nPendingError; } if (ppPointer == NULL) { DETOUR_TRACE(("ppPointer is null\n")); return ERROR_INVALID_HANDLE; } if (*ppPointer == NULL) { error = ERROR_INVALID_HANDLE; s_nPendingError = error; s_ppPendingError = ppPointer; DETOUR_TRACE(("*ppPointer is null (ppPointer=%p)\n", ppPointer)); DETOUR_BREAK(); return error; } PBYTE pbTarget = (PBYTE)*ppPointer; PDETOUR_TRAMPOLINE pTrampoline = NULL; DetourOperation *o = NULL; #ifdef DETOURS_IA64 #error Feature not supported in this release. #else // DETOURS_IA64 pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL); pDetour = DetourCodeFromPointer(pDetour, NULL); #endif // !DETOURS_IA64 // Don't follow a jump if its destination is the target function. // This happens when the detour does nothing other than call the target. if (pDetour == (PVOID)pbTarget) { if (s_fIgnoreTooSmall) { goto stop; } else { DETOUR_BREAK(); goto fail; } } if (ppRealTarget != NULL) { *ppRealTarget = pbTarget; } if (ppRealDetour != NULL) { *ppRealDetour = pDetour; } o = new DetourOperation; if (o == NULL) { error = ERROR_NOT_ENOUGH_MEMORY; fail: s_nPendingError = error; DETOUR_BREAK(); stop: if (pTrampoline != NULL) { detour_free_trampoline(pTrampoline); pTrampoline = NULL; if (ppRealTrampoline != NULL) { *ppRealTrampoline = NULL; } } if (o != NULL) { delete o; o = NULL; } s_ppPendingError = ppPointer; return error; } pTrampoline = detour_alloc_trampoline(pbTarget); if (pTrampoline == NULL) { error = ERROR_NOT_ENOUGH_MEMORY; DETOUR_BREAK(); goto fail; } if (ppRealTrampoline != NULL) { *ppRealTrampoline = pTrampoline; } DETOUR_TRACE(("detours: pbTramp=%p, pDetour=%p\n", pTrampoline, pDetour)); memset(pTrampoline->rAlign, 0, sizeof(pTrampoline->rAlign)); // Determine the number of movable target instructions. PBYTE pbSrc = pbTarget; PBYTE pbTrampoline = pTrampoline->rbCode; PBYTE pbPool = pbTrampoline + sizeof(pTrampoline->rbCode); ULONG cbTarget = 0; ULONG cbJump = SIZE_OF_JMP; ULONG nAlign = 0; #ifdef DETOURS_ARM #error Feature not supported in this release. #endif while (cbTarget < cbJump) { PBYTE pbOp = pbSrc; LONG lExtra = 0; DETOUR_TRACE((" DetourCopyInstruction(%p,%p)\n", pbTrampoline, pbSrc)); pbSrc = (PBYTE) DetourCopyInstruction(pbTrampoline, (PVOID*)&pbPool, pbSrc, NULL, &lExtra); DETOUR_TRACE((" DetourCopyInstruction() = %p (%d bytes)\n", pbSrc, (int)(pbSrc - pbOp))); pbTrampoline += (pbSrc - pbOp) + lExtra; cbTarget = (LONG)(pbSrc - pbTarget); pTrampoline->rAlign[nAlign].obTarget = cbTarget; pTrampoline->rAlign[nAlign].obTrampoline = pbTrampoline - pTrampoline->rbCode; if (detour_does_code_end_function(pbOp)) { break; } } // Consume, but don't duplicate padding if it is needed and available. while (cbTarget < cbJump) { LONG cFiller = detour_is_code_filler(pbSrc); if (cFiller == 0) { break; } pbSrc += cFiller; cbTarget = (LONG)(pbSrc - pbTarget); } #if DETOUR_DEBUG { DETOUR_TRACE((" detours: rAlign [")); LONG n = 0; for (n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) { if (pTrampoline->rAlign[n].obTarget == 0 && pTrampoline->rAlign[n].obTrampoline == 0) { break; } DETOUR_TRACE((" %d/%d", pTrampoline->rAlign[n].obTarget, pTrampoline->rAlign[n].obTrampoline )); } DETOUR_TRACE((" ]\n")); } #endif if (cbTarget < cbJump || nAlign > ARRAYSIZE(pTrampoline->rAlign)) { // Too few instructions. error = ERROR_INVALID_BLOCK; if (s_fIgnoreTooSmall) { goto stop; } else { DETOUR_BREAK(); goto fail; } } if (pbTrampoline > pbPool) { __debugbreak(); } #if 0 // [GalenH] if (cbTarget < pbTrampoline - pTrampoline->rbCode) { __debugbreak(); } #endif pTrampoline->cbCode = (BYTE)(pbTrampoline - pTrampoline->rbCode); pTrampoline->cbRestore = (BYTE)cbTarget; CopyMemory(pTrampoline->rbRestore, pbTarget, cbTarget); #if !defined(DETOURS_IA64) if (cbTarget > sizeof(pTrampoline->rbCode) - cbJump) { // Too many instructions. error = ERROR_INVALID_HANDLE; DETOUR_BREAK(); goto fail; } #endif // !DETOURS_IA64 pTrampoline->pbRemain = pbTarget + cbTarget; pTrampoline->pbDetour = (PBYTE)pDetour; #ifdef DETOURS_IA64 #error Feature not supported in this release. #endif // DETOURS_IA64 pbTrampoline = pTrampoline->rbCode + pTrampoline->cbCode; #ifdef DETOURS_X64 #error Feature not supported in this release. #endif // DETOURS_X64 #ifdef DETOURS_X86 pbTrampoline = detour_gen_jmp_immediate(pbTrampoline, pTrampoline->pbRemain); pbTrampoline = detour_gen_brk(pbTrampoline, pbPool); #endif // DETOURS_X86 #ifdef DETOURS_ARM #error Feature not supported in this release. #endif // DETOURS_ARM DWORD dwOld = 0; if (!VirtualProtect(pbTarget, cbTarget, PAGE_EXECUTE_READWRITE, &dwOld)) { error = GetLastError(); DETOUR_BREAK(); goto fail; } DETOUR_TRACE(("detours: pbTarget=%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x\n", pbTarget, pbTarget[0], pbTarget[1], pbTarget[2], pbTarget[3], pbTarget[4], pbTarget[5], pbTarget[6], pbTarget[7], pbTarget[8], pbTarget[9], pbTarget[10], pbTarget[11])); DETOUR_TRACE(("detours: pbTramp =%p: " "%02x %02x %02x %02x " "%02x %02x %02x %02x " "%02x %02x %02x %02x\n", pTrampoline, pTrampoline->rbCode[0], pTrampoline->rbCode[1], pTrampoline->rbCode[2], pTrampoline->rbCode[3], pTrampoline->rbCode[4], pTrampoline->rbCode[5], pTrampoline->rbCode[6], pTrampoline->rbCode[7], pTrampoline->rbCode[8], pTrampoline->rbCode[9], pTrampoline->rbCode[10], pTrampoline->rbCode[11])); o->fIsRemove = FALSE; o->ppbPointer = (PBYTE*)ppPointer; o->pTrampoline = pTrampoline; o->pbTarget = pbTarget; o->dwPerm = dwOld; o->pNext = s_pPendingOperations; s_pPendingOperations = o; return NO_ERROR; }
DWORD WINAPI StormThread1( void ) { // Local Variables int iCount = 0 ; //static Sync CritSec; Sleep( 1000 ) ; // Sleep 1 second Log("\n ====================================================== ") ; Log("\n =============== StormThread1 SEPERATOR =============== ") ; Log("\n ====================================================== ") ; do { if( iCount != 3 ) { pGlobal->g_Game_Mod_Base = (DWORD64)( GetModuleHandle( "H1Z1.exe" ) ) ; pGlobal->g_H_Game_Mod_Base = (HANDLE)pGlobal->g_Game_Mod_Base ; pGlobal->g_D3D9_Mod_Base = (DWORD64)( GetModuleHandle( "d3d9.dll" ) ) ; Sleep( 100 ) ; // Sleep .1 second } else { Log( "Global Bases Failed: %d\n", iCount ) ; break ; } iCount++ ; } while( !pGlobal->g_Game_Mod_Base && !pGlobal->g_D3D9_Mod_Base ) ; //Log( "\nH1Z1.exe - Base Address: %016llX", pGlobal->g_Game_Mod_Base ) ; //Log( "\nH1Z1.exe - Handle: %08X", pGlobal->g_H_Game_Mod_Base ) ; //Log( "\ng_D3D_Mod_Base: %016llX", pGlobal->g_D3D9_Mod_Base ) ; pGlobal->g_Game_Mod_Size = (DWORD64)GetModuleSize( "H1Z1.exe" ) ; //Log( "\nH1Z1.exe - Size: %016llX\n", pGlobal->g_Game_Mod_Size ) ; // Setup Overlay OverlayWindow( VTable ) ; // Enable Debug Privileges EnableDebugPriv() ; // OpenProcess with All Access pGlobal->g_PseudoHandle = GetCurrentProcess() ; //Log( "PseudoHandle: %016llX\n", pGlobal->g_PseudoHandle ) ; pGlobal->g_AllAccess_Process_Handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, Get_PID_From_Process_Handle( pGlobal->g_PseudoHandle ) ) ; Log( "All Access Handle: %016llX\n", pGlobal->g_AllAccess_Process_Handle ) ; /* =========================================================================== */ /* Present() & Gameoverlayrenderer64 HOOK Related Information */ /* =========================================================================== */ // Define & Initialize Patch Info Structure pPatchInfo = (PPATCH_INFO)malloc( sizeof( PATCH_INFO ) ) ; memset( pPatchInfo, 0xEE, sizeof(PATCH_INFO) ) ; //Log( "pPatchInfo: %016llX", pPatchInfo ) ; // Assign The Present() addess within SystemCall pPatchInfo->SystemCall = (BYTE*)VTable[ PR ] ; // This is Present() within directx 9 sdk //Log( "pPatchInfo->SystemCall: %016llX", pPatchInfo->SystemCall ) ; // Define Signature & Mask For Present() pPatchInfo->SignatureSize = 0xF ; memcpy( pPatchInfo->Signature, "\xE9\x00\x00\x00\x00\x58\x08\x00\x00\x68\x00\x00\x00\x00\x00", pPatchInfo->SignatureSize ) ; memcpy( pPatchInfo->SignatureMask, "x????xx??x?????", pPatchInfo->SignatureSize ) ; //Log( "pPatchInfo->SignatureSize; %016llX", &pPatchInfo->SignatureSize ) ; //Log( "pPatchInfo->Signature: %016llX", pPatchInfo->Signature ) ; //Log( "pPatchInfo->SignatureMask: %016llX", pPatchInfo->SignatureMask ) ; // Setup Prologue Patch pPatchInfo->PrologPatchOffset = 0x0 ; pPatchInfo->SizePrologPatch = 0xF ; memcpy( pPatchInfo->PrologPatch, "\x48\xB8\xDE\xC0\xBE\xBA\xFE\xCA\xED\xFE\x50\xC3\x90\x90\x90", pPatchInfo->SizePrologPatch ) ; //Log( "pPatchInfo->PrologPatchOffset: %016llX", &pPatchInfo->PrologPatchOffset ) ; //Log( "pPatchInfo->SizePrologPatch: %016llX", &pPatchInfo->SizePrologPatch ) ; //Log( "pPatchInfo->PrologPatch: %016llX", pPatchInfo->PrologPatch ) ; // Assign Detour Functions - Prologue & Epilogue Assignment. pPatchInfo->PrologDetour = (BYTE*)Prolog_Present ; //Log( "pPatchInfo->PrologDetour %016llX", pPatchInfo->PrologDetour ) ; // Make Sure our System Call Region has the proper RWE permissions. DWORD old_protect ; if( VirtualProtect( pPatchInfo->SystemCall, pPatchInfo->SignatureSize, PAGE_EXECUTE_READWRITE, &old_protect ) ) { // Verify Signature @ Function We Want To Hook if( VerifySignature( pPatchInfo->SignatureMask, pPatchInfo->Signature, pPatchInfo->SignatureSize, pPatchInfo->SystemCall ) ) { // Get Prologues Existing Bytes From Function We Want To Hook memcpy( pPatchInfo->PrologOriginal, pPatchInfo->SystemCall, pPatchInfo->SignatureSize ) ; //Log( "pPatchInfo->PrologOriginal: %016llX", pPatchInfo->PrologOriginal ) ; // Assign our patches the proper addresses to our Detour Functions. // Prologue MakePatchLegit( pPatchInfo->PrologDetour, pPatchInfo->PrologPatch ) ; //Log( "pPatchInfo->PrologPatch After Fixup: %016llX", pPatchInfo->PrologPatch ) ; // Follow Steam Hook FixUpSteamHook( pPatchInfo ) ; // Prologue Hook Complete InsertDetour( pPatchInfo->SystemCall, pPatchInfo->PrologPatch, pPatchInfo->SizePrologPatch, pPatchInfo->PrologPatchOffset ) ; /* Activate Hook */ Log( "First Hook Complete" ); FixUpGameOverlayHook( pPatchInfo ) ; } else { Log( "Verify Signature Failed" ) ; } } else { Log( "First HOOK Virtual Protect Failed" ) ; } //CritSec.lock() ; // Prologue Hook //InsertDetour( pPatchInfo->SystemCall, pPatchInfo->PrologPatch, pPatchInfo->SizePrologPatch, pPatchInfo->PrologPatchOffset ) ; /* Activate Hook */ //Log( "First Hook Complete" ) ; //// Call Hook //InsertDetour( pPatchInfo->GameOverlayPatchCall, pPatchInfo->PatchCall, 0x6, 0 ) ; /* Activate Hook */ //Log( "Second HOOK Complete" ) ; //CritSec.unlock() ; //pCanvas = &Canvas ; /* =========================================================================== */ /* Clean-Up Related Information */ /* =========================================================================== */ //free( pPatchInfo ) ; //pPatchInfo = NULL ; return 0 ; } // End Of StormThread1
DWORD VirtualProtect(DWORD pAddress, DWORD len, DWORD prot) { DWORD oldprot = 0; VirtualProtect((void*)pAddress, len, prot, &oldprot); return oldprot; }
bool PLH::VEHHook::Hook() { //Lock the TargetMutex for thread safe vector operations std::lock_guard<std::mutex> m_Lock(m_TargetMutex); if (m_ThisCtx.m_Type == VEHMethod::INT3_BP) { //Write INT3 BreakPoint MemoryProtect Protector(m_ThisCtx.m_Src, 1, PAGE_EXECUTE_READWRITE); m_ThisCtx.m_StorageByte = *m_ThisCtx.m_Src; *m_ThisCtx.m_Src = 0xCC; m_HookTargets.push_back(m_ThisCtx); }else if (m_ThisCtx.m_Type == VEHMethod::HARDWARE_BP) { CONTEXT Ctx; Ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; if (!GetThreadContext(GetCurrentThread(), &Ctx)) { PostError(PLH::RuntimeError(RuntimeError::Severity::Critical, "Failed to get context")); return false; } uint8_t RegIndex = 0; bool FoundReg = false; for (; RegIndex < 4; RegIndex++) { if ((Ctx.Dr7 & (1 << (RegIndex * 2))) == 0) { FoundReg = true; break; } } if (!FoundReg) { PostError(PLH::RuntimeError(RuntimeError::Severity::Critical, "Failed to find free Reg")); return false; } switch (RegIndex) { case 0: Ctx.Dr0 = (DWORD_PTR)m_ThisCtx.m_Src; break; case 1: Ctx.Dr1 = (DWORD_PTR)m_ThisCtx.m_Src; break; case 2: Ctx.Dr2 = (DWORD_PTR)m_ThisCtx.m_Src; break; case 3: Ctx.Dr3 = (DWORD_PTR)m_ThisCtx.m_Src; break; default: PostError(PLH::RuntimeError(RuntimeError::Severity::Critical, "PolyHook VEH: Invalid Debug Register Index")); return false; } //Turn a local register on Ctx.Dr7 |= 1 << (2*RegIndex); m_ThisCtx.m_StorageByte = RegIndex; //Still need to call suspend thread *TODO* if (!SetThreadContext(GetCurrentThread(), &Ctx)) { PostError(PLH::RuntimeError(RuntimeError::Severity::Critical, "PolyHook VEH: Failed to set thread context")); return false; } m_HookTargets.push_back(m_ThisCtx); }else if (m_ThisCtx.m_Type == VEHMethod::GUARD_PAGE){ //Read current page protection MEMORY_BASIC_INFORMATION mbi; VirtualQuery(m_ThisCtx.m_Src, &mbi, sizeof(mbi)); //can't use Page Guards with NO_ACCESS flag if (mbi.Protect & PAGE_NOACCESS) { PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook VEH: Cannot hook page with NOACCESS Flag")); return false; } if (AreInSamePage((BYTE*)&PLH::VEHHook::VEHHandler, m_ThisCtx.m_Src)) { PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook VEH: Cannot hook page on same page as the VEH")); return false; } //!!!!COMPILER SPECIFIC HACK HERE!!!!! bool(PLH::VEHHook::* pHookFunc)(void) = &PLH::VEHHook::Hook; if (AreInSamePage((BYTE*&)pHookFunc, m_ThisCtx.m_Src)) { PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook VEH: Cannot hook page on same page as the hooking function")); return false; } m_HookTargets.push_back(m_ThisCtx); //Write Page Guard protection DWORD OldProtection; VirtualProtect(m_ThisCtx.m_Src, 1 ,PAGE_EXECUTE_READWRITE | PAGE_GUARD, &OldProtection); } return true; }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { DWORD thispid = GetCurrentProcessId(); char modname[16] = "testa.dll"; DWORD baseaddress = GetModuleHandle(modname); DWORD endaddress = GetProcAddress(baseaddress, "endmarker"); unsigned int memlen = ((endaddress - baseaddress)); DWORD newprotect = 0x40; DWORD oldprotect = NULL; int vpretval = VirtualProtect( baseaddress, memlen, newprotect, &oldprotect); #ifdef DEBUG if (vpretval!=0) { printf("Memory successfully set to RWX.\n"); printf("PID: %d\n", thispid); printf("Base address of module: 0x%8x\n", baseaddress); printf("End address of meaning: 0x%8x\n", endaddress); printf("Old protection: 0x%8x\n", oldprotect); printf("New protection: 0x%8x\n", newprotect); printf("Length in bytes: 0x%8x\n", memlen); printf("Return value from VirtualProtect: %d\n", vpretval); } else { printf("No joy...\n"); printf("PID: %d\n", thispid); printf("Base address of module: 0x%8x\n", baseaddress); printf("End address of meaning: 0x%8x\n", endaddress); printf("Old protection: 0x%8x\n", oldprotect); printf("New protection: 0x%8x\n", newprotect); printf("Length in bytes: 0x%8x\n", memlen); printf("Return value from VirtualProtect: %d\n", vpretval); } vpretval = VirtualProtect( baseaddress, memlen, newprotect, &oldprotect); if (vpretval!=0) { printf("\n\n#########################################################\nJust verifying that I did it right here...\nI wanted to make sure old protection actually changed.\n"); printf("PID: %d\n", thispid); printf("Base address of module: 0x%8x\n", baseaddress); printf("Old protection: 0x%8x\n", oldprotect); printf("New protection: 0x%8x\n", newprotect); printf("Length in bytes: 0x%8x\n", memlen); printf("Return value from VirtualProtect: %d\n", vpretval); } else { printf("No joy...\n"); } #endif break; } case DLL_PROCESS_DETACH: // Code to run when the DLL is freed // printf ("Unload working...\n"); break; case DLL_THREAD_ATTACH: // Code to run when a thread is created during the DLL's lifetime // printf ("ThreadLoad working...\n"); break; case DLL_THREAD_DETACH: // Code to run when a thread ends normally. // printf ("ThreadUnload working...\n"); break; } return TRUE; }
bool PLH::MemoryProtect::Protect(void* Address, size_t Size, DWORD ProtectionFlags) { return VirtualProtect(Address, Size, ProtectionFlags, &m_OldProtection); }
void CDMA::PI_DMA_WRITE() { DWORD PI_WR_LEN_REG = ((g_Reg->PI_WR_LEN_REG) & 0x00FFFFFFul) + 1; if ((PI_WR_LEN_REG & 1) != 0) { PI_WR_LEN_REG += 1; /* fixes AI Shougi 3, Doraemon 3, etc. */ } g_Reg->PI_STATUS_REG |= PI_STATUS_DMA_BUSY; if ( g_Reg->PI_DRAM_ADDR_REG + PI_WR_LEN_REG > g_MMU->RdramSize()) { if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { g_Notify->DisplayError(L"PI_DMA_WRITE not in Memory"); } g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; g_Reg->MI_INTR_REG |= MI_INTR_PI; g_Reg->CheckInterrupts(); return; } if ( g_Reg->PI_CART_ADDR_REG >= 0x08000000 && g_Reg->PI_CART_ADDR_REG <= 0x08010000) { if (g_System->m_SaveUsing == SaveChip_Auto) { g_System->m_SaveUsing = SaveChip_Sram; } if (g_System->m_SaveUsing == SaveChip_Sram) { m_Sram.DmaFromSram( g_MMU->Rdram()+g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_CART_ADDR_REG - 0x08000000, PI_WR_LEN_REG ); g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; g_Reg->MI_INTR_REG |= MI_INTR_PI; g_Reg->CheckInterrupts(); return; } if (g_System->m_SaveUsing == SaveChip_FlashRam) { m_FlashRam.DmaFromFlashram( g_MMU->Rdram()+g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_CART_ADDR_REG - 0x08000000, PI_WR_LEN_REG ); g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; g_Reg->MI_INTR_REG |= MI_INTR_PI; g_Reg->CheckInterrupts(); } return; } if ( g_Reg->PI_CART_ADDR_REG >= 0x10000000 && g_Reg->PI_CART_ADDR_REG <= 0x1FBFFFFF) { DWORD i; #ifdef tofix #ifdef ROM_IN_MAPSPACE if (WrittenToRom) { DWORD OldProtect; VirtualProtect(ROM,m_RomFileSize,PAGE_READONLY, &OldProtect); } #endif #endif BYTE * ROM = g_Rom->GetRomAddress(); BYTE * RDRAM = g_MMU->Rdram(); g_Reg->PI_CART_ADDR_REG -= 0x10000000; if (g_Reg->PI_CART_ADDR_REG + PI_WR_LEN_REG < g_Rom->GetRomSize()) { for (i = 0; i < PI_WR_LEN_REG; i ++) { *(RDRAM+((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM+((g_Reg->PI_CART_ADDR_REG + i) ^ 3)); } } else { DWORD Len; Len = g_Rom->GetRomSize() - g_Reg->PI_CART_ADDR_REG; for (i = 0; i < Len; i ++) { *(RDRAM+((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(ROM+((g_Reg->PI_CART_ADDR_REG + i) ^ 3)); } for (i = Len; i < PI_WR_LEN_REG - Len; i ++) { *(RDRAM+((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0; } } g_Reg->PI_CART_ADDR_REG += 0x10000000; if (!g_System->DmaUsed()) { g_System->SetDmaUsed(true); OnFirstDMA(); } if (g_Recompiler && g_System->bSMM_PIDMA()) { g_Recompiler->ClearRecompCode_Phys(g_Reg->PI_DRAM_ADDR_REG, g_Reg->PI_WR_LEN_REG,CRecompiler::Remove_DMA); } g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; g_Reg->MI_INTR_REG |= MI_INTR_PI; g_Reg->CheckInterrupts(); //ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9) + 50); //ChangeTimer(PiTimer,(int)(PI_WR_LEN_REG * 8.9)); return; } if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { g_Notify->DisplayError(L"PI_DMA_WRITE not in ROM"); } g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; g_Reg->MI_INTR_REG |= MI_INTR_PI; g_Reg->CheckInterrupts(); }
PBYTE uncompress_xp3_idx(HANDLE hFile, PDWORD idx_len, UNCOM unCom) { DWORD ByteRead; xp3_file_header header; SetFilePointer(hFile, 11, NULL, FILE_BEGIN); ReadFile(hFile, &header.offset_lo, 4, &ByteRead, NULL); ReadFile(hFile, &header.offset_hi, 4, &ByteRead, NULL); if (header.offset_lo != 0x17) SetFilePointer(hFile, header.offset_lo, (PLONG)&header.offset_hi, FILE_BEGIN); else { ReadFile(hFile, &header.minor_version, 4, &ByteRead, NULL); ReadFile(hFile, &header.flag, 1, &ByteRead, NULL); ReadFile(hFile, &header.index_size_lo, 4, &ByteRead, NULL); ReadFile(hFile, &header.index_size_hi, 4, &ByteRead, NULL); ReadFile(hFile, &header.index_offset_lo, 4, &ByteRead, NULL); ReadFile(hFile, &header.index_offset_hi, 4, &ByteRead, NULL); SetFilePointer(hFile, header.index_offset_lo, (PLONG)&header.index_offset_hi, FILE_BEGIN); } BYTE idx_flag; DWORD idx_size_lo; DWORD idx_size_hi; DWORD idx_uncom_lo; DWORD idx_uncom_hi; ReadFile(hFile, &idx_flag, 1, &ByteRead, NULL); ReadFile(hFile, &idx_size_lo, 4, &ByteRead, NULL); ReadFile(hFile, &idx_size_hi, 4, &ByteRead, NULL); if (idx_flag) { ReadFile(hFile, &idx_uncom_lo, 4, &ByteRead, NULL); ReadFile(hFile, &idx_uncom_hi, 4, &ByteRead, NULL); } else { idx_uncom_lo = idx_size_lo; idx_uncom_hi = idx_size_hi; } PBYTE idx = (u8*)VirtualAlloc(NULL, idx_size_lo, MEM_COMMIT, PAGE_READWRITE); PBYTE idx_raw = (u8*)VirtualAlloc(NULL, idx_uncom_lo, MEM_COMMIT, PAGE_READWRITE); if (!idx || !idx_raw) { AppendMsg(L"内存分配失败!"); return 0; } ReadFile(hFile, idx, idx_size_lo, &ByteRead, NULL); if (idx_flag) unCom((PBYTE)idx_raw, &idx_uncom_lo, (PBYTE)idx, idx_size_lo); else memcpy(idx_raw, idx, idx_size_lo); VirtualProtect(idx_raw, idx_uncom_lo, PAGE_READONLY, NULL); VirtualFree(idx, idx_size_lo, MEM_DECOMMIT); VirtualFree(idx, 0, MEM_RELEASE); *idx_len = idx_uncom_lo; return idx_raw; }
int patch_connect() { char str[2048]; HMODULE m = GetModuleHandle( "ws2_32.dll" ); if( !m ) { MessageBox( 0, "No Module handle for ws2_32.dll", "error", MB_OK ); return 0; } volatile FARPROC cptr = GetProcAddress( m, "connect" ); volatile unsigned char *data = (volatile unsigned char *)cptr; if( !cptr ) { MessageBox( 0, "no address for connect", "error", MB_OK ); return 0; } sprintf( str, "address of connect is 0x%08lx", (DWORD)data ); MessageBox( 0, str, "info", MB_OK ); DWORD oldProtect; if( !VirtualProtect( (void*)cptr, 4096, PAGE_EXECUTE_WRITECOPY, &oldProtect ) ) { if( !VirtualProtect( (void*)cptr, 4096, PAGE_EXECUTE_READWRITE, &oldProtect ) ) { MessageBox( 0, "VirtualProtect failed", "error", MB_OK ); return 0; } } hook_connect_reentry = ((DWORD)(data))+8; sprintf( str,"reentry=%08lx", hook_connect_reentry ); MessageBox(0,str,"INFO",MB_OK ); sprintf( str, "original: %02x %02x %02x %02x %02x %02x %02x %02x", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] ); MessageBox( 0, str, "info", MB_OK ); data[0] = 0xff; /* long jump, indirect */ data[1] = 0x25; DWORD *jmpaddr = (DWORD *)(data+2); *jmpaddr = (DWORD)&hook_connect_entry; sprintf( str, "new: %02x %02x %02x %02x %02x %02x %02x %02x", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7] ); MessageBox( 0, str, "info", MB_OK ); /* DWORD other; if( !VirtualProtect( cptr, 4096, oldProtect, &other ) ) { MessageBox( 0, "SecondVirtualProtect failed", "error", MB_OK ); return 0; } */ return 1; }
bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr ) { PIMAGE_THUNK_DATA pIAT; // Ptr to import address table PIMAGE_THUNK_DATA pINT; // Ptr to import names table PIMAGE_THUNK_DATA pIteratingIAT; // Figure out which OS platform we're on OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx( &osvi ); // If no import names table, we can't redirect this, so bail if ( pImportDesc->OriginalFirstThunk == 0 ) return false; pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk ); pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk ); // Count how many entries there are in this IAT. Array is 0 terminated pIteratingIAT = pIAT; unsigned cFuncs = 0; while ( pIteratingIAT->u1.Function ) { cFuncs++; pIteratingIAT++; } if ( cFuncs == 0 ) // If no imported functions, we're done! return false; // These next few lines ensure that we'll be able to modify the IAT, // which is often in a read-only section in the EXE. DWORD flOldProtect, flNewProtect, flDontCare; MEMORY_BASIC_INFORMATION mbi; // Get the current protection attributes VirtualQuery( pIAT, &mbi, sizeof(mbi) ); // remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag flNewProtect = mbi.Protect; flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ); flNewProtect |= (PAGE_READWRITE); if ( !VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flNewProtect, &flOldProtect) ) { return false; } // If the Default hook is enabled, build an array of redirection stubs in the processes memory. DLPD_IAT_STUB * pStubs = 0; if ( DLLHook->UseDefault ) { // Allocate memory for the redirection stubs. Make one extra stub at the // end to be a sentinel pStubs = new DLPD_IAT_STUB[ cFuncs + 1]; if ( !pStubs ) return false; } // Scan through the IAT, completing the stubs and redirecting the IAT // entries to point to the stubs pIteratingIAT = pIAT; while ( pIteratingIAT->u1.Function ) { void* HookFn = 0; // Set to either the SFunctionHook or pStubs. if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) ) // import by name { PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData ); // Iterate through the hook functions, searching for this import. SFunctionHook* FHook = DLLHook->Functions; while ( FHook->Name ) { if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 ) { OutputDebugString( "Hooked function: " ); OutputDebugString( (char*)pImportName->Name ); OutputDebugString( "\n" ); // Save the old function in the SFunctionHook structure and get the new one. FHook->OrigFn = (void*) pIteratingIAT->u1.Function; HookFn = FHook->HookFn; break; } FHook++; } // If the default function is enabled, store the name for the user. if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name; } else { // If the default function is enabled, store the ordinal for the user. if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = pINT->u1.Ordinal; } // If the default function is enabled, fill in the fields to the stub code. if ( DLLHook->UseDefault ) { pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn - (DWORD)(PDWORD)&pStubs->instr_JMP; pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count; // If it wasn't manually hooked, use the Stub function. if ( !HookFn ) HookFn = (void*)pStubs; } // Replace the IAT function pointer if we have a hook. if ( HookFn ) { // Cheez-o hack to see if what we're importing is code or data. // If it's code, we shouldn't be able to write to it if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) ) { pIteratingIAT->u1.Function = (DWORD_PTR)HookFn; } else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { // Special hack for Win9X, which builds stubs for imported // functions in system DLLs (Loaded above 2GB). These stubs are // writeable, so we have to explicitly check for this case if ( pIteratingIAT->u1.Function > (DWORD_PTR)0x80000000 ) pIteratingIAT->u1.Function = (DWORD_PTR)HookFn; } } if ( DLLHook->UseDefault ) pStubs++; // Advance to next stub pIteratingIAT++; // Advance to next IAT entry pINT++; // Advance to next INT entry } if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = 0; // Final stub is a sentinel // Put the page attributes back the way they were. VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare); return true; }
// This function "replaces" a function with another function // So, for example, if you do this: // OriginalWSASendProc = (MyWSASendProc) HookImportedFunction (GetModuleHandle (0), "WS2_32.DLL", "WSASend", (PROC) MyWSASend); // This will "replaces" WSASend() with MyWSASend(). Every time the app calls WSASend(), MyWSASend() gets called instead. // This function returns a pointer to the original function. PROC HookImportedFunction (HMODULE hModule, // Module to intercept calls from PSTR FunctionModule, // The dll file that contains the function you want to hook PSTR FunctionName, // The function that you want to hook PROC pfnNewProc) // New function, this gets called instead { #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue)) PROC pfnOriginalProc; IMAGE_DOS_HEADER *pDosHeader; IMAGE_NT_HEADERS *pNTHeader; IMAGE_IMPORT_DESCRIPTOR *pImportDesc; IMAGE_THUNK_DATA *pThunk; if (IsBadCodePtr (pfnNewProc)) return NULL; if (OriginalGetProcAddressProc) { pfnOriginalProc = OriginalGetProcAddressProc(GetModuleHandle(FunctionModule), FunctionName); } else { pfnOriginalProc = GetProcAddress(GetModuleHandle(FunctionModule), FunctionName); } if(!pfnOriginalProc) return NULL; pDosHeader = (PIMAGE_DOS_HEADER)hModule; if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ) return NULL; if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ) return NULL; pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ) return NULL; if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) return NULL; pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDosHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader ) return NULL; while ( pImportDesc->Name ) { PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name); if ( stricmp(pszModName, FunctionModule) == 0 ) break; pImportDesc++; } pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); if ( pImportDesc->Name == 0 ) return 0; pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk); MEMORY_BASIC_INFORMATION mbi_thunk; while ( pThunk->u1.Function ) { if ( (DWORD)pThunk->u1.Function == (DWORD)pfnOriginalProc) { VirtualQuery(pThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); if (FALSE == VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect)) return NULL; DWORD * pTemp = (DWORD*)&pThunk->u1.Function; *pTemp = (DWORD)(pfnNewProc); VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,mbi_thunk.Protect, NULL); break; } pThunk++; } SYSTEM_INFO si; DWORD i; byte *data = NULL; GetSystemInfo(&si); LPVOID lpMem = si.lpMinimumApplicationAddress; while (lpMem < si.lpMaximumApplicationAddress) { VirtualQuery(lpMem, &mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION)); if ((DWORD)mbi_thunk.BaseAddress <= (DWORD)pDosHeader + pNTHeader->OptionalHeader.SizeOfImage && mbi_thunk.State == MEM_COMMIT && mbi_thunk.RegionSize > 0 && !(mbi_thunk.Protect & PAGE_GUARD)) { if (VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect)) { data = (byte*)mbi_thunk.BaseAddress; for (i = 0; i < mbi_thunk.RegionSize - 3; i++) { if (*(DWORD*)(data+i) == (DWORD)pfnOriginalProc) { *(DWORD*)(data+i) = (DWORD)pfnNewProc; } } VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize,mbi_thunk.Protect, NULL); } } lpMem = MakePtr(LPVOID, mbi_thunk.BaseAddress, mbi_thunk.RegionSize+1); } return pfnOriginalProc; }
// address: 0x401000 void _start(unsigned int param1, __size32 param2) { unsigned char cl; // r9 __size32 eax; // r24 __size32 eax_1; // r24{27} int eax_2; // r24{245} int eax_3; // r24{162} __size32 ebp; // r29 unsigned int ebx; // r27 unsigned short *ebx_1; // r27 unsigned int ebx_10; // r27{261} union { unsigned int x11; unsigned short * x12; } ebx_11; // r27{335} __size32 ebx_12; // r27{300} union { unsigned int x11; unsigned short * x12; } ebx_13; // r27{323} union { unsigned int x11; unsigned short * x12; } ebx_14; // r27{292} union { unsigned int x11; void * x12; } ebx_15; // r27{347} unsigned int ebx_2; // r27{34} unsigned int ebx_3; // r27{44} unsigned int ebx_4; // r27{112} __size32 ebx_5; // r27{168} __size32 ebx_6; // r27{172} unsigned short *ebx_7; // r27{305} unsigned int ebx_8; // r27{239} unsigned int ebx_9; // r27{282} int ecx; // r25 __size32 *ecx_1; // r25 __size32 *ecx_2; // r25{259} __size32 edi; // r31 int edx; // r26 void *edx_1; // r26 __size32 esi; // r30 __size32 esi_1; // r30{12} __size32 *esi_10; // r30{221} __size32 *esi_11; // r30{219} __size32 *esi_12; // r30{214} __size32 esi_13; // r30{83} unsigned int esi_14; // r30{283} unsigned int esi_15; // r30{270} unsigned int esi_16; // r30{262} __size32 *esi_17; // r30{337} __size32 *esi_18; // r30{307} __size32 *esi_19; // r30{294} __size32 esi_2; // r30{72} __size32 *esi_20; // r30{349} __size32 esi_3; // r30{253} unsigned int esi_4; // r30{94} unsigned int esi_5; // r30{108} unsigned int esi_6; // r30{132} __size32 *esi_7; // r30{150} __size32 esi_8; // r30{177} __size32 *esi_9; // r30{180} int esp; // r28 int local1; // m[esp - 52] int local12; // m[esp - 48] __size32 *local2; // m[esp - 52] int local21; // m[esp - 52]{355} __size32 *local22; // m[esp - 52]{374} unsigned int local23; // m[esp - 84]{377} unsigned int local24; // ebx_8{239} __size32 local25; // esi_13{247} __size32 local26; // esi_3{253} unsigned int local27; // ebx_10{261} unsigned int local28; // esi_16{262} unsigned int local29; // esi_15{270} unsigned int local3; // m[esp - 84] unsigned int local30; // ebx_9{282} unsigned int local31; // esi_14{283} union { unsigned int x11; unsigned short * x12; } local32; // ebx_14{292} __size32 *local33; // esi_19{294} unsigned int local34; // param1{360} __size32 local35; // ebx_12{300} __size32 *local36; // esi_18{307} unsigned int local37; // local3{369} union { unsigned int x11; unsigned short * x12; } local38; // ebx_11{335} __size32 *local39; // esi_17{337} unsigned int local40; // local3{372} int local41; // eax_3{344} union { unsigned int x11; void * x12; } local42; // ebx_15{347} __size32 *local43; // esi_20{349} union { void * x13; int x14; } local5; // m[esp - 80] esi_1 = 0; eax_1 = AddAce(); local25 = esi_1; local34 = param1; ebx_2 = eax_1 + 37; eax = AreAllAccessesGranted(); local24 = ebx_2; if (eax == 0) { ebx_3 = eax_1 + 3; local24 = ebx_3; } ebx_8 = local24; CloseHandle(89); local27 = ebx_8; ecx = VirtualProtect(); /* Warning: also results in edx */ eax = 0; edi = param2; do { eax_2 = eax; esi_13 = local25; local26 = esi_13; if (esi_13 == ebx_8) { esi_2 = 0; local26 = esi_2; } esi_3 = local26; edi += edx * 9; cl = *(esi_3 + 0x404000); ecx = ecx >> 8 & 0xffffff | (cl); *(char*)(eax_2 + 0x401278) = *(eax_2 + 0x401278) ^ cl; eax = eax_2 + 1; esi_13 = esi_3 + 1; local25 = esi_13; } while (eax_2 + 1 < 0x1420); ecx_1 = 0x402558; esi_4 = ebx_8 + (esi_3 + 1) * 4; edi = 0xf0400ff8; local1 = 0; local28 = esi_4; do { ecx_2 = ecx_1; ebx_10 = local27; esi_16 = local28; local21 = local1; eax = *(ecx_2 + 4); edx_1 = ecx_2 + 8; local30 = ebx_10; local31 = esi_16; if ((int)((eax - 8) / 2) > 0) { esi_5 = (eax - 8) / 2; local29 = esi_5; do { esi_15 = local29; eax = *(unsigned short*)edx_1; ebx_4 = eax & 0xf000; local30 = ebx_4; if ((eax & 0xf000) == 0x3000) { eax = (eax & 0xfff) + *ecx_2; *(__size32*)(eax + 0x400ff8) = *(eax + 0x400ff8) - 0xfbff008; } edx_1++; esi_6 = esi_15 - 1; local29 = esi_6; local31 = esi_6; } while (esi_15 != 1); } ebx_9 = local30; esi_14 = local31; eax = *(ecx_2 + 4); ecx_1 = ecx_2 + eax; cl = (unsigned char) ecx_2 + eax; local1 = local21 + eax; local27 = ebx_9; local28 = esi_14; local32 = ebx_9; local41 = eax; local42 = ebx_9; } while ((unsigned int)(local21 + eax) < 228); flags = SUBFLAGS32(*0x401d64, 0, global11); esi_7 = 0x401d54; local2 = 0x401d54; local33 = esi_7; local43 = esi_7; if (*0x401d64 != 0) { do { ebx_14 = local32; esi_19 = local33; param1 = local34; edx = *(esi_19 + 12); eax_3 = LoadLibraryA(edx + 0x400ff8); /* Warning: also results in ecx_1 */ local37 = param1; local38 = ebx_14; local39 = esi_19; local40 = param1; edi = eax_3; if (eax_3 != 0) { ebx_5 = *esi_19; local35 = ebx_5; if (ebx_5 == 0) { ebx_6 = *(esi_19 + 16); local35 = ebx_6; } ebx_12 = local35; ebx_1 = ebx_12 + 0x400ff8; esi_8 = *(esi_19 + 16); eax = *(ebx_12 + 0x400ff8); esi_9 = esi_8 + 0x400ff8; flags = LOGICALFLAGS32(eax); local36 = esi_9; if (eax != 0) { do { ebx_7 = ebx_1; esi_18 = local36; if (flags) { cl = (unsigned char) eax + 0x400ffa; eax = GetProcAddress(edi, eax + 0x400ffa); /* Warning: also results in ecx_1 */ } else { eax = *(unsigned short*)ebx_7; eax = GetProcAddress(edi, eax); /* Warning: also results in ecx_1 */ edi = eax_3; } ebx_1 = ebx_7 + 4; *(__size32*)esi_18 = eax; eax = *(ebx_7 + 4); esi_12 = esi_18 + 4; flags = LOGICALFLAGS32(eax); local36 = esi_12; local37 = local3; } while (eax != 0); } eax_3 = eax; ebx_13 = ebx_1; local3 = local37; esi_11 = local2; local38 = ebx_13; local39 = esi_11; local40 = local3; } ebx_11 = local38; esi_17 = local39; local3 = local40; esi_10 = esi_17 + 20; tmp1 = *(esi_17 + 36); flags = SUBFLAGS32(*(esi_17 + 36), 0, tmp1); local2 = esi_17 + 20; local32 = ebx_11; local33 = esi_10; local34 = local3; local41 = eax_3; local42 = ebx_11; local43 = esi_10; } while (*(esi_17 + 36) != 0); } eax_3 = local41; ebx_15 = local42; esi_20 = local43; (*0x401a48)(local23, local5, pc, 0x401000, 0x3000, 64, esp - 40, -1, local22, local12, 0, 0, 0, 0, param2, esi, ebp, ebx, cl, eax_3, ecx_1, 0x401a48, ebx_15, 0x400ff8, esi_20, edi, flags, ZF, CF); *(__size32*)(esp - 4) = 0; ExitProcess(*(esp - 4)); return; }