void PLH::VEHHook::UnHook() { std::lock_guard<std::mutex> m_Lock(m_TargetMutex); if (m_ThisCtx.m_Type == VEHMethod::INT3_BP) { MemoryProtect Protector(m_ThisCtx.m_Src, 1, PAGE_EXECUTE_READWRITE); *m_ThisCtx.m_Src = m_ThisCtx.m_StorageByte; }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; } Ctx.Dr7 &= ~(1 << (2 * m_ThisCtx.m_StorageByte)); //Still need to call suspend thread if (!SetThreadContext(GetCurrentThread(), &Ctx)) { PostError(PLH::RuntimeError(RuntimeError::Severity::Critical, "Failed to set context")); return; } }else if (m_ThisCtx.m_Type == VEHMethod::GUARD_PAGE) { volatile BYTE GenerateExceptionRead = *m_ThisCtx.m_Src; } m_HookTargets.erase(std::remove(m_HookTargets.begin(), m_HookTargets.end(), m_ThisCtx), m_HookTargets.end()); }
bool PLH::VFuncSwap::Hook() { MemoryProtect Protector(&m_hkVtable[m_hkIndex], sizeof(void*), PAGE_READWRITE); m_OrigVFunc = m_hkVtable[m_hkIndex]; m_hkVtable[m_hkIndex] = m_hkDest; return true; }
void PLH::IATHook::UnHook() { PIMAGE_THUNK_DATA Thunk; if (!FindIATFunc(m_hkLibraryName.c_str(), m_hkSrcFunc.c_str(), &Thunk)) return; MemoryProtect Protector(Thunk, sizeof(ULONG_PTR), PAGE_EXECUTE_READWRITE); Thunk->u1.Function = (ULONG_PTR)m_pIATFuncOrig; }
TChart::TChart(CString name): TAbstractGraphics(name) { repaint=REPAINT_NONE; SeriesDataWnd=NULL; void *x; if((x=Series.GainAcsess(WRITE))!=0) { SeriesProtector Protector(x); TSeriesArray& series(Protector); series.Parent=this; } LastSeriesUpdateID=Series.GetModificationID(); LastSeriesRenderUpdateID=0; LeftAxis=BottomAxis=NULL; Frame=NULL; }
bool PLH::X86Detour::Hook() { DWORD OldProtection; m_hkLength = CalculateLength(m_hkSrc, 5); m_OriginalLength = m_hkLength; if (m_hkLength == 0) { XTrace("Function to small to hook\n"); return false; } m_Trampoline = new BYTE[m_hkLength + 30]; //Allocate Space for original plus extra to jump back and for jmp table VirtualProtect(m_Trampoline, m_hkLength + 5, PAGE_EXECUTE_READWRITE, &OldProtection); //Allow Execution m_NeedFree = true; memcpy(m_OriginalCode, m_hkSrc, m_hkLength); memcpy(m_Trampoline, m_hkSrc, m_hkLength); //Copy original into allocated space RelocateASM(m_Trampoline, m_hkLength, (DWORD)m_hkSrc, (DWORD)m_Trampoline); WriteRelativeJMP((DWORD)&m_Trampoline[m_hkLength], (DWORD)m_hkSrc + m_hkLength); //JMP back to original code //Change protection to allow write on original function MemoryProtect Protector(m_hkSrc, m_hkLength, PAGE_EXECUTE_READWRITE); //Encode Jump from Hooked Function to the Destination function WriteRelativeJMP((DWORD)m_hkSrc, (DWORD)m_hkDest); //Write nops over bytes of overwritten instructions for (int i = 5; i < m_OriginalLength; i++) m_hkSrc[i] = 0x90; FlushSrcInsCache(); //Revert to old protection on original function VirtualProtect(m_hkSrc, m_hkLength, OldProtection, &OldProtection); PostError(RuntimeError(RuntimeError::Severity::Warning, "PolyHook x86Detour: Some opcodes may not be relocated properly")); return true; /*Original -JMP Destination -NOP (extends to length of overwritten opcode) -Rest of function Destination -Do your shit -Return Trampoline (goes to trampoline) Trampoline -Execute Overwritten Opcodes -Patch original relative jmps to point to jump table (JE Jumptable entry 1) -JMP to rest of function (in original) -*BEGIN JUMPTABLE* -1)JMP to location of relative jmp one -2)...continue pattern for all relative jmps */ }
bool PLH::VTableSwap::Hook() { MemoryProtect Protector(m_phkClass, sizeof(void*), PAGE_READWRITE); m_OrigVtable = *m_phkClass; m_hkOriginal = m_OrigVtable[m_hkIndex]; m_VFuncCount = GetVFuncCount(m_OrigVtable); m_NewVtable = (BYTE**) new DWORD_PTR[m_VFuncCount]; m_NeedFree = true; memcpy(m_NewVtable, m_OrigVtable, sizeof(void*)*m_VFuncCount); *m_phkClass = m_NewVtable; m_NewVtable[m_hkIndex] = m_hkDest; return true; }
void PLH::VEHHook::UnHook() { std::lock_guard<std::mutex> m_Lock(m_TargetMutex); if (m_ThisCtx.m_Type == VEHMethod::INT3_BP) { MemoryProtect Protector(m_ThisCtx.m_Src, 1, PAGE_EXECUTE_READWRITE); *m_ThisCtx.m_Src = m_ThisCtx.m_OriginalByte; }else if (m_ThisCtx.m_Type == VEHMethod::GUARD_PAGE) { volatile BYTE GenerateExceptionRead = *m_ThisCtx.m_Src; } m_HookTargets.erase(std::remove(m_HookTargets.begin(), m_HookTargets.end(), m_ThisCtx), m_HookTargets.end()); }
/*----------------------------------------------*/ bool PLH::IATHook::Hook() { PIMAGE_THUNK_DATA Thunk; if (!FindIATFunc(m_hkLibraryName.c_str(), m_hkSrcFunc.c_str(), &Thunk, m_hkModuleName.c_str())) { PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook IATHook: Failed to find import")); return false; } MemoryProtect Protector(Thunk, sizeof(ULONG_PTR), PAGE_EXECUTE_READWRITE); m_pIATFuncOrig = (void*)Thunk->u1.Function; Thunk->u1.Function = (ULONG_PTR)m_hkDest; return true; }
LONG CALLBACK PLH::VEHHook::VEHHandler(EXCEPTION_POINTERS* ExceptionInfo) { #ifdef _WIN64 #define XIP Rip #else #define XIP Eip #endif // _WIN64 std::lock_guard<std::mutex> m_Lock(m_TargetMutex); DWORD ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode; if (ExceptionCode == EXCEPTION_BREAKPOINT) { for (HookCtx& Ctx : m_HookTargets) { if(Ctx.m_Type != VEHMethod::INT3_BP) continue; //Are we at a breakpoint that we placed? if (ExceptionInfo->ContextRecord->XIP != (DWORD_PTR)Ctx.m_Src) continue; //Remove Int3 Breakpoint MemoryProtect Protector(Ctx.m_Src, 1, PAGE_EXECUTE_READWRITE); *Ctx.m_Src = Ctx.m_OriginalByte; //Set instruction pointer to our callback ExceptionInfo->ContextRecord->XIP = (DWORD_PTR) Ctx.m_Dest; return EXCEPTION_CONTINUE_EXECUTION; } }else if (ExceptionCode == EXCEPTION_GUARD_PAGE) { for (HookCtx& Ctx : m_HookTargets) { //still need to check if exception is in our page if (Ctx.m_Type != VEHMethod::GUARD_PAGE) continue; if(!AreInSamePage((BYTE*)ExceptionInfo->ContextRecord->XIP,Ctx.m_Src)) continue; if (ExceptionInfo->ContextRecord->XIP == (DWORD_PTR)Ctx.m_Src) ExceptionInfo->ContextRecord->XIP = (DWORD_PTR)Ctx.m_Dest; return EXCEPTION_CONTINUE_EXECUTION; } } return EXCEPTION_CONTINUE_SEARCH; }
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_OriginalByte = *m_ThisCtx.m_Src; *m_ThisCtx.m_Src = 0xCC; 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; }
void SeriesListCtrl::ChangeStatus(int t) { POSITION pos=GetFirstSelectedItemPosition(); void *x; if(pos) { if((x=Series->GainAcsess(READ_EX))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); while(pos) { int n=GetItemData(GetNextSelectedItem(pos)); TChartSeries *series=Series[n]; series->SetStatus(t); } } UpdateSeriesList(); } }
LRESULT TChart::OnSeriesDataImport( WPARAM wParam, LPARAM lParam ) { MessagesInspectorSubject* msg=(MessagesInspectorSubject*)lParam; void *x; BYTE t=0; if(msg) { if((x=Series.GainAcsess(WRITE))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); for(int i=0;i<Series.GetSize();i++) { if(Series[i]->ImportData(msg,DO_NOT_DELETE_MSG)!=0) t++; } } delete msg; if(t) UpdateNow(REPAINT_DEFAULT); } return 0; }
void SeriesListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { ProtectedSeriesArray& Series=*(SeriesListCtrl::Series); void *x; HitItem=HitTest(point); if (HitItem>=0) { CRect rect; GetItemRect(HitItem, rect, LVIR_ICON); if (point.x < rect.left) { BYTE state=GetState(HitItem); state++; if(state>2) state=1; SetState(HitItem,state); if((x=Series.GainAcsess(WRITE))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); Series[GetItemData(HitItem)]->SetVisible(state-1); } } } CListCtrl::OnLButtonDown(nFlags, point); }
void TChart::FindMinMax() { int i,n=-1; void *x; if(SeriesIsChanged()) { if((x=Series.GainAcsess(READ))!=0) { SeriesProtector Protector(x); TSeriesArray& series(Protector); MinMax=PointsRgn(); for(i=0;i<series.GetSize() && n<0;i++) { if(series[i]->FindMinMax()) n=i; } if(n>=0) MinMax=series[n]->MinMax; for(;i<series.GetSize();i++) { if(series[i]->FindMinMax()) MinMax+=series[i]->MinMax; } } if(LeftAxis!=NULL) LeftAxis->SetMinMax(MinMax.minY,MinMax.maxY); if(BottomAxis!=NULL) BottomAxis->SetMinMax(MinMax.minX,MinMax.maxX); } }
void SeriesListCtrl::OnSaveAsText() { BYTE cr[3]; cr[0]=0xd;cr[1]=0xa;cr[2]=0; int i,j, match, err=0, num; POSITION pos=GetFirstSelectedItemPosition(); CArray<int,const int&> arr; CString temp; CString T,T1; while(pos) arr.Add(GetItemData(GetNextSelectedItem(pos))); for(i=0;i<arr.GetSize() && !err;i++) { match=0; for(j=i+1;j<arr.GetSize();j++) { T=Items[arr[j]].Name; T1=Items[arr[i]].Name; if(!(strcmp(Items[arr[j]].Name,Items[arr[i]].Name))) match++; } if(match>0) err=1; } if(!(arr.GetSize()) || err) { AfxMessageBox("¬Ќ»ћјЌ»≈!!! ќдин или более Series имеют одинаковые имена. ¬ыполнение операции невозможно!"); return; } else { CString temp; CFile f; err=0; num=0; void *x; if((x=Series->GainAcsess(READ))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); for(i=0;i<arr.GetSize();i++) { TChartSeries *series=Series[arr[i]]; temp=GetSaveAsPath(); int t; if((t=temp.ReverseFind('\\'))>=0) temp=temp.Left(++t); temp+=series->Name+".xls"; HANDLE SearchHandle; WIN32_FIND_DATA FindFileData; TCHAR szError[1024]; if( (SearchHandle=FindFirstFile(LPCSTR(temp),&FindFileData) )==INVALID_HANDLE_VALUE) { CFileException ex; if(f.Open(temp,CFile::modeCreate | CFile::modeWrite,&ex)) { temp.Format("%s: points=%d",series->Name,series->GetSize()); for(int i=0;i<series->GetSize();i++) { series->FormatElement(i,temp); char* fs; while((fs=const_cast<char*>(strchr(temp,'.')))!=NULL) (*fs)=','; f.Write(LPCSTR(temp),temp.GetLength()); f.Write(cr,sizeof(cr)); } f.Close(); num++; } else { ex.GetErrorMessage(szError, 1024); } } else err++; } } if(err) { temp.Format("¬Ќ»ћјЌ»≈!!! %d из %d файлов не были созданы. ‘айлы с такими именами уже существуют.",err, num+err); AfxMessageBox(temp); } else { temp.Format("ќпераци¤ прошла успешно. —оздано %d файлов", num); AfxMessageBox(temp); } } }
void ImageWndCtrlsTab::OnBnClickedScan() { UpdateData(); ImageWnd* parent=(ImageWnd*)Parent; parent->strips.ScanLine.curL.x=Xmin/parent->scale; parent->strips.ScanLine.curR.x=Xmax/parent->scale; parent->strips.ScanLine.curL.y=parent->strips.ScanLine.curR.y=stroka/parent->scale; parent->DrawScanLine(parent->strips.ScanLine.curL,parent->strips.ScanLine.curR); CMainFrame* MainWnd=(CMainFrame*)AfxGetMainWnd(); MainWnd->TabCtrl1.ChangeTab(MainWnd->TabCtrl1.FindTab("Main control")); void* x; CString T,T1; BYTE *dark,*cupol,*strips; TPointVsErrorSeries *t2; //TSimplePointSeries *t1; int midl=stroka, dd=AvrRange,w=parent->strips.org.w, Ymin=midl-dd, Ymax=midl+dd, mm=(Ymax-Ymin)/2; MyTimer Timer1,Timer2; sec time; CString logT; TPointVsErrorSeries::DataImportMsg *CHM2, *AdarkChartMsg, *AcupolChartMsg, *AstripsChartMsg, *ChartMsg; TSimplePointSeries::DataImportMsg *CHM1, *darkChartMsg,*cupolChartMsg, *stripsChartMsg; CHM2=AdarkChartMsg=AcupolChartMsg=AstripsChartMsg=ChartMsg=NULL; CHM1=darkChartMsg=cupolChartMsg=stripsChartMsg=NULL; LogMessage *log=new LogMessage(); log->CreateEntry("Log","Speed tests results",LogMessage::low_pr); if(!(parent->dark.org.HasImage() && parent->cupol.org.HasImage() && parent->strips.org.HasImage())) return; if(Xmin<0) Xmin=0; if(Xmin>=parent->strips.org.w) Xmin=parent->strips.org.w; if(Xmax<0) Xmax=0; if(Xmax>=parent->strips.org.w) Xmax=parent->strips.org.w; if(Xmax<Xmin) {int t=Xmax; Xmax=Xmin; Xmin=t;} Timer2.Start(); T.Format("%d",midl); T1.Format("%davrg",midl); for(int i=0;i<3;i++) { CHM2 =new TPointVsErrorSeries::DataImportMsg(); switch(i) { case 0: AdarkChartMsg=CHM2; break; case 1: AcupolChartMsg=CHM2; break; case 2: AstripsChartMsg=CHM2; break; } } CMainFrame* mf=(CMainFrame*)AfxGetMainWnd(); TChart& chrt=mf->Chart1; if((x=chrt.Series.GainAcsess(WRITE))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); if((t2=new TPointVsErrorSeries(T))!=0) { for(int i=0;i<Series.GetSize();i++) Series[i]->SetStatus(SER_INACTIVE); Series.Add(t2); t2->_SymbolStyle::Set(NO_SYMBOL); ChartMsg=t2->CreateDataImportMsg(); t2->AssignColors(ColorsStyle(clRED,Series.GetRandomColor())); t2->PointType.Set(GenericPnt); t2->SetStatus(SER_ACTIVE); t2->SetVisible(true); } } Timer1.Start(); parent->dark.org.LoadBitmapArray(Ymin,Ymax); parent->cupol.org.LoadBitmapArray(Ymin,Ymax); parent->strips.org.LoadBitmapArray(Ymin,Ymax); Timer1.Stop(); time=Timer1.GetValue(); logT.Format("D C S %d lines load = %s",2*dd+1,ConvTimeToStr(time)); log->Msgs.Add(logT); dark=parent->dark.org.arr; cupol=parent->cupol.org.arr; strips=parent->strips.org.arr; SimplePoint pnt; pnt.type.Set(GenericPnt); ValuesAccumulator pnteD,pnteC,pnteS; PointVsError pnte; pnteD.type.Set(AveragePnt); pnteC.type.Set(AveragePnt); pnteS.type.Set(AveragePnt); Timer1.Start(); for(int i = Xmin; i < Xmax; i++) { pnteD.Clear();pnteC.Clear();pnteS.Clear(); for(int j = 1; j <= dd; j++) { pnteD << dark[i+(mm+j)*w] << dark[i+(mm-j)*w]; pnteC << cupol[i+(mm+j)*w] << cupol[i+(mm-j)*w]; pnteS << strips[i+(mm+j)*w] << strips[i+(mm-j)*w]; } pnt.x=i; pnt.y=dark[i+mm*w]; pnteD << pnt.y; pnt.y=cupol[i+mm*w]; pnteC << pnt.y; pnt.y=strips[i+mm*w]; pnteS << pnt.y; pnte=pnteD; pnte.x=i; AdarkChartMsg->Points.Add(pnte); pnte=pnteC; pnte.x=i; AcupolChartMsg->Points.Add(pnte); pnte=pnteS; pnte.x=i; AstripsChartMsg->Points.Add(pnte); } Timer1.Stop(); time=Timer1.GetValue(); logT.Format("D C S %d lines averaging time=%s",2*dd+1,ConvTimeToStr(time)); log->Msgs.Add(logT); Timer1.Start(); for(int i=0;i<AdarkChartMsg->Points.GetSize();i++) { pnte=(AstripsChartMsg->Points[i]-AdarkChartMsg->Points[i])/(AcupolChartMsg->Points[i]-AdarkChartMsg->Points[i]); pnte.type.Set(GenericPnt); ChartMsg->Points.Add(pnte); } Timer1.Stop(); time=Timer1.GetValue(); logT.Format("Normalizing %d point time=%s",AdarkChartMsg->Points.GetSize(),ConvTimeToStr(time)); log->Msgs.Add(logT); parent->dark.org.UnloadBitmapArray(); parent->cupol.org.UnloadBitmapArray(); parent->strips.org.UnloadBitmapArray(); delete AdarkChartMsg; delete AcupolChartMsg; delete AstripsChartMsg; ChartMsg->Dispatch(); Timer2.Stop(); time=Timer2.GetValue(); logT.Format("Total processing time=%s",ConvTimeToStr(time)); log->Msgs.Add(logT); CKSVU3App* Parent=(CKSVU3App*)AfxGetApp(); Parent->myThread.PostParentMessage(UM_GENERIC_MESSAGE,log); }
void PLH::VTableSwap::UnHook() { MemoryProtect Protector(m_phkClass, sizeof(void*), PAGE_READWRITE); *m_phkClass = m_OrigVtable; FreeNewVtable(); }
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; }
void PLH::VFuncSwap::UnHook() { MemoryProtect Protector(&m_hkVtable[m_hkIndex], sizeof(void*), PAGE_READWRITE); m_hkVtable[m_hkIndex] = m_OrigVFunc; }
bool PLH::X64Detour::Hook() { //Allocate Memory as close as possible to src, to minimize chance 32bit displacements will be out of range (for relative jmp type) MEMORY_BASIC_INFORMATION mbi; for (size_t Addr = (size_t)m_hkSrc; Addr > (size_t)m_hkSrc - 0x80000000; Addr = (size_t)mbi.BaseAddress - 1) { if (!VirtualQuery((LPCVOID)Addr, &mbi, sizeof(mbi))) break; if (mbi.State != MEM_FREE) continue; if (m_Trampoline = (BYTE*)VirtualAlloc(mbi.BaseAddress, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) break; } if (!m_Trampoline) return false; m_NeedFree = true; //Decide which jmp type to use based on function size bool UseRelativeJmp = false; m_hkLength = CalculateLength(m_hkSrc, 16); //More stable 16 byte jmp m_OriginalLength = m_hkLength; //We modify hkLength in Relocation routine if (m_hkLength == 0) { UseRelativeJmp = true; m_hkLength = CalculateLength(m_hkSrc, 6); //Smaller, less safe 6 byte (jmp could be out of bounds) if (m_hkLength == 0) { PostError(RuntimeError(RuntimeError::Severity::UnRecoverable, "PolyHook x64Detour: Function to small to hook")); return false; } } memcpy(m_OriginalCode, m_hkSrc, m_hkLength); memcpy(m_Trampoline, m_hkSrc, m_hkLength); RelocateASM(m_Trampoline,m_hkLength, (DWORD64)m_hkSrc, (DWORD64)m_Trampoline); //Write the jmp from our trampoline back to the original WriteAbsoluteJMP((DWORD64)&m_Trampoline[m_hkLength], (DWORD64)m_hkSrc + m_hkLength); // Build a far jump to the Destination function. (jmps not to address pointed at but to the value in the address) MemoryProtect Protector(m_hkSrc, m_hkLength, PAGE_EXECUTE_READWRITE); int HookSize = 0; if (UseRelativeJmp) { HookSize = 6; m_hkSrc[0] = 0xFF; m_hkSrc[1] = 0x25; //Write 32Bit Displacement from rip *(long*)(m_hkSrc + 2) = CalculateRelativeDisplacement<long>((DWORD64)m_hkSrc, (DWORD64)&m_Trampoline[m_hkLength + 16], 6); *(DWORD64*)&m_Trampoline[m_hkLength + 16] = (DWORD64)m_hkDest; //Write the address into memory at [RIP+Displacement] }else { HookSize = 16; WriteAbsoluteJMP((DWORD64)m_hkSrc, (DWORD64)m_hkDest); } //Nop Extra bytes from overwritten opcode for (int i = HookSize; i < m_OriginalLength; i++) m_hkSrc[i] = 0x90; FlushInstructionCache(GetCurrentProcess(), m_hkSrc, m_hkLength); PostError(RuntimeError(RuntimeError::Severity::Warning, "PolyHook x64Detour: Relocation can be out of range")); return true; }
void SeriesListCtrl::UpdateSeriesList() { int n=HitItem; LV_ITEM lvi; CString T; void *x; CBitmap * tmpbmp; BMPanvas icon; if (Series == NULL) return; if((x=Series->GainAcsess(READ))!=0) { SeriesProtector Protector(x); TSeriesArray& Series(Protector); int n1=Series.GetSize(); if(n>=n1) n=n-1; // if(LastN!=n1) { DeleteAllItems(); Items.RemoveAll(); ImageList1.Detach(); ImageList1.Create(16,16,ILC_COLOR,Series.GetSize(),1); for(int i=0;i<Series.GetSize();i++) { icon.Create(CreateCompatibleDC(NULL),16,16,24); HGDIOBJ brsh=icon.SelectObject(bckg); icon.PatBlt(PATCOPY); icon.SelectObject(brsh); Series[i]->UpdateIcon(icon); HBITMAP hbmp=icon.GetHBMP(BMP_DETACH); tmpbmp=CBitmap::FromHandle(hbmp); ImageList1.Add(tmpbmp,(CBitmap*)NULL); lvi.mask = LVIF_PARAM; lvi.iItem = i;lvi.iSubItem = 0; lvi.lParam=i; InsertItem(&lvi); Items.Add(ListItemData()); } SetImageList(&ImageList1,LVSIL_SMALL); } for(int i=0;i<GetItemCount();i++) { int k=GetItemData(i); TChartSeries* series=Series[k]; lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = (char*)LPCTSTR(series->Name); lvi.iImage = i; lvi.stateMask = LVIS_STATEIMAGEMASK; lvi.state = INDEXTOSTATEIMAGEMASK(series->IsVisible()+1); SetItem(&lvi); lvi.mask = LVIF_TEXT; lvi.iSubItem++; T.Format("%d",series->GetSize()); SetItemText(i,lvi.iSubItem++,(char*)LPCTSTR(T)); series->GetStatus(T); SetItemText(i,lvi.iSubItem++,(char*)LPCTSTR(T)); T.Format("%d",series->GetPID()); SetItemText(i,lvi.iSubItem++,(char*)LPCTSTR(T)); lvi.mask=LVIF_STATE; lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED; lvi.state = 0; SetItemState(i,&lvi); Items[k].Name=series->Name; Items[k].Size=series->GetSize(); Items[k].Status=series->GetStatus(); Items[k].PID=series->GetPID(); } LastN=Series.GetSize(); if(n>=0) { _ms_lvi.mask=LVIF_STATE; _ms_lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED; _ms_lvi.state = LVIS_SELECTED | LVIS_FOCUSED; LV_ITEM FAR * temp=&_ms_lvi; this->PostMessage(LVM_SETITEMSTATE ,(WPARAM)(n), (LPARAM)(temp)); EnsureVisible(n, false); } //SortItems(CompareFunc1,(LPARAM) (this)); } }