-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample.cpp
142 lines (111 loc) · 5.19 KB
/
example.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "detours.h" // download from http://research.microsoft.com/sn/detours/
LONG WINAPI UnhandlerExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo); // Our exception filter
DWORD WINAPI GetTickCount_Detour(void); // Our detoured GetTickCount()
BOOL WINAPI GetThreadContext_Detour (HANDLE hThread,LPCONTEXT lpContext); // Our detoured GetThreadContext()
DETOUR_TRAMPOLINE(BOOL WINAPI GetThreadContext_Trampoline(HANDLE ,LPCONTEXT) ,GetThreadContext); // detour macro for (empty)trampoline
// Function defines
void Set_SEH_and_BreakPoints(void); // Set the SEH and breakpoints
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler=NULL; // Pointer to existing exception handler
// Global variables
DWORD dwBreakPoint=0x100334f; // The hardware-breakpoint (4 available)
int nBreakPointJump=0x18; // How many bytes we make EIP to skip from this breakpoint
BYTE opcodes[5]; // Original opcodes in GetTickCount() entry-point to be stored for restoring
// DLL entrypoint which OS-loader calls for us after injecting
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(GetModuleHandle(NULL));
MessageBox(NULL,"We are in and hooked !","SEH_example",0);
// Store original opcodes under GetTickCount()
ReadProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);
// Hijack GetTickCount to jmp to our GetTickCount_Detour
DetourFunction((PBYTE)GetTickCount,(PBYTE)GetTickCount_Detour);
// Hijack also GetThreadContext() to hide debug-registers altering
DetourFunctionWithTrampoline((PBYTE)GetThreadContext_Trampoline,(PBYTE)GetThreadContext_Detour);
break;
case DLL_PROCESS_DETACH:
// Try to remove all hooks and handlers.
DetourRemove((PBYTE) GetThreadContext_Trampoline,(PBYTE) GetThreadContext_Detour);
WriteProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);
if (oldHandler) SetUnhandledExceptionFilter(oldHandler);
break;
}
return true;
}
// Hijacked GetTickCount. This is called when target-app (Notepad) is calling GetTickCount()
DWORD WINAPI GetTickCount_Detour()
{
// From here we add our Structured Exception Handler
// We can't add it in the DLLmain since that function is called in
// different thread-context and the SEH and Breakpoints are per thread basis
Set_SEH_and_BreakPoints();
// Return original bytes to GetTickCount() i.e. unhook it. We only need this "callback" once.
WriteProcessMemory(GetCurrentProcess(),(LPVOID)GetProcAddress(GetModuleHandle("Kernel32"),"GetTickCount"),&opcodes,5,0);
MessageBox(NULL,"HW-breakpoints are set !","SEH_example",0);
// Return actual function result
return GetTickCount();
}
// Add the SEH-handler and set HW-breakpoint(s)
void Set_SEH_and_BreakPoints()
{
// Store existing handler to global variable to reset later
oldHandler=SetUnhandledExceptionFilter(UnhandlerExceptionFilter);
// Set debug-registers for HW-breakpoint and activate it
CONTEXT ctx = {CONTEXT_DEBUG_REGISTERS};
ctx.Dr6 = 0x00000000;
ctx.Dr0 = dwBreakPoint; // Set Address of Breakpoint 1
ctx.Dr7 = 0x00000001; // Activate Breakpoint 1
/*
use these for setting more breakpoints
ctx.Dr1=address; // Set Address of Breakpoint 2
ctx.Dr7 |= 0x00000004; // Activate Breakpoint 2
ctx.Dr2=address; // Set Address of Breakpoint 3
ctx.Dr7 |= 0x00000010; // Activate Breakpoint 3
ctx.Dr3=address; // Set Address of Breakpoint 4
ctx.Dr7 |= 0x00000040; // Activate Breakpoint 4
*/
// Write the values to registers. From now on the breakpoint is active
SetThreadContext(GetCurrentThread(), &ctx);
}
// Our ExceptionHandler
// study the ExceptionInfo-struct for stuff you need
LONG WINAPI UnhandlerExceptionFilter(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
// HW-breakpoints DON'T generate EXCEPTION_BREAKPOINT but EXCEPTION_SINGLE_STEP so we check for that
if(ExceptionInfo->ExceptionRecord->ExceptionCode==EXCEPTION_SINGLE_STEP )
{
// Verify that the breakpoint was the one we set
if ((DWORD)ExceptionInfo->ExceptionRecord->ExceptionAddress==dwBreakPoint)
{
// move instruction pointer forward to skip unwanted instructions and let
// the process continue as nothing has happened
ExceptionInfo->ContextRecord->Eip+=nBreakPointJump;
return EXCEPTION_CONTINUE_EXECUTION;
}
}
// Some other exception occured. Pass it to next handler
return EXCEPTION_CONTINUE_SEARCH;
}
// Hijacked GetThreadContext(). We don't actually need this in our notepad-example
// I included it just for help since for a real hack you need to fake
// DEBUG-registers so that the game doesn't see they that are altered
//
BOOL WINAPI GetThreadContext_Detour (HANDLE hThread,LPCONTEXT lpContext)
{
// Get the Real values from original API-function (see the _trampoline)
BOOL ret=GetThreadContext_Trampoline( hThread, lpContext);
// If target is interested in Debug-registers return fake values
if (lpContext->ContextFlags && CONTEXT_DEBUG_REGISTERS) {
lpContext->Dr0=0;
lpContext->Dr1=0;
lpContext->Dr2=0;
lpContext->Dr3=0;
lpContext->Dr6=0;
lpContext->Dr7=0;
}
return ret;
}