├── .gitignore
├── Detours
├── Detours.vcxproj
├── Detours.vcxproj.filters
└── src
│ ├── DetoursNotify.cpp
│ ├── DetoursNotify.h
│ ├── Makefile
│ ├── creatwth.cpp
│ ├── detours.cpp
│ ├── detours.h
│ ├── detours_patch.cpp
│ ├── detver.h
│ ├── disasm.cpp
│ ├── disolarm.cpp
│ ├── disolarm64.cpp
│ ├── disolia64.cpp
│ ├── disolx64.cpp
│ ├── disolx86.cpp
│ ├── image.cpp
│ ├── mem_patch.cpp
│ ├── mem_patch.h
│ ├── modules.cpp
│ ├── uimports.cpp
│ └── windows_shim.h
├── DetoursTest.sln
├── DetoursTest
├── DetoursTest.cpp
├── DetoursTest.vcxproj
└── DetoursTest.vcxproj.filters
├── LICENSE
├── README.md
└── config.props
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 | *.user
10 |
11 | # Precompiled Headers
12 | *.gch
13 | *.pch
14 |
15 | # Compiled Dynamic libraries
16 | *.so
17 | *.dylib
18 | *.dll
19 |
20 | # Fortran module files
21 | *.mod
22 | *.smod
23 |
24 | # Compiled Static libraries
25 | *.lai
26 | *.la
27 | *.a
28 | *.lib
29 |
30 | # Executables
31 | *.exe
32 | *.out
33 | *.app
34 |
35 | #Exception dir
36 | .vs
37 | .git
--------------------------------------------------------------------------------
/Detours/Detours.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | ARM
7 |
8 |
9 | Debug
10 | ARM64
11 |
12 |
13 | Debug
14 | Win32
15 |
16 |
17 | Release
18 | ARM
19 |
20 |
21 | Release
22 | ARM64
23 |
24 |
25 | Release
26 | Win32
27 |
28 |
29 | Debug
30 | x64
31 |
32 |
33 | Release
34 | x64
35 |
36 |
37 |
38 |
39 |
40 | true
41 | true
42 | true
43 | true
44 | true
45 | true
46 | true
47 | true
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | 15.0
65 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}
66 | Win32Proj
67 | Detours
68 | 10.0.17763.0
69 |
70 |
71 |
72 | StaticLibrary
73 | true
74 | v141_xp
75 | Unicode
76 | false
77 |
78 |
79 | StaticLibrary
80 | true
81 | v141
82 | Unicode
83 | false
84 |
85 |
86 | StaticLibrary
87 | true
88 | v141
89 | Unicode
90 | false
91 |
92 |
93 | StaticLibrary
94 | false
95 | v141_xp
96 | true
97 | Unicode
98 | false
99 |
100 |
101 | StaticLibrary
102 | false
103 | v141
104 | true
105 | Unicode
106 | false
107 |
108 |
109 | StaticLibrary
110 | false
111 | v141
112 | true
113 | Unicode
114 | false
115 |
116 |
117 | StaticLibrary
118 | true
119 | v141_xp
120 | Unicode
121 | false
122 |
123 |
124 | StaticLibrary
125 | false
126 | v141_xp
127 | true
128 | Unicode
129 | false
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | true
171 |
172 |
173 | true
174 |
175 |
176 | true
177 |
178 |
179 | true
180 |
181 |
182 | false
183 |
184 |
185 | false
186 |
187 |
188 | false
189 |
190 |
191 | false
192 |
193 |
194 |
195 | NotUsing
196 | Level3
197 | Disabled
198 |
199 |
200 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
201 |
202 |
203 | MultiThreadedDebug
204 | false
205 | true
206 |
207 |
208 | Windows
209 | true
210 |
211 |
212 |
213 |
214 | NotUsing
215 | Level3
216 | Disabled
217 |
218 |
219 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
220 |
221 |
222 | MultiThreadedDebug
223 | false
224 | true
225 |
226 |
227 | Windows
228 | true
229 |
230 |
231 |
232 |
233 | NotUsing
234 | Level3
235 | Disabled
236 |
237 |
238 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
239 |
240 |
241 | MultiThreadedDebug
242 | false
243 | true
244 |
245 |
246 | Windows
247 | true
248 |
249 |
250 |
251 |
252 | NotUsing
253 | Level3
254 | Disabled
255 |
256 |
257 | _DEBUG;_LIB;%(PreprocessorDefinitions)
258 |
259 |
260 | MultiThreadedDebug
261 | false
262 | true
263 |
264 |
265 | Windows
266 | true
267 |
268 |
269 |
270 |
271 | NotUsing
272 | Level3
273 | MaxSpeed
274 | true
275 | true
276 |
277 |
278 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
279 |
280 |
281 | MultiThreaded
282 | false
283 | true
284 |
285 |
286 | Windows
287 | true
288 | true
289 | true
290 |
291 |
292 |
293 |
294 | NotUsing
295 | Level3
296 | MaxSpeed
297 | true
298 | true
299 |
300 |
301 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
302 |
303 |
304 | MultiThreaded
305 | false
306 | true
307 |
308 |
309 | Windows
310 | true
311 | true
312 | true
313 |
314 |
315 |
316 |
317 | NotUsing
318 | Level3
319 | MaxSpeed
320 | true
321 | true
322 |
323 |
324 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
325 |
326 |
327 | MultiThreaded
328 | false
329 | true
330 |
331 |
332 | Windows
333 | true
334 | true
335 | true
336 |
337 |
338 |
339 |
340 | NotUsing
341 | Level3
342 | MaxSpeed
343 | true
344 | true
345 |
346 |
347 | NDEBUG;_LIB;%(PreprocessorDefinitions)
348 |
349 |
350 | MultiThreaded
351 | false
352 | true
353 |
354 |
355 | Windows
356 | true
357 | true
358 | true
359 |
360 |
361 |
362 |
363 |
364 |
--------------------------------------------------------------------------------
/Detours/Detours.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {052c3ff8-1732-4f83-acee-8e25f57f3c72}
18 |
19 |
20 | {9aee9e28-9e23-4b40-b0cd-2e79a28293ef}
21 |
22 |
23 |
24 |
25 | 源文件
26 |
27 |
28 | DeeoursNotify
29 |
30 |
31 | patch
32 |
33 |
34 | patch
35 |
36 |
37 | 源文件
38 |
39 |
40 |
41 |
42 | 头文件
43 |
44 |
45 | 头文件
46 |
47 |
48 | DeeoursNotify
49 |
50 |
51 | patch
52 |
53 |
54 | patch
55 |
56 |
57 |
58 |
59 | 资源文件
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Detours/src/DetoursNotify.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cxxzhang/DetoursEx/194f97661acde8d2f44428733888f805b2fb765c/Detours/src/DetoursNotify.cpp
--------------------------------------------------------------------------------
/Detours/src/DetoursNotify.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cxxzhang/DetoursEx/194f97661acde8d2f44428733888f805b2fb765c/Detours/src/DetoursNotify.h
--------------------------------------------------------------------------------
/Detours/src/Makefile:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | ##
3 | ## Makefile for Detours.
4 | ##
5 | ## Microsoft Research Detours Package, Version 4.0.1
6 | ##
7 | ## Copyright (c) Microsoft Corporation. All rights reserved.
8 | ##
9 |
10 | ROOT = ..
11 | !include "$(ROOT)\system.mak"
12 |
13 | !IF "$(DETOURS_SOURCE_BROWSING)" == ""
14 | DETOURS_SOURCE_BROWSING = 0
15 | !ENDIF
16 |
17 | #######################/#######################################################
18 | ##
19 | CFLAGS=/nologo /W4 /WX /we4777 /we4800 /Zi /MT /Gy /Gm- /Zl /Od /DDETOUR_DEBUG=$(DETOURS_DEBUG)
20 |
21 | !IF $(DETOURS_SOURCE_BROWSING)==1
22 | CFLAGS=$(CFLAGS) /FR
23 | !ELSE
24 | CFLAGS=$(CFLAGS) /DWIN32_LEAN_AND_MEAN /D_WIN32_WINNT=0x501
25 | !ENDIF
26 |
27 | !IF "$(DETOURS_TARGET_PROCESSOR)" == "IA64"
28 | CFLAGS=$(CFLAGS) /wd4163 # intrinsic rdtebex not available; using newer Windows headers with older compiler
29 | !ENDIF
30 |
31 | !if defined(DETOURS_WIN_7) && defined(DETOURS_CL_17_OR_NEWER)
32 | CFLAGS=$(CFLAGS) /D_USING_V110_SDK71_
33 | !elseif defined(DETOURS_ANALYZE)
34 | CFLAGS=$(CFLAGS) /analyze
35 | !endif
36 |
37 | OBJS = \
38 | $(OBJD)\detours.obj \
39 | $(OBJD)\modules.obj \
40 | $(OBJD)\disasm.obj \
41 | $(OBJD)\image.obj \
42 | $(OBJD)\creatwth.obj \
43 | $(OBJD)\disolx86.obj \
44 | $(OBJD)\disolx64.obj \
45 | $(OBJD)\disolia64.obj \
46 | $(OBJD)\disolarm.obj \
47 | $(OBJD)\disolarm64.obj \
48 |
49 | ##############################################################################
50 | ##
51 | .SUFFIXES: .cpp .h .obj
52 |
53 | !ifdef DETOURS_ANALYZE
54 | .cpp{$(OBJD)}.obj:
55 | $(CC) $(CFLAGS) /Fd$(LIBD)\detours.pdb /Fo$(OBJD)\ /c $<
56 | !else
57 | .cpp{$(OBJD)}.obj::
58 | $(CC) $(CFLAGS) /Fd$(LIBD)\detours.pdb /Fo$(OBJD)\ /c $<
59 | !endif
60 |
61 | ##############################################################################
62 |
63 | all: dirs \
64 | $(LIBD)\detours.lib \
65 | $(INCD)\detours.h \
66 | $(INCD)\detver.h \
67 | !IF $(DETOURS_SOURCE_BROWSING)==1
68 | $(OBJD)\detours.bsc \
69 | !endif
70 |
71 | ##############################################################################
72 |
73 | clean:
74 | -del *~ 2>nul
75 | -del $(LIBD)\detours.pdb $(LIBD)\detours.lib 2>nul
76 | -rmdir /q /s $(OBJD) 2>nul
77 |
78 | realclean: clean
79 | -rmdir /q /s $(OBJDS) 2>nul
80 |
81 | ##############################################################################
82 |
83 | dirs:
84 | @if not exist "$(INCD)" mkdir "$(INCD)" && echo. Created $(INCD)
85 | @if not exist "$(LIBD)" mkdir "$(LIBD)" && echo. Created $(LIBD)
86 | @if not exist "$(BIND)" mkdir "$(BIND)" && echo. Created $(BIND)
87 | @if not exist "$(OBJD)" mkdir "$(OBJD)" && echo. Created $(OBJD)
88 |
89 | $(OBJD)\detours.bsc : $(OBJS)
90 | bscmake /v /n /o $@ $(OBJS:.obj=.sbr)
91 |
92 | $(LIBD)\detours.lib : $(OBJS)
93 | link /lib /out:$@ /nologo $(OBJS)
94 |
95 | $(INCD)\detours.h : detours.h
96 | copy detours.h $@
97 |
98 | $(INCD)\detver.h : detver.h
99 | copy detver.h $@
100 |
101 | $(OBJD)\detours.obj : detours.cpp detours.h
102 | $(OBJD)\modules.obj : modules.cpp detours.h
103 | $(OBJD)\disasm.obj : disasm.cpp detours.h
104 | $(OBJD)\image.obj : image.cpp detours.h
105 | $(OBJD)\creatwth.obj : creatwth.cpp uimports.cpp detours.h
106 | $(OBJD)\disolx86.obj: disasm.cpp detours.h
107 | $(OBJD)\disolx64.obj: disasm.cpp detours.h
108 | $(OBJD)\disolia64.obj: disasm.cpp detours.h
109 | $(OBJD)\disolarm.obj: disasm.cpp detours.h
110 | $(OBJD)\disolarm64.obj: disasm.cpp detours.h
111 |
112 | test: all
113 | cd $(MAKEDIR)\..\samples\slept
114 | nmake /nologo test
115 | cd $(MAKEDIR)
116 |
117 | ################################################################# End of File.
118 |
--------------------------------------------------------------------------------
/Detours/src/detours.h:
--------------------------------------------------------------------------------
1 | /////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Core Detours Functionality (detours.h of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 4.0.1
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 |
10 | #pragma once
11 | #ifndef _DETOURS_H_
12 | #define _DETOURS_H_
13 |
14 | #define DETOURS_VERSION 0x4c0c1 // 0xMAJORcMINORcPATCH
15 |
16 | //////////////////////////////////////////////////////////////////////////////
17 | //
18 |
19 | #include "windows_shim.h"
20 | #include "mem_patch.h"
21 |
22 | #ifdef DETOURS_INTERNAL
23 |
24 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
25 | #ifndef _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
26 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
27 | #endif
28 |
29 | #pragma warning(disable:4068) // unknown pragma (suppress)
30 |
31 | #if _MSC_VER >= 1900
32 | #pragma warning(push)
33 | #pragma warning(disable:4091) // empty typedef
34 | #endif
35 |
36 | // Suppress declspec(dllimport) for the sake of Detours
37 | // users that provide kernel32 functionality themselves.
38 | // This is ok in the mainstream case, it will just cost
39 | // an extra instruction calling some functions, which
40 | // LTCG optimizes away.
41 | //
42 | #define _KERNEL32_ 1
43 | #define _USER32_ 1
44 |
45 | #endif // DETOURS_INTERNAL
46 |
47 | //////////////////////////////////////////////////////////////////////////////
48 | //
49 |
50 | #undef DETOURS_X64
51 | #undef DETOURS_X86
52 | #undef DETOURS_IA64
53 | #undef DETOURS_ARM
54 | #undef DETOURS_ARM64
55 | #undef DETOURS_BITS
56 | #undef DETOURS_32BIT
57 | #undef DETOURS_64BIT
58 |
59 | #if defined(_X86_)
60 | #define DETOURS_X86
61 | #define DETOURS_OPTION_BITS 64
62 |
63 | #elif defined(_AMD64_)
64 | #define DETOURS_X64
65 | #define DETOURS_OPTION_BITS 32
66 |
67 | #elif defined(_IA64_)
68 | #define DETOURS_IA64
69 | #define DETOURS_OPTION_BITS 32
70 |
71 | #elif defined(_ARM_)
72 | #define DETOURS_ARM
73 |
74 | #elif defined(_ARM64_)
75 | #define DETOURS_ARM64
76 |
77 | #else
78 | #error Unknown architecture (x86, amd64, ia64, arm, arm64)
79 | #endif
80 |
81 | #if defined(DETOURS_ARM64) || defined(DETOURS_X64) || defined(DETOURS_IA64)
82 | #undef DETOURS_32BIT
83 | #define DETOURS_64BIT 1
84 | #define DETOURS_BITS 64
85 | // If all 64bit kernels can run one and only one 32bit architecture.
86 | //#define DETOURS_OPTION_BITS 32
87 | #else
88 | #define DETOURS_32BIT 1
89 | #undef DETOURS_64BIT
90 | #define DETOURS_BITS 32
91 | // If all 64bit kernels can run one and only one 32bit architecture.
92 | //#define DETOURS_OPTION_BITS 32
93 | #endif
94 |
95 | /////////////////////////////////////////////////////////////// Helper Macros.
96 | //
97 | #define DETOURS_STRINGIFY_(x) #x
98 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
99 |
100 | #define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS)
101 |
102 | //////////////////////////////////////////////////////////////////////////////
103 | //
104 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL.
105 | //
106 | // These definitions are include so that Detours will build even if the
107 | // compiler doesn't have full SAL 2.0 support.
108 | //
109 | #ifndef DETOURS_DONT_REMOVE_SAL_20
110 |
111 | #ifdef DETOURS_TEST_REMOVE_SAL_20
112 | #undef _Analysis_assume_
113 | #undef _Benign_race_begin_
114 | #undef _Benign_race_end_
115 | #undef _Field_range_
116 | #undef _Field_size_
117 | #undef _In_
118 | #undef _In_bytecount_
119 | #undef _In_count_
120 | #undef __in_ecount
121 | #undef _In_opt_
122 | #undef _In_opt_bytecount_
123 | #undef _In_opt_count_
124 | #undef _In_opt_z_
125 | #undef _In_range_
126 | #undef _In_reads_
127 | #undef _In_reads_bytes_
128 | #undef _In_reads_opt_
129 | #undef _In_reads_opt_bytes_
130 | #undef _In_reads_or_z_
131 | #undef _In_z_
132 | #undef _Inout_
133 | #undef _Inout_opt_
134 | #undef _Inout_z_count_
135 | #undef _Out_
136 | #undef _Out_opt_
137 | #undef _Out_writes_
138 | #undef _Outptr_result_maybenull_
139 | #undef _Readable_bytes_
140 | #undef _Success_
141 | #undef _Writable_bytes_
142 | #undef _Pre_notnull_
143 | #endif
144 |
145 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_)
146 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_
147 | #endif
148 |
149 | #if defined(_In_count_) && !defined(_In_reads_)
150 | #define _In_reads_(x) _In_count_(x)
151 | #endif
152 |
153 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_)
154 | #define _In_reads_opt_(x) _In_opt_count_(x)
155 | #endif
156 |
157 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_)
158 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x)
159 | #endif
160 |
161 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_)
162 | #define _In_reads_bytes_(x) _In_bytecount_(x)
163 | #endif
164 |
165 | #ifndef _In_
166 | #define _In_
167 | #endif
168 |
169 | #ifndef _In_bytecount_
170 | #define _In_bytecount_(x)
171 | #endif
172 |
173 | #ifndef _In_count_
174 | #define _In_count_(x)
175 | #endif
176 |
177 | #ifndef __in_ecount
178 | #define __in_ecount(x)
179 | #endif
180 |
181 | #ifndef _In_opt_
182 | #define _In_opt_
183 | #endif
184 |
185 | #ifndef _In_opt_bytecount_
186 | #define _In_opt_bytecount_(x)
187 | #endif
188 |
189 | #ifndef _In_opt_count_
190 | #define _In_opt_count_(x)
191 | #endif
192 |
193 | #ifndef _In_opt_z_
194 | #define _In_opt_z_
195 | #endif
196 |
197 | #ifndef _In_range_
198 | #define _In_range_(x,y)
199 | #endif
200 |
201 | #ifndef _In_reads_
202 | #define _In_reads_(x)
203 | #endif
204 |
205 | #ifndef _In_reads_bytes_
206 | #define _In_reads_bytes_(x)
207 | #endif
208 |
209 | #ifndef _In_reads_opt_
210 | #define _In_reads_opt_(x)
211 | #endif
212 |
213 | #ifndef _In_reads_opt_bytes_
214 | #define _In_reads_opt_bytes_(x)
215 | #endif
216 |
217 | #ifndef _In_reads_or_z_
218 | #define _In_reads_or_z_
219 | #endif
220 |
221 | #ifndef _In_z_
222 | #define _In_z_
223 | #endif
224 |
225 | #ifndef _Inout_
226 | #define _Inout_
227 | #endif
228 |
229 | #ifndef _Inout_opt_
230 | #define _Inout_opt_
231 | #endif
232 |
233 | #ifndef _Inout_z_count_
234 | #define _Inout_z_count_(x)
235 | #endif
236 |
237 | #ifndef _Out_
238 | #define _Out_
239 | #endif
240 |
241 | #ifndef _Out_opt_
242 | #define _Out_opt_
243 | #endif
244 |
245 | #ifndef _Out_writes_
246 | #define _Out_writes_(x)
247 | #endif
248 |
249 | #ifndef _Outptr_result_maybenull_
250 | #define _Outptr_result_maybenull_
251 | #endif
252 |
253 | #ifndef _Writable_bytes_
254 | #define _Writable_bytes_(x)
255 | #endif
256 |
257 | #ifndef _Readable_bytes_
258 | #define _Readable_bytes_(x)
259 | #endif
260 |
261 | #ifndef _Success_
262 | #define _Success_(x)
263 | #endif
264 |
265 | #ifndef _Pre_notnull_
266 | #define _Pre_notnull_
267 | #endif
268 |
269 | #ifdef DETOURS_INTERNAL
270 |
271 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers)
272 |
273 | #ifndef _Benign_race_begin_
274 | #define _Benign_race_begin_
275 | #endif
276 |
277 | #ifndef _Benign_race_end_
278 | #define _Benign_race_end_
279 | #endif
280 |
281 | #ifndef _Field_size_
282 | #define _Field_size_(x)
283 | #endif
284 |
285 | #ifndef _Field_range_
286 | #define _Field_range_(x,y)
287 | #endif
288 |
289 | #ifndef _Analysis_assume_
290 | #define _Analysis_assume_(x)
291 | #endif
292 |
293 | #endif // DETOURS_INTERNAL
294 | #endif // DETOURS_DONT_REMOVE_SAL_20
295 |
296 | //////////////////////////////////////////////////////////////////////////////
297 | //
298 | #ifndef GUID_DEFINED
299 | #define GUID_DEFINED
300 | typedef struct _GUID
301 | {
302 | DWORD Data1;
303 | WORD Data2;
304 | WORD Data3;
305 | BYTE Data4[ 8 ];
306 | } GUID;
307 |
308 | #ifdef INITGUID
309 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
310 | const GUID name \
311 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
312 | #else
313 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
314 | const GUID name
315 | #endif // INITGUID
316 | #endif // !GUID_DEFINED
317 |
318 | #if defined(__cplusplus)
319 | #ifndef _REFGUID_DEFINED
320 | #define _REFGUID_DEFINED
321 | #define REFGUID const GUID &
322 | #endif // !_REFGUID_DEFINED
323 | #else // !__cplusplus
324 | #ifndef _REFGUID_DEFINED
325 | #define _REFGUID_DEFINED
326 | #define REFGUID const GUID * const
327 | #endif // !_REFGUID_DEFINED
328 | #endif // !__cplusplus
329 |
330 | #ifndef ARRAYSIZE
331 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
332 | #endif
333 |
334 | //
335 | //////////////////////////////////////////////////////////////////////////////
336 |
337 | #ifdef __cplusplus
338 | extern "C" {
339 | #endif // __cplusplus
340 |
341 | /////////////////////////////////////////////////// Instruction Target Macros.
342 | //
343 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0)
344 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1)
345 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0"
346 |
347 | extern const GUID DETOUR_EXE_RESTORE_GUID;
348 | extern const GUID DETOUR_EXE_HELPER_GUID;
349 |
350 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
351 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
352 |
353 | #ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
354 | #define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32
355 | #endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
356 |
357 | /////////////////////////////////////////////////////////// Binary Structures.
358 | //
359 | #pragma pack(push, 8)
360 | typedef struct _DETOUR_SECTION_HEADER
361 | {
362 | DWORD cbHeaderSize;
363 | DWORD nSignature;
364 | DWORD nDataOffset;
365 | DWORD cbDataSize;
366 |
367 | DWORD nOriginalImportVirtualAddress;
368 | DWORD nOriginalImportSize;
369 | DWORD nOriginalBoundImportVirtualAddress;
370 | DWORD nOriginalBoundImportSize;
371 |
372 | DWORD nOriginalIatVirtualAddress;
373 | DWORD nOriginalIatSize;
374 | DWORD nOriginalSizeOfImage;
375 | DWORD cbPrePE;
376 |
377 | DWORD nOriginalClrFlags;
378 | DWORD reserved1;
379 | DWORD reserved2;
380 | DWORD reserved3;
381 |
382 | // Followed by cbPrePE bytes of data.
383 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER;
384 |
385 | typedef struct _DETOUR_SECTION_RECORD
386 | {
387 | DWORD cbBytes;
388 | DWORD nReserved;
389 | GUID guid;
390 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD;
391 |
392 | #pragma pack(pop)
393 |
394 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \
395 | { \
396 | sizeof(DETOUR_SECTION_HEADER),\
397 | DETOUR_SECTION_HEADER_SIGNATURE,\
398 | sizeof(DETOUR_SECTION_HEADER),\
399 | (cbSectionSize),\
400 | \
401 | 0,\
402 | 0,\
403 | 0,\
404 | 0,\
405 | \
406 | 0,\
407 | 0,\
408 | 0,\
409 | 0,\
410 | }
411 |
412 | ///////////////////////////////////////////////////////////// Binary Typedefs.
413 | //
414 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(
415 | _In_opt_ PVOID pContext,
416 | _In_opt_ LPCSTR pszFile,
417 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile);
418 |
419 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)(
420 | _In_opt_ PVOID pContext,
421 | _In_ LPCSTR pszOrigFile,
422 | _In_ LPCSTR pszFile,
423 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile);
424 |
425 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)(
426 | _In_opt_ PVOID pContext,
427 | _In_ ULONG nOrigOrdinal,
428 | _In_ ULONG nOrdinal,
429 | _Out_ ULONG *pnOutOrdinal,
430 | _In_opt_ LPCSTR pszOrigSymbol,
431 | _In_opt_ LPCSTR pszSymbol,
432 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol);
433 |
434 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)(
435 | _In_opt_ PVOID pContext);
436 |
437 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext,
438 | _In_ ULONG nOrdinal,
439 | _In_opt_ LPCSTR pszName,
440 | _In_opt_ PVOID pCode);
441 |
442 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext,
443 | _In_opt_ HMODULE hModule,
444 | _In_opt_ LPCSTR pszFile);
445 |
446 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext,
447 | _In_ DWORD nOrdinal,
448 | _In_opt_ LPCSTR pszFunc,
449 | _In_opt_ PVOID pvFunc);
450 |
451 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter.
452 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext,
453 | _In_ DWORD nOrdinal,
454 | _In_opt_ LPCSTR pszFunc,
455 | _In_opt_ PVOID* ppvFunc);
456 |
457 | typedef VOID * PDETOUR_BINARY;
458 | typedef VOID * PDETOUR_LOADED_BINARY;
459 |
460 | typedef struct _DETROUS_HOOK_NOTIFY_INFO_STRCUT
461 | {
462 | PVOID pContext;
463 | PVOID pFunInfo;//PF_DETOUR_HOOK_NOTIFY
464 |
465 | PVOID pParam1;//address saved params. most support 16 pararms, if not enough? you can count offset by yourself.
466 | PVOID pParam2;
467 | PVOID pParam3;
468 | PVOID pParam4;
469 | PVOID pParam5;
470 | PVOID pParam6;
471 | PVOID pParam7;
472 | PVOID pParam8;
473 | PVOID pParam9;
474 | PVOID pParam10;
475 | PVOID pParam11;
476 | PVOID pParam12;
477 | PVOID pParam13;
478 | PVOID pParam14;
479 | PVOID pParam15;
480 | PVOID pParam16;
481 |
482 | #if defined(_X86_)
483 | PVOID ESP;
484 | PVOID pEAX;//address saved eax value
485 | PVOID pECX;
486 | PVOID pEDX;
487 | PVOID pEBX;
488 | PVOID pESP;
489 | PVOID pEBP;
490 | PVOID pESI;
491 | PVOID pEDI;
492 | #elif defined(_AMD64_)
493 | PVOID RSP;
494 | PVOID pRSP;
495 | PVOID pRAX;
496 | PVOID pRCX;
497 | PVOID pRDX;
498 | PVOID pRBX;
499 | PVOID pRBP;
500 | PVOID pRSI;
501 | PVOID pRDI;
502 | PVOID pR8;
503 | PVOID pR9;
504 | PVOID pR10;
505 | PVOID pR11;
506 | PVOID pR12;
507 | PVOID pR13;
508 | PVOID pR14;
509 | PVOID pR15;
510 | #elif defined(_ARM64_)
511 | PVOID SP;
512 | PVOID pX0;
513 | PVOID pX1;
514 | PVOID pX2;
515 | PVOID pX3;
516 | PVOID pX4;
517 | PVOID pX5;
518 | PVOID pX6;
519 | PVOID pX7;
520 | PVOID pX8;
521 | PVOID pX9;
522 | PVOID pX10;
523 | PVOID pX11;
524 | PVOID pX12;
525 | PVOID pX13;
526 | PVOID pX14;
527 | PVOID pX15;
528 | PVOID pX16;
529 | PVOID pX17;
530 | PVOID pX18;
531 | PVOID pX19;
532 | PVOID pX20;
533 | PVOID pX21;
534 | PVOID pX22;
535 | PVOID pX23;
536 | PVOID pX24;
537 | PVOID pX25;
538 | PVOID pX26;
539 | PVOID pX27;
540 | PVOID pX28;
541 | PVOID pX29;
542 | PVOID pX30;
543 | #elif defined(_ARM_)
544 | PVOID SP;
545 | PVOID pR0;
546 | PVOID pR1;
547 | PVOID pR2;
548 | PVOID pR3;
549 | PVOID pR4;
550 | PVOID pR5;
551 | PVOID pR6;
552 | PVOID pR7;
553 | PVOID pR8;
554 | PVOID pR9;
555 | PVOID pR10;
556 | PVOID pR11;
557 | PVOID pR12;
558 | #endif
559 | }DETROUS_HOOK_NOTIFY_INFO_STRCUT, *PDETROUS_HOOK_NOTIFY_INFO_STRCUT;
560 |
561 | typedef BOOL (CALLBACK* PF_DETOUR_HOOK_NOTIFY)(_In_ PDETROUS_HOOK_NOTIFY_INFO_STRCUT pInfo);
562 |
563 | //////////////////////////////////////////////////////////// Transaction APIs.
564 | //
565 | LONG WINAPI DetourTransactionBegin(VOID);
566 | LONG WINAPI DetourTransactionAbort(VOID);
567 | LONG WINAPI DetourTransactionCommit(VOID);
568 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer);
569 |
570 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread);
571 |
572 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer,
573 | _In_ PVOID pDetour);
574 |
575 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
576 | _In_ PVOID pDetour,
577 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline,
578 | _Out_opt_ PVOID *ppRealTarget,
579 | _Out_opt_ PVOID *ppRealDetour);
580 |
581 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer,
582 | _In_ PVOID pDetour);
583 |
584 | LONG WINAPI DetourInstallNotify(_Inout_ PVOID *ppPointer, _In_ PF_DETOUR_HOOK_NOTIFY pNotify,PVOID pContext = NULL );
585 | LONG WINAPI DetourInstallNotifyEx(_Inout_ PVOID *ppPointer, _In_ PF_DETOUR_HOOK_NOTIFY pNotify, PVOID pContext, USHORT ulEspAddWhenBlock);
586 | LONG WINAPI DetourUnInstallNotify(_Inout_ PVOID *ppPointer, _In_ PF_DETOUR_HOOK_NOTIFY pNotify);
587 | UCHAR* WINAPI SkipJump(UCHAR* Ptr);
588 |
589 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore);
590 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain);
591 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound);
592 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound);
593 |
594 | ////////////////////////////////////////////////////////////// Code Functions.
595 | //
596 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
597 | _In_ LPCSTR pszFunction);
598 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer,
599 | _Out_opt_ PVOID *ppGlobals);
600 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
601 | _Inout_opt_ PVOID *ppDstPool,
602 | _In_ PVOID pSrc,
603 | _Out_opt_ PVOID *ppTarget,
604 | _Out_opt_ LONG *plExtra);
605 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
606 | _In_ BOOL fLimitReferencesToModule);
607 | PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
608 | _Out_ PDWORD pcbAllocatedSize);
609 |
610 | ///////////////////////////////////////////////////// Loaded Binary Functions.
611 | //
612 | ///////////////////////////////////////////////// Persistent Binary Functions.
613 | //
614 |
615 |
616 | /////////////////////////////////////////////////// Create Process & Load Dll.
617 | //
618 |
619 | //
620 | //////////////////////////////////////////////////////////////////////////////
621 | #ifdef __cplusplus
622 | }
623 | #endif // __cplusplus
624 |
625 | /////////////////////////////////////////////////// Type-safe overloads for C++
626 | //
627 | //
628 | //////////////////////////////////////////////////////////////////////////////
629 |
630 | //////////////////////////////////////////////// Detours Internal Definitions.
631 | //
632 | #ifdef __cplusplus
633 | #ifdef DETOURS_INTERNAL
634 |
635 | #define NOTHROW
636 | // #define NOTHROW (nothrow)
637 |
638 | //////////////////////////////////////////////////////////////////////////////
639 | //
640 |
641 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS)
642 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier)
643 | #endif
644 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
645 |
646 | #ifdef _DEBUG
647 |
648 | int Detour_AssertExprWithFunctionName(int reportType, const char* filename, int linenumber, const char* FunctionName, const char* msg);
649 |
650 | #define DETOUR_ASSERT_EXPR_WITH_FUNCTION(expr, msg) \
651 | (void) ((expr) || \
652 | (1 != Detour_AssertExprWithFunctionName(_CRT_ASSERT, __FILE__, __LINE__,__FUNCTION__, msg)) || \
653 | (_CrtDbgBreak(), 0))
654 |
655 | #define DETOUR_ASSERT(expr) DETOUR_ASSERT_EXPR_WITH_FUNCTION((expr), #expr)
656 |
657 | #else// _DEBUG
658 | #define DETOUR_ASSERT(expr)
659 | #endif// _DEBUG
660 |
661 | #ifndef DETOUR_TRACE
662 | #if DETOUR_DEBUG
663 | #define DETOUR_TRACE(x) printf x
664 | #define DETOUR_BREAK() __debugbreak()
665 | #include
666 | #include
667 | #else
668 | #define DETOUR_TRACE(x)
669 | #define DETOUR_BREAK()
670 | #endif
671 | #endif
672 |
673 | #if 1 || defined(DETOURS_IA64)
674 |
675 | //
676 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle.
677 | //
678 |
679 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3)
680 |
681 | #define DETOUR_IA64_TEMPLATE_OFFSET (0)
682 | #define DETOUR_IA64_TEMPLATE_SIZE (5)
683 |
684 | #define DETOUR_IA64_INSTRUCTION_SIZE (41)
685 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE)
686 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE)
687 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE)
688 |
689 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128);
690 |
691 | #if defined(_MSC_VER)
692 | #define ALIGNED_(x) __declspec(align(x))
693 | #else
694 | #if defined(__GNUC__)
695 | #define ALIGNED_(x) __attribute__ ((aligned(x)))
696 | #endif
697 | #endif
698 |
699 | struct ALIGNED_(16) DETOUR_IA64_BUNDLE
700 | {
701 | public:
702 | union
703 | {
704 | BYTE data[16];
705 | UINT64 wide[2];
706 | };
707 |
708 | enum {
709 | A_UNIT = 1u,
710 | I_UNIT = 2u,
711 | M_UNIT = 3u,
712 | B_UNIT = 4u,
713 | F_UNIT = 5u,
714 | L_UNIT = 6u,
715 | X_UNIT = 7u,
716 | };
717 | struct DETOUR_IA64_METADATA
718 | {
719 | ULONG nTemplate : 8; // Instruction template.
720 | ULONG nUnit0 : 4; // Unit for slot 0
721 | ULONG nUnit1 : 4; // Unit for slot 1
722 | ULONG nUnit2 : 4; // Unit for slot 2
723 | };
724 |
725 | protected:
726 | static const DETOUR_IA64_METADATA s_rceCopyTable[33];
727 |
728 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const;
729 |
730 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst,
731 | _In_ BYTE slot,
732 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const;
733 |
734 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0
735 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0.
736 |
737 | // 00
738 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0.
739 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0]
740 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5]
741 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42]
742 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46]
743 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83]
744 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87]
745 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124]
746 | BYTE GetTemplate() const;
747 | // Get 4 bit opcodes.
748 | BYTE GetInst0() const;
749 | BYTE GetInst1() const;
750 | BYTE GetInst2() const;
751 | BYTE GetUnit(BYTE slot) const;
752 | BYTE GetUnit0() const;
753 | BYTE GetUnit1() const;
754 | BYTE GetUnit2() const;
755 | // Get 37 bit data.
756 | UINT64 GetData0() const;
757 | UINT64 GetData1() const;
758 | UINT64 GetData2() const;
759 |
760 | // Get/set the full 41 bit instructions.
761 | UINT64 GetInstruction(BYTE slot) const;
762 | UINT64 GetInstruction0() const;
763 | UINT64 GetInstruction1() const;
764 | UINT64 GetInstruction2() const;
765 | void SetInstruction(BYTE slot, UINT64 instruction);
766 | void SetInstruction0(UINT64 instruction);
767 | void SetInstruction1(UINT64 instruction);
768 | void SetInstruction2(UINT64 instruction);
769 |
770 | // Get/set bitfields.
771 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count);
772 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field);
773 |
774 | // Get specific read-only fields.
775 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode
776 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension
777 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension
778 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension
779 |
780 | // Get/set specific fields.
781 | static UINT64 GetImm7a(UINT64 instruction);
782 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a);
783 | static UINT64 GetImm13c(UINT64 instruction);
784 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c);
785 | static UINT64 GetSignBit(UINT64 instruction);
786 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit);
787 | static UINT64 GetImm20a(UINT64 instruction);
788 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a);
789 | static UINT64 GetImm20b(UINT64 instruction);
790 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b);
791 |
792 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset);
793 |
794 | BOOL IsMovlGp() const;
795 |
796 | VOID SetInst(BYTE Slot, BYTE nInst);
797 | VOID SetInst0(BYTE nInst);
798 | VOID SetInst1(BYTE nInst);
799 | VOID SetInst2(BYTE nInst);
800 | VOID SetData(BYTE Slot, UINT64 nData);
801 | VOID SetData0(UINT64 nData);
802 | VOID SetData1(UINT64 nData);
803 | VOID SetData2(UINT64 nData);
804 | BOOL SetNop(BYTE Slot);
805 | BOOL SetNop0();
806 | BOOL SetNop1();
807 | BOOL SetNop2();
808 |
809 | public:
810 | BOOL IsBrl() const;
811 | VOID SetBrl();
812 | VOID SetBrl(UINT64 target);
813 | UINT64 GetBrlTarget() const;
814 | VOID SetBrlTarget(UINT64 target);
815 | VOID SetBrlImm(UINT64 imm);
816 | UINT64 GetBrlImm() const;
817 |
818 | UINT64 GetMovlGp() const;
819 | VOID SetMovlGp(UINT64 gp);
820 |
821 | VOID SetStop();
822 |
823 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const;
824 | };
825 | #endif // DETOURS_IA64
826 |
827 | #ifdef DETOURS_ARM
828 |
829 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1))
830 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1))
831 |
832 | #endif // DETOURS_ARM
833 |
834 | //////////////////////////////////////////////////////////////////////////////
835 |
836 | #ifdef __cplusplus
837 | extern "C" {
838 | #endif // __cplusplus
839 |
840 | #define DETOUR_OFFLINE_LIBRARY(x) \
841 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \
842 | _Inout_opt_ PVOID *ppDstPool, \
843 | _In_ PVOID pSrc, \
844 | _Out_opt_ PVOID *ppTarget, \
845 | _Out_opt_ LONG *plExtra); \
846 | \
847 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \
848 | _In_ BOOL fLimitReferencesToModule); \
849 |
850 | DETOUR_OFFLINE_LIBRARY(X86)
851 | DETOUR_OFFLINE_LIBRARY(X64)
852 | DETOUR_OFFLINE_LIBRARY(ARM)
853 | DETOUR_OFFLINE_LIBRARY(ARM64)
854 | DETOUR_OFFLINE_LIBRARY(IA64)
855 |
856 | #undef DETOUR_OFFLINE_LIBRARY
857 |
858 | #ifdef __cplusplus
859 | }
860 | #endif // __cplusplus
861 |
862 |
863 | #endif // DETOURS_INTERNAL
864 |
865 |
866 | //////////////////////////////////////////////////////////////////////////////
867 | //
868 | // Helpers for manipulating page protection.
869 | //
870 |
871 | #ifdef __cplusplus
872 | extern "C" {
873 | #endif // __cplusplus
874 |
875 | _Success_(return != FALSE)
876 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess,
877 | _In_ PVOID pAddress,
878 | _In_ SIZE_T nSize,
879 | _In_ DWORD dwNewProtect,
880 | _Out_ PDWORD pdwOldProtect);
881 |
882 | _Success_(return != FALSE)
883 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
884 | _In_ SIZE_T nSize,
885 | _In_ DWORD dwNewProtect,
886 | _Out_ PDWORD pdwOldProtect);
887 |
888 | // Detours must depend only on kernel32.lib, so we cannot use IsEqualGUID
889 | BOOL WINAPI DetourAreSameGuid(_In_ REFGUID left, _In_ REFGUID right);
890 |
891 | #ifdef __cplusplus
892 | }
893 | #endif // __cplusplus
894 |
895 | //////////////////////////////////////////////////////////////////////////////
896 |
897 | #define MM_ALLOCATION_GRANULARITY 0x10000
898 |
899 | //////////////////////////////////////////////////////////////////////////////
900 |
901 | #endif // __cplusplus
902 |
903 | #endif // _DETOURS_H_
904 | //
905 | //////////////////////////////////////////////////////////////// End of File.
--------------------------------------------------------------------------------
/Detours/src/detours_patch.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_INTERNAL
2 | #include "detours.h"
3 | #undef DETOURS_INTERNAL
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | typedef unsigned char BYTE_,*PBYTE_;
10 | typedef PBYTE_ ULONG_PTR_;
11 | typedef uint64_t ULONG64_;
12 | PBYTE_ detour_gen_jmp_immediate(PBYTE_ pbCode, PBYTE_ pbJmpVal);
13 | PBYTE_ detour_gen_jmp_indirect(PBYTE_ pbCode, PBYTE_ *ppbJmpVal);
14 | PBYTE_ detour_gen_brk(PBYTE_ pbCode, PBYTE_ pbLimit);
15 | PBYTE_ detour_gen_jmp_immediate(PBYTE_ pbCode, PBYTE_ *ppPool, PBYTE_ pbJmpVal);
16 | PBYTE_ detour_gen_jmp_indirect(BYTE_ *pbCode, ULONG64_ *pbJmpVal);
17 |
18 | struct DetourMemoryOpWrapper {
19 | DetourMemoryOpWrapper *pNext;
20 | DetourMemoryOpWrapper *pPrev;
21 | void *pbCode;
22 | char rbCode[0x100];
23 | int iCodeSize;
24 | };
25 |
26 | static DetourMemoryOpWrapper *s_detoursMemoryOp = nullptr;
27 |
28 |
29 | static BOOL is_trampoline(ULONG_PTR_ addr);
30 |
31 | inline static void push_op(DetourMemoryOpWrapper *o) {
32 | o->pPrev = s_detoursMemoryOp;
33 | if (s_detoursMemoryOp) {
34 | s_detoursMemoryOp->pNext = o;
35 | }
36 | o->pNext = nullptr;
37 | s_detoursMemoryOp = o;
38 | }
39 |
40 | #define MAX_PAGE_SIZE 0x1000
41 | #define MAX_PATCH_SIZE 0x100
42 |
43 | // do 's|detour_gen_(.*?)\((.*?)\);|detour_gen_$1_($2);|' on detours.cpp
44 | template
45 | PBYTE_ detour_gen_jmp_indirect_(T1 pbCode, T2 value) {
46 | DETOUR_TRACE(("detour_gen_jmp_indirect_(%p, %p)\n", pbCode, value));
47 | #if !defined(_DARWIN)
48 | return detour_gen_jmp_indirect((T1)pbCode, (T2)value);
49 | #endif
50 | if (is_trampoline((ULONG_PTR_)(pbCode))) return detour_gen_jmp_indirect((T1)pbCode, (T2)value);
51 |
52 | char _pbCodeBuf[2 * MAX_PAGE_SIZE + 0x100] = { 0 };
53 | char *pbCodeBuf = _pbCodeBuf + MAX_PAGE_SIZE - ((ULONG64_)(ULONG_PTR_)_pbCodeBuf & 0xfff) + ((ULONG64_)(ULONG_PTR_)pbCode & 0xfff);
54 | memcpy(pbCodeBuf, pbCode, MAX_PATCH_SIZE);
55 | ULONG_PTR_ newvalue = 0;
56 | if (value != nullptr) {
57 | newvalue = (ULONG_PTR_)value - (ULONG_PTR_)pbCode + (ULONG_PTR_)pbCodeBuf;
58 | }
59 | PBYTE_ ret = detour_gen_jmp_indirect((T1)pbCodeBuf, (T2)newvalue);
60 |
61 | DetourMemoryOpWrapper *o = new DetourMemoryOpWrapper;
62 | o->pbCode = pbCode;
63 | o->iCodeSize = (int)(ret - (PBYTE_)pbCodeBuf);
64 | memcpy(o->rbCode, pbCodeBuf, sizeof(o->rbCode));
65 | push_op(o);
66 |
67 | ret = (PBYTE_)((ULONG_PTR_)ret - (ULONG_PTR_)pbCodeBuf + (ULONG_PTR_)pbCode);
68 | return ret;
69 | }
70 |
71 | template
72 | PBYTE_ detour_gen_jmp_immediate_(T1 pbCode, T2 value) {
73 | DETOUR_TRACE(("detour_gen_jmp_immediate_(%p, %p)\n", pbCode, value));
74 | #if !defined(_DARWIN)
75 | return detour_gen_jmp_immediate((T1)pbCode, (T2)value);
76 | #endif
77 | if (is_trampoline((ULONG_PTR_)(pbCode))) return detour_gen_jmp_immediate((T1)pbCode, (T2)value);
78 |
79 |
80 | char _pbCodeBuf[2 * MAX_PAGE_SIZE + 0x100] = { 0 };
81 | char *pbCodeBuf = _pbCodeBuf + MAX_PAGE_SIZE - ((ULONG64_)(ULONG_PTR_)_pbCodeBuf & 0xfff) + ((ULONG64_)(ULONG_PTR_)pbCode & 0xfff);
82 | memcpy(pbCodeBuf, pbCode, MAX_PATCH_SIZE);
83 | ULONG_PTR_ newvalue = 0;
84 | if (value != nullptr) {
85 | newvalue = (ULONG_PTR_)value - (ULONG_PTR_)pbCode + (ULONG_PTR_)pbCodeBuf;
86 | }
87 | PBYTE_ ret = detour_gen_jmp_immediate((T1)pbCodeBuf, (T2)(ULONG_PTR_)newvalue);
88 |
89 | DetourMemoryOpWrapper *o = new DetourMemoryOpWrapper;
90 | o->pbCode = pbCode;
91 | o->iCodeSize = (int)(ret - (PBYTE_)pbCodeBuf);
92 | memcpy(o->rbCode, pbCodeBuf, sizeof(o->rbCode));
93 | push_op(o);
94 |
95 | ret = (PBYTE_)((ULONG_PTR_)ret - (ULONG_PTR_)pbCodeBuf + (ULONG_PTR_)pbCode);
96 | return ret;
97 | }
98 |
99 | template
100 | PBYTE_ detour_gen_jmp_immediate_(T1 pbCode, T2 ppPool, T3 pbJmpVal) {
101 | DETOUR_TRACE(("detour_gen_jmp_immediate_(%p, %p, %p)\n", pbCode, ppPool, pbJmpVal));
102 | #if !defined(_DARWIN)
103 | return detour_gen_jmp_immediate((T1)pbCode, (T2)ppPool, (T3)pbJmpVal);
104 | #endif
105 | if (is_trampoline((ULONG_PTR_)(pbCode))) return detour_gen_jmp_immediate((T1)pbCode, (T2)ppPool, (T3)pbJmpVal);
106 |
107 |
108 | if (ppPool) {
109 | DETOUR_TRACE(("detour_gen_jmp_immediate_: Warning, cannot handle ppPool cases!\n"));
110 | return detour_gen_jmp_immediate(pbCode, ppPool, pbJmpVal);
111 | }
112 |
113 | char _pbCodeBuf[2 * MAX_PAGE_SIZE + 0x100] = { 0 };
114 | char *pbCodeBuf = _pbCodeBuf + MAX_PAGE_SIZE - ((ULONG64_)(ULONG_PTR_)_pbCodeBuf & 0xfff) + ((ULONG64_)(ULONG_PTR_)pbCode & 0xfff);
115 | memcpy(pbCodeBuf, pbCode, MAX_PATCH_SIZE);
116 | ULONG_PTR_ newvalue = pbJmpVal;
117 | //if (pbJmpVal != nullptr) {
118 | // newvalue = (ULONG_PTR_)pbJmpVal - (ULONG_PTR_)pbCode + (ULONG_PTR_)pbCodeBuf;
119 | //}
120 | PBYTE_ ret = detour_gen_jmp_immediate((T1)pbCodeBuf, nullptr, (T3)newvalue);
121 |
122 | DetourMemoryOpWrapper *o = new DetourMemoryOpWrapper;
123 | o->pbCode = pbCode;
124 | o->iCodeSize = (int)(ret - (PBYTE_)pbCodeBuf);
125 | memcpy(o->rbCode, pbCodeBuf, sizeof(o->rbCode));
126 | push_op(o);
127 |
128 | ret = (PBYTE_)((ULONG_PTR_)ret - (ULONG_PTR_)pbCodeBuf + (ULONG_PTR_)pbCode);
129 | return ret;
130 | }
131 |
132 | template
133 | PBYTE_ detour_gen_brk_(T1 pbCode, T2 value) {
134 | DETOUR_TRACE(("detour_gen_brk_(%p, %p)\n", pbCode, value));
135 | #if !defined(_DARWIN)
136 | return detour_gen_brk((T1)pbCode, (T2)value);
137 | #endif
138 | if (is_trampoline((ULONG_PTR_)(pbCode))) return detour_gen_brk((T1)pbCode, (T2)value);
139 |
140 | char _pbCodeBuf[2 * MAX_PAGE_SIZE + 0x100] = { 0 };
141 | char *pbCodeBuf = _pbCodeBuf + MAX_PAGE_SIZE - ((ULONG64_)(ULONG_PTR_)_pbCodeBuf & 0xfff) + ((ULONG64_)(ULONG_PTR_)pbCode & 0xfff);
142 | memcpy(pbCodeBuf, pbCode, MAX_PATCH_SIZE);
143 | ULONG_PTR_ newvalue = 0;
144 | if (value != nullptr) {
145 | newvalue = (ULONG_PTR_)value - (ULONG_PTR_)pbCode + (ULONG_PTR_)pbCodeBuf;
146 | }
147 | PBYTE_ ret = detour_gen_brk((T1)pbCodeBuf, (T2)newvalue);
148 |
149 | DetourMemoryOpWrapper *o = new DetourMemoryOpWrapper;
150 | o->pbCode = pbCode;
151 | o->iCodeSize = (int)(ret - (PBYTE_)pbCodeBuf);
152 | memcpy(o->rbCode, pbCodeBuf, sizeof(o->rbCode));
153 | push_op(o);
154 | ret = (PBYTE_)((ULONG_PTR_)ret - (ULONG_PTR_)pbCodeBuf + (ULONG_PTR_)pbCode);
155 | return ret;
156 | }
157 |
158 |
159 | #define DetourTransactionCommit _DetourTransactionCommit
160 | #include "detours.cpp"
161 | #undef DetourTransactionCommit
162 |
163 | static BOOL is_trampoline(ULONG_PTR_ addr) {
164 | for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) {
165 | ULONG_PTR_ addrRegion = (ULONG_PTR_)pRegion;
166 | if ( addrRegion <= addr && addr < addrRegion + DETOUR_REGION_SIZE ) {
167 | return TRUE;
168 | }
169 | }
170 | return FALSE;
171 | }
172 |
173 |
174 | #include
175 |
176 | extern "C" {
177 |
178 | // struct DetourOperationWrapper {
179 | // DetourOperationWrapper *pNext;
180 | // PBYTE oldPbTarget;
181 | // PBYTE newPbTarget;
182 | // DWORD cbTarget;
183 | // DWORD flOld;
184 | // };
185 | LONG WINAPI DetourTransactionCommit() {
186 | // DetourOperationWrapper *ori_s_pPendingOperations = nullptr;
187 | // LONG ret = 0;
188 | // for (DetourOperation *o = s_pPendingOperations; o != nullptr;) {
189 | // DetourOperationWrapper *o_ = new DetourOperationWrapper;
190 | // o_->oldPbTarget = o->pbTarget;
191 | // o_->cbTarget = o->pTrampoline->pbRemain - o->pbTarget;
192 | // o_->newPbTarget = new BYTE[o_->cbTarget + 0x100];
193 | // memcpy(o_->newPbTarget, o_->oldPbTarget, o_->cbTarget);
194 | // o_->flOld = o->dwPerm;
195 | // if (!VirtualProtect(o_->oldPbTarget, o_->cbTarget, PAGE_READWRITE, &o_->flOld)) {
196 | // // wait for ret
197 | // ret = GetLastError();
198 | // delete o_;
199 | // break;
200 | // }
201 |
202 | // o_->pNext = ori_s_pPendingOperations;
203 | // ori_s_pPendingOperations = o_;
204 | // DETOUR_TRACE(("Before transaction commit: %p (%x)\n", o_->oldPbTarget, o_->cbTarget));
205 | // // o->pbTarget = o_->newPbTarget;
206 | // // o->pTrampoline->pbRemain = o_->newPbTarget + o_->cbTarget;
207 | // // o->pTrampoline->rbCodeIn
208 | // o = o->pNext;
209 | // }
210 | // if (!ret) {
211 | // ret = _DetourTransactionCommit();
212 | // DETOUR_TRACE(("Transaction Result: %d\n", ret));
213 | // } else {
214 | // DETOUR_TRACE(("Error During VirtualProtect prepare: %d\n", ret));
215 | // }
216 |
217 | // for (DetourOperationWrapper *o_ = ori_s_pPendingOperations; o_ != nullptr;) {
218 | // //if (!!memcmp(o_->oldPbTarget, o_->newPbTarget, o_->cbTarget)) {
219 | // // DETOUR_TRACE(("Applying After transaction commit: %p (%x) <- %p\n", o_->oldPbTarget, o_->cbTarget, o_->newPbTarget));
220 | // // CodePatch(o_->oldPbTarget, o_->newPbTarget, o_->cbTarget);
221 | // //}
222 | // DWORD flOld = 0;
223 | // if (!VirtualProtect(o_->oldPbTarget, o_->cbTarget, o_->flOld, &flOld)) {
224 | // // wait for ret
225 | // ret = GetLastError();
226 | // DETOUR_TRACE(("Failed to restore page permission for %p: error %d\n", o_->oldPbTarget, ret));
227 | // }
228 |
229 | // delete[] o_->newPbTarget;
230 | // DetourOperationWrapper *n_ = o_->pNext;
231 | // delete o_;
232 | // o_ = n_;
233 | // }
234 | // return ret;
235 | LONG ret = _DetourTransactionCommit();
236 | DetourMemoryOpWrapper *begin = nullptr;
237 | for (DetourMemoryOpWrapper *o = s_detoursMemoryOp; o != nullptr; ) {
238 | begin = o;
239 | o = o->pPrev;
240 | }
241 | for (DetourMemoryOpWrapper *o = begin; o != nullptr; ) {
242 | BYTE *rbCode = (BYTE *)o->rbCode;
243 | DETOUR_TRACE(("Applying Code Changes: %p\n", o->pbCode));
244 | DETOUR_TRACE(("detours: pbCode=%p: "
245 | "%02x %02x %02x %02x "
246 | "%02x %02x %02x %02x "
247 | "%02x %02x %02x %02x [after]\n",
248 | o->pbCode,
249 | rbCode[0], rbCode[1], rbCode[2], rbCode[3],
250 | rbCode[4], rbCode[5], rbCode[6], rbCode[7],
251 | rbCode[8], rbCode[9], rbCode[10], rbCode[11]));
252 | if (!CodePatch(o->pbCode, o->rbCode, o->iCodeSize/* sizeof(o->rbCode)*/))
253 | ret = GetLastError();
254 | DetourMemoryOpWrapper *n = o->pNext;
255 | delete o;
256 | o = n;
257 | }
258 | s_detoursMemoryOp = NULL;
259 | // Mark all of the regions as executable.
260 | // for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) {
261 | // DETOUR_TRACE(("Marking Trampolines as RX: %p\n", pRegion));
262 | // CodePatch(pRegion, NULL, DETOUR_REGION_SIZE);
263 | // }
264 | return ret;
265 | }
266 |
267 |
268 |
269 | }
270 |
--------------------------------------------------------------------------------
/Detours/src/detver.h:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Common version parameters.
4 | //
5 | // Microsoft Research Detours Package, Version 4.0.1
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 |
10 | #define _USING_V110_SDK71_ 1
11 | #include "winver.h"
12 | #if 0
13 | #include
14 | #include "detours.h"
15 | #else
16 | #ifndef DETOURS_STRINGIFY
17 | #define DETOURS_STRINGIFY_(x) #x
18 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
19 | #endif
20 |
21 | #define VER_FILEFLAGSMASK 0x3fL
22 | #define VER_FILEFLAGS 0x0L
23 | #define VER_FILEOS 0x00040004L
24 | #define VER_FILETYPE 0x00000002L
25 | #define VER_FILESUBTYPE 0x00000000L
26 | #endif
27 | #define VER_DETOURS_BITS DETOURS_STRINGIFY(DETOURS_BITS)
28 |
--------------------------------------------------------------------------------
/Detours/src/disolarm.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_ARM_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/Detours/src/disolarm64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_ARM64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/Detours/src/disolia64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_IA64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/Detours/src/disolx64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_X64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/Detours/src/disolx86.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_X86_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/Detours/src/mem_patch.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #define DETOURS_INTERNAL
4 | #include "detours.h"
5 |
6 |
7 | #define patch_min(a,b) ((a) < (b) ? (a) : (b))
8 |
9 | #if defined(_DARWIN)
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | void ClearCache(void *start, void *end) {
19 | return sys_icache_invalidate(start, (uint64_t)end - (uint64_t)start);
20 | }
21 |
22 |
23 |
24 | #define KERN_RETURN_ERROR(kr, failure) \
25 | do { \
26 | if (kr != KERN_SUCCESS) { \
27 | return failure; \
28 | } \
29 | } while (0);
30 |
31 | #include
32 | typedef uintptr_t addr_t;
33 | #if defined(TARGET_ARCH_ARM64)
34 | #define SYS_mprotect 74
35 | int mprotect_impl(void *addr, size_t len, int prot) {
36 | int ret = 0;
37 | __asm__ __volatile__("mov x16, %[_SYS_mprotect]\n"
38 | "svc 0x80\n"
39 | "mov %w[_ret], w0\n"
40 | "add %w[_ret], %w[_ret], #0x0\n"
41 | : [_ret] "=r"(ret)
42 | : [_SYS_mprotect] "n"(SYS_mprotect)
43 | :);
44 | return ret;
45 | }
46 | #endif
47 |
48 | #define ALIGN_FLOOR(address, range) ((uintptr_t)address & ~((uintptr_t)range - 1))
49 | #define ALIGN_CEIL(address, range) (((uintptr_t)address + (uintptr_t)range - 1) & ~((uintptr_t)range - 1))
50 | int _CodePatchPage(void *address, uint8_t *buffer, uint32_t buffer_size) {
51 | if (address == nullptr || buffer == nullptr || buffer_size == 0) {
52 | return -1;
53 | }
54 |
55 | size_t page_size = PAGE_SIZE;
56 | addr_t patch_page = ALIGN_FLOOR(address, page_size);
57 |
58 | // cross over page
59 | if ((addr_t)address + buffer_size > patch_page + page_size) {
60 | void *address_a = address;
61 | uint8_t *buffer_a = buffer;
62 | uint32_t buffer_size_a = (patch_page + page_size - (addr_t)address);
63 | auto ret = _CodePatchPage(address_a, buffer_a, buffer_size_a);
64 | if (ret == -1) {
65 | return ret;
66 | }
67 |
68 | void *address_b = (void *)((addr_t)address + buffer_size_a);
69 | uint8_t *buffer_b = buffer + buffer_size_a;
70 | uint32_t buffer_size_b = buffer_size - buffer_size_a;
71 | ret = _CodePatchPage(address_b, buffer_b, buffer_size_b);
72 | return ret;
73 | }
74 |
75 | addr_t remap_dest_page = patch_page;
76 | mach_vm_address_t remap_dummy_page = 0;
77 |
78 | auto self_task = mach_task_self();
79 | kern_return_t kr;
80 |
81 | int orig_prot = 0;
82 | int orig_max_prot = 0;
83 | int share_mode = 0;
84 | int is_enable_remap = -1;
85 | if (is_enable_remap == -1) {
86 | auto get_region_info = [&](addr_t region_start) -> void {
87 | vm_region_submap_info_64 region_submap_info;
88 | mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
89 | mach_vm_address_t addr = region_start;
90 | mach_vm_size_t size = 0;
91 | natural_t depth = 0;
92 | while (1) {
93 | kr = mach_vm_region_recurse(mach_task_self(), (mach_vm_address_t *)&addr, (mach_vm_size_t *)&size, &depth,
94 | (vm_region_recurse_info_t)®ion_submap_info, &count);
95 | if (region_submap_info.is_submap) {
96 | depth++;
97 | } else {
98 | orig_prot = region_submap_info.protection;
99 | orig_max_prot = region_submap_info.max_protection;
100 | share_mode = region_submap_info.share_mode;
101 | return;
102 | }
103 | }
104 | };
105 | get_region_info(remap_dest_page);
106 | if (orig_max_prot != 5 && share_mode != 2) {
107 | is_enable_remap = 1;
108 | } else {
109 | is_enable_remap = 0;
110 | }
111 | }
112 | if (is_enable_remap == 1) {
113 | addr_t remap_dummy_page = 0;
114 | {
115 | kr = mach_vm_allocate(self_task, (mach_vm_address_t *)&remap_dummy_page, page_size, VM_FLAGS_ANYWHERE);
116 | KERN_RETURN_ERROR(kr, -1);
117 |
118 | memcpy((void *)remap_dummy_page, (void *)patch_page, page_size);
119 |
120 | int offset = (int)((addr_t)address - patch_page);
121 | memcpy((void *)(remap_dummy_page + offset), buffer, buffer_size);
122 |
123 | kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_EXECUTE);
124 | KERN_RETURN_ERROR(kr, -1);
125 | }
126 |
127 | vm_prot_t prot, max_prot;
128 | kr = mach_vm_remap(self_task, (mach_vm_address_t *)&remap_dest_page, page_size, 0,
129 | VM_FLAGS_OVERWRITE | VM_FLAGS_FIXED, self_task, remap_dummy_page, true, &prot, &max_prot,
130 | VM_INHERIT_COPY);
131 | KERN_RETURN_ERROR(kr, -1);
132 |
133 | kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size);
134 | KERN_RETURN_ERROR(kr, -1);
135 | } else {
136 |
137 | if (0) {
138 | {
139 | auto kr = mach_vm_allocate(self_task, &remap_dummy_page, page_size, VM_FLAGS_ANYWHERE);
140 | KERN_RETURN_ERROR(kr, -1);
141 |
142 | kr = mach_vm_deallocate(self_task, remap_dummy_page, page_size);
143 | KERN_RETURN_ERROR(kr, -1);
144 | }
145 |
146 | vm_prot_t prot, max_prot;
147 | kr = mach_vm_remap(self_task, &remap_dummy_page, page_size, 0, VM_FLAGS_ANYWHERE, self_task, remap_dest_page,
148 | false, &prot, &max_prot, VM_INHERIT_SHARE);
149 | KERN_RETURN_ERROR(kr, -1);
150 |
151 | kr = mach_vm_protect(self_task, remap_dummy_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE);
152 | // the kr always return KERN_PROTECTION_FAILURE
153 | kr = KERN_PROTECTION_FAILURE;
154 |
155 | memcpy((void *)(remap_dummy_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size);
156 | }
157 |
158 | static __typeof(vm_protect) *vm_protect_impl = vm_protect;
159 |
160 | {
161 | kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
162 | KERN_RETURN_ERROR(kr, -1);
163 |
164 | memcpy((void *)(patch_page + ((uint64_t)address - remap_dest_page)), buffer, buffer_size);
165 |
166 | kr = vm_protect_impl(self_task, remap_dest_page, page_size, false, 5);
167 | KERN_RETURN_ERROR(kr, -1);
168 |
169 | ClearCache((void *)remap_dest_page, (void *)((addr_t)remap_dest_page + page_size));
170 | }
171 | }
172 | ClearCache(address, (void*)((addr_t)address + buffer_size));
173 |
174 |
175 | return 0;
176 | }
177 |
178 | #elif defined(_LINUX)
179 |
180 | BOOL _CodePatchPage(void *target, void *buffer, size_t count) {
181 | DWORD flOld = 0;
182 | if (!VirtualProtect(target, count, PAGE_EXECUTE_READWRITE, &flOld)) {
183 | return FALSE;
184 | }
185 | memcpy(target, buffer, count);
186 | if (!VirtualProtect(target, count, flOld, &flOld)) {
187 | return FALSE;
188 | }
189 | return TRUE;
190 | }
191 |
192 | #elif defined(_WIN32)
193 |
194 | #include
195 |
196 | BOOL _CodePatchPage(void *target, void *buffer, size_t count) {
197 | DWORD flOld = 0;
198 | if (!VirtualProtect(target, count, PAGE_EXECUTE_READWRITE, &flOld)) {
199 | return FALSE;
200 | }
201 | memcpy(target, buffer, count);
202 | if (!VirtualProtect(target, count, flOld, &flOld)) {
203 | return FALSE;
204 | }
205 | return TRUE;
206 | }
207 |
208 | #endif
209 |
210 |
211 | #if !defined(_WIN32)
212 | extern "C" {
213 |
214 | static int g_lastError = 0;
215 |
216 | void SetLastError(int err) {
217 | g_lastError = err;
218 | }
219 |
220 | int GetLastError() {
221 | return g_lastError;
222 | }
223 |
224 | }
225 | #endif
226 |
227 |
228 | #include
229 |
230 | extern "C" {
231 |
232 | BOOL CodePatch(void *address, void *buffer, size_t buffer_size) {
233 | std::vector _buffer;
234 | if (!buffer) {
235 | _buffer.resize(buffer_size);
236 | buffer = _buffer.data();
237 | memcpy(buffer, address, buffer_size);
238 | }
239 | char * start_addr = (char *)address;
240 | char * startPage = (char *)((uintptr_t)(start_addr + getpagesize()) & ~(getpagesize() - 1));
241 | BOOL ret = TRUE;
242 | if (!(ret = _CodePatchPage(start_addr, (uint8_t *)buffer, patch_min(startPage - start_addr, (int)buffer_size)))) {
243 | return ret;
244 | }
245 | uint32_t bufloc = (uint32_t)patch_min(startPage - start_addr, (int)buffer_size);
246 | while (bufloc < buffer_size) {
247 | uint32_t nextbufloc = (uint32_t)patch_min(bufloc + 0x1000, buffer_size);
248 | if (!(ret = _CodePatchPage(start_addr + bufloc,(uint8_t *)( (char *)buffer + bufloc), nextbufloc - bufloc))) {
249 | return ret;
250 | }
251 | bufloc = nextbufloc;
252 | }
253 | return ret;
254 | }
255 |
256 | }
257 |
--------------------------------------------------------------------------------
/Detours/src/mem_patch.h:
--------------------------------------------------------------------------------
1 | extern "C" {
2 |
3 | BOOL CodePatch(void *address, void *buffer, size_t buffer_size);
4 |
5 | }
--------------------------------------------------------------------------------
/Detours/src/modules.cpp:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Module Enumeration Functions (modules.cpp of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 4.0.1
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 | // Module enumeration functions.
10 | //
11 |
12 | // #define DETOUR_DEBUG 1
13 | #define DETOURS_INTERNAL
14 | #include "detours.h"
15 |
16 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
17 | #error detours.h version mismatch
18 | #endif
19 |
20 | #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
21 | #define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
22 |
23 | //////////////////////////////////////////////////////////////////////////////
24 | //
25 | const GUID DETOUR_EXE_RESTORE_GUID = {
26 | 0xbda26f34, 0xbc82, 0x4829,
27 | { 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
28 |
29 | //////////////////////////////////////////////////////////////////////////////
30 | //
31 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
32 | {
33 | static DETOUR_SYM_INFO symInfo;
34 | static PDETOUR_SYM_INFO pSymInfo = NULL;
35 | static BOOL failed = false;
36 |
37 | if (failed) {
38 | return NULL;
39 | }
40 | if (pSymInfo != NULL) {
41 | return pSymInfo;
42 | }
43 |
44 | ZeroMemory(&symInfo, sizeof(symInfo));
45 | // Create a real handle to the process.
46 | #if 0
47 | DuplicateHandle(GetCurrentProcess(),
48 | GetCurrentProcess(),
49 | GetCurrentProcess(),
50 | &symInfo.hProcess,
51 | 0,
52 | FALSE,
53 | DUPLICATE_SAME_ACCESS);
54 | #else
55 | symInfo.hProcess = GetCurrentProcess();
56 | #endif
57 |
58 | symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0);
59 | if (symInfo.hDbgHelp == NULL) {
60 | abort:
61 | failed = true;
62 | if (symInfo.hDbgHelp != NULL) {
63 | FreeLibrary(symInfo.hDbgHelp);
64 | }
65 | symInfo.pfImagehlpApiVersionEx = NULL;
66 | symInfo.pfSymInitialize = NULL;
67 | symInfo.pfSymSetOptions = NULL;
68 | symInfo.pfSymGetOptions = NULL;
69 | symInfo.pfSymLoadModule64 = NULL;
70 | symInfo.pfSymGetModuleInfo64 = NULL;
71 | symInfo.pfSymFromName = NULL;
72 | return NULL;
73 | }
74 |
75 | symInfo.pfImagehlpApiVersionEx
76 | = (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
77 | "ImagehlpApiVersionEx");
78 | symInfo.pfSymInitialize
79 | = (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
80 | symInfo.pfSymSetOptions
81 | = (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
82 | symInfo.pfSymGetOptions
83 | = (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
84 | symInfo.pfSymLoadModule64
85 | = (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
86 | symInfo.pfSymGetModuleInfo64
87 | = (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
88 | symInfo.pfSymFromName
89 | = (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
90 |
91 | API_VERSION av;
92 | ZeroMemory(&av, sizeof(av));
93 | av.MajorVersion = API_VERSION_NUMBER;
94 |
95 | if (symInfo.pfImagehlpApiVersionEx == NULL ||
96 | symInfo.pfSymInitialize == NULL ||
97 | symInfo.pfSymLoadModule64 == NULL ||
98 | symInfo.pfSymGetModuleInfo64 == NULL ||
99 | symInfo.pfSymFromName == NULL) {
100 | goto abort;
101 | }
102 |
103 | symInfo.pfImagehlpApiVersionEx(&av);
104 | if (av.MajorVersion < API_VERSION_NUMBER) {
105 | goto abort;
106 | }
107 |
108 | if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
109 | // We won't retry the initialize if it fails.
110 | goto abort;
111 | }
112 |
113 | if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
114 | DWORD dw = symInfo.pfSymGetOptions();
115 |
116 | dw &= ~(SYMOPT_CASE_INSENSITIVE |
117 | SYMOPT_UNDNAME |
118 | SYMOPT_DEFERRED_LOADS |
119 | 0);
120 | dw |= (
121 | #if defined(SYMOPT_EXACT_SYMBOLS)
122 | SYMOPT_EXACT_SYMBOLS |
123 | #endif
124 | #if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
125 | SYMOPT_NO_UNQUALIFIED_LOADS |
126 | #endif
127 | SYMOPT_DEFERRED_LOADS |
128 | #if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
129 | SYMOPT_FAIL_CRITICAL_ERRORS |
130 | #endif
131 | #if defined(SYMOPT_INCLUDE_32BIT_MODULES)
132 | SYMOPT_INCLUDE_32BIT_MODULES |
133 | #endif
134 | 0);
135 | symInfo.pfSymSetOptions(dw);
136 | }
137 |
138 | pSymInfo = &symInfo;
139 | return pSymInfo;
140 | }
141 |
142 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
143 | _In_ LPCSTR pszFunction)
144 | {
145 | if (pszFunction == NULL) {
146 | SetLastError(ERROR_INVALID_PARAMETER);
147 | return NULL;
148 | }
149 |
150 | /////////////////////////////////////////////// First, try GetProcAddress.
151 | //
152 | #pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
153 | HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0);
154 | if (hModule == NULL) {
155 | return NULL;
156 | }
157 |
158 | PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
159 | if (pbCode) {
160 | return pbCode;
161 | }
162 |
163 | ////////////////////////////////////////////////////// Then try ImageHelp.
164 | //
165 | DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
166 | PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
167 | if (pSymInfo == NULL) {
168 | DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n",
169 | GetLastError()));
170 | return NULL;
171 | }
172 |
173 | if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
174 | (PCHAR)pszModule, NULL,
175 | (DWORD64)hModule, 0) == 0) {
176 | if (ERROR_SUCCESS != GetLastError()) {
177 | DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n",
178 | pSymInfo->hProcess, GetLastError()));
179 | return NULL;
180 | }
181 | }
182 |
183 | HRESULT hrRet;
184 | CHAR szFullName[512];
185 | IMAGEHLP_MODULE64 modinfo;
186 | ZeroMemory(&modinfo, sizeof(modinfo));
187 | modinfo.SizeOfStruct = sizeof(modinfo);
188 | if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
189 | DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %lu\n",
190 | pSymInfo->hProcess, hModule, GetLastError()));
191 | return NULL;
192 | }
193 |
194 | hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
195 | if (FAILED(hrRet)) {
196 | DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
197 | return NULL;
198 | }
199 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
200 | if (FAILED(hrRet)) {
201 | DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
202 | return NULL;
203 | }
204 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
205 | if (FAILED(hrRet)) {
206 | DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
207 | return NULL;
208 | }
209 |
210 | struct CFullSymbol : SYMBOL_INFO {
211 | CHAR szRestOfName[512];
212 | } symbol;
213 | ZeroMemory(&symbol, sizeof(symbol));
214 | //symbol.ModBase = (ULONG64)hModule;
215 | symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
216 | #ifdef DBHLPAPI
217 | symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
218 | #else
219 | symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
220 | #endif
221 |
222 | if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
223 | DETOUR_TRACE(("SymFromName(%hs) failed: %lu\n", szFullName, GetLastError()));
224 | return NULL;
225 | }
226 |
227 | #if defined(DETOURS_IA64)
228 | // On the IA64, we get a raw code pointer from the symbol engine
229 | // and have to convert it to a wrapped [code pointer, global pointer].
230 | //
231 | PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
232 | PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
233 |
234 | pldSymbol->EntryPoint = symbol.Address;
235 | pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
236 | return (PBYTE)pldSymbol;
237 | #elif defined(DETOURS_ARM)
238 | // On the ARM, we get a raw code pointer, which we must convert into a
239 | // valied Thumb2 function pointer.
240 | return DETOURS_PBYTE_TO_PFUNC(symbol.Address);
241 | #else
242 | return (PBYTE)symbol.Address;
243 | #endif
244 | }
245 |
246 | //////////////////////////////////////////////////// Module Image Functions.
247 | //
248 |
249 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
250 | {
251 | PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
252 |
253 | MEMORY_BASIC_INFORMATION mbi;
254 | ZeroMemory(&mbi, sizeof(mbi));
255 |
256 | // Find the next memory region that contains a mapped PE image.
257 | //
258 | for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
259 | if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) {
260 | break;
261 | }
262 |
263 | // Skip uncommitted regions and guard pages.
264 | //
265 | if ((mbi.State != MEM_COMMIT) ||
266 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
267 | (mbi.Protect & PAGE_GUARD)) {
268 | continue;
269 | }
270 |
271 | __try {
272 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
273 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
274 | (DWORD)pDosHeader->e_lfanew > mbi.RegionSize ||
275 | (DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) {
276 | continue;
277 | }
278 |
279 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
280 | pDosHeader->e_lfanew);
281 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
282 | continue;
283 | }
284 |
285 | SetLastError(NO_ERROR);
286 | return (HMODULE)pDosHeader;
287 | }
288 | #pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
289 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
290 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
291 | continue;
292 | }
293 | }
294 | return NULL;
295 | }
296 |
297 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
298 | {
299 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
300 | if (hModule == NULL) {
301 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
302 | }
303 |
304 | __try {
305 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
306 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
307 | SetLastError(ERROR_BAD_EXE_FORMAT);
308 | return NULL;
309 | }
310 |
311 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
312 | pDosHeader->e_lfanew);
313 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
314 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
315 | return NULL;
316 | }
317 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
318 | SetLastError(ERROR_EXE_MARKED_INVALID);
319 | return NULL;
320 | }
321 |
322 | PDETOUR_CLR_HEADER pClrHeader = NULL;
323 | if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
324 | if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
325 | ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) {
326 | pClrHeader = (PDETOUR_CLR_HEADER)
327 | (((PBYTE)pDosHeader)
328 | + ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
329 | }
330 | }
331 | else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
332 | if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
333 | ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) {
334 | pClrHeader = (PDETOUR_CLR_HEADER)
335 | (((PBYTE)pDosHeader)
336 | + ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
337 | }
338 | }
339 |
340 | if (pClrHeader != NULL) {
341 | // For MSIL assemblies, we want to use the _Cor entry points.
342 |
343 | HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL");
344 | if (hClr == NULL) {
345 | return NULL;
346 | }
347 |
348 | SetLastError(NO_ERROR);
349 | return (PVOID)GetProcAddress(hClr, "_CorExeMain");
350 | }
351 |
352 | SetLastError(NO_ERROR);
353 |
354 | // Pure resource DLLs have neither an entry point nor CLR information
355 | // so handle them by returning NULL (LastError is NO_ERROR)
356 | if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) {
357 | return NULL;
358 | }
359 |
360 | return ((PBYTE)pDosHeader) +
361 | pNtHeader->OptionalHeader.AddressOfEntryPoint;
362 | }
363 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
364 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
365 | SetLastError(ERROR_EXE_MARKED_INVALID);
366 | return NULL;
367 | }
368 | }
369 |
370 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule)
371 | {
372 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
373 | if (hModule == NULL) {
374 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
375 | }
376 |
377 | __try {
378 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
379 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
380 | SetLastError(ERROR_BAD_EXE_FORMAT);
381 | return NULL;
382 | }
383 |
384 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
385 | pDosHeader->e_lfanew);
386 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
387 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
388 | return NULL;
389 | }
390 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
391 | SetLastError(ERROR_EXE_MARKED_INVALID);
392 | return NULL;
393 | }
394 | SetLastError(NO_ERROR);
395 |
396 | return (pNtHeader->OptionalHeader.SizeOfImage);
397 | }
398 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
399 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
400 | SetLastError(ERROR_EXE_MARKED_INVALID);
401 | return NULL;
402 | }
403 | }
404 |
405 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr)
406 | {
407 | MEMORY_BASIC_INFORMATION mbi;
408 | ZeroMemory(&mbi, sizeof(mbi));
409 |
410 | __try {
411 | if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) {
412 | SetLastError(ERROR_BAD_EXE_FORMAT);
413 | return NULL;
414 | }
415 |
416 | // Skip uncommitted regions and guard pages.
417 | //
418 | if ((mbi.State != MEM_COMMIT) ||
419 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
420 | (mbi.Protect & PAGE_GUARD)) {
421 | SetLastError(ERROR_BAD_EXE_FORMAT);
422 | return NULL;
423 | }
424 |
425 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
426 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
427 | SetLastError(ERROR_BAD_EXE_FORMAT);
428 | return NULL;
429 | }
430 |
431 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
432 | pDosHeader->e_lfanew);
433 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
434 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
435 | return NULL;
436 | }
437 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
438 | SetLastError(ERROR_EXE_MARKED_INVALID);
439 | return NULL;
440 | }
441 | SetLastError(NO_ERROR);
442 |
443 | return (HMODULE)pDosHeader;
444 | }
445 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
446 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
447 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
448 | return NULL;
449 | }
450 | }
451 |
452 |
453 | static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr)
454 | {
455 | if (raddr != NULL) {
456 | return ((PBYTE)pDosHeader) + raddr;
457 | }
458 | return NULL;
459 | }
460 |
461 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
462 | _In_opt_ PVOID pContext,
463 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
464 | {
465 | if (pfExport == NULL) {
466 | SetLastError(ERROR_INVALID_PARAMETER);
467 | return FALSE;
468 | }
469 |
470 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
471 | if (hModule == NULL) {
472 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
473 | }
474 |
475 | __try {
476 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
477 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
478 | SetLastError(ERROR_BAD_EXE_FORMAT);
479 | return NULL;
480 | }
481 |
482 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
483 | pDosHeader->e_lfanew);
484 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
485 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
486 | return FALSE;
487 | }
488 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
489 | SetLastError(ERROR_EXE_MARKED_INVALID);
490 | return FALSE;
491 | }
492 |
493 | PIMAGE_EXPORT_DIRECTORY pExportDir
494 | = (PIMAGE_EXPORT_DIRECTORY)
495 | RvaAdjust(pDosHeader,
496 | pNtHeader->OptionalHeader
497 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
498 |
499 | if (pExportDir == NULL) {
500 | SetLastError(ERROR_EXE_MARKED_INVALID);
501 | return FALSE;
502 | }
503 |
504 | PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader
505 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
506 | PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
507 | PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
508 | PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
509 |
510 | for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
511 | PBYTE pbCode = (pdwFunctions != NULL)
512 | ? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
513 | PCHAR pszName = NULL;
514 |
515 | // if the pointer is in the export region, then it is a forwarder.
516 | if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) {
517 | pbCode = NULL;
518 | }
519 |
520 | for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
521 | if (pwOrdinals[n] == nFunc) {
522 | pszName = (pdwNames != NULL)
523 | ? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
524 | break;
525 | }
526 | }
527 | ULONG nOrdinal = pExportDir->Base + nFunc;
528 |
529 | if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
530 | break;
531 | }
532 | }
533 | SetLastError(NO_ERROR);
534 | return TRUE;
535 | }
536 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
537 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
538 | SetLastError(ERROR_EXE_MARKED_INVALID);
539 | return NULL;
540 | }
541 | }
542 |
543 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
544 | _In_opt_ PVOID pContext,
545 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
546 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc)
547 | {
548 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
549 | if (hModule == NULL) {
550 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
551 | }
552 |
553 | __try {
554 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
555 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
556 | SetLastError(ERROR_BAD_EXE_FORMAT);
557 | return FALSE;
558 | }
559 |
560 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
561 | pDosHeader->e_lfanew);
562 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
563 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
564 | return FALSE;
565 | }
566 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
567 | SetLastError(ERROR_EXE_MARKED_INVALID);
568 | return FALSE;
569 | }
570 |
571 | PIMAGE_IMPORT_DESCRIPTOR iidp
572 | = (PIMAGE_IMPORT_DESCRIPTOR)
573 | RvaAdjust(pDosHeader,
574 | pNtHeader->OptionalHeader
575 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
576 |
577 | if (iidp == NULL) {
578 | SetLastError(ERROR_EXE_MARKED_INVALID);
579 | return FALSE;
580 | }
581 |
582 | for (; iidp->OriginalFirstThunk != 0; iidp++) {
583 |
584 | PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
585 | if (pszName == NULL) {
586 | SetLastError(ERROR_EXE_MARKED_INVALID);
587 | return FALSE;
588 | }
589 |
590 | PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
591 | RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
592 | PVOID * pAddrs = (PVOID *)
593 | RvaAdjust(pDosHeader, iidp->FirstThunk);
594 |
595 | HMODULE hFile = DetourGetContainingModule(pAddrs[0]);
596 |
597 | if (pfImportFile != NULL) {
598 | if (!pfImportFile(pContext, hFile, pszName)) {
599 | break;
600 | }
601 | }
602 |
603 | DWORD nNames = 0;
604 | if (pThunks) {
605 | for (; pThunks[nNames].u1.Ordinal; nNames++) {
606 | DWORD nOrdinal = 0;
607 | PCSTR pszFunc = NULL;
608 |
609 | if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
610 | nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
611 | }
612 | else {
613 | pszFunc = (PCSTR)RvaAdjust(pDosHeader,
614 | (DWORD)pThunks[nNames].u1.AddressOfData + 2);
615 | }
616 |
617 | if (pfImportFunc != NULL) {
618 | if (!pfImportFunc(pContext,
619 | nOrdinal,
620 | pszFunc,
621 | &pAddrs[nNames])) {
622 | break;
623 | }
624 | }
625 | }
626 | if (pfImportFunc != NULL) {
627 | pfImportFunc(pContext, 0, NULL, NULL);
628 | }
629 | }
630 | }
631 | if (pfImportFile != NULL) {
632 | pfImportFile(pContext, NULL, NULL);
633 | }
634 | SetLastError(NO_ERROR);
635 | return TRUE;
636 | }
637 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
638 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
639 | SetLastError(ERROR_EXE_MARKED_INVALID);
640 | return FALSE;
641 | }
642 | }
643 |
644 | // Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex".
645 | struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT
646 | {
647 | PVOID pContext;
648 | PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc;
649 | };
650 |
651 | // Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx
652 | // for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on.
653 |
654 | static
655 | BOOL
656 | CALLBACK
657 | DetourEnumerateImportsThunk(_In_ PVOID VoidContext,
658 | _In_ DWORD nOrdinal,
659 | _In_opt_ PCSTR pszFunc,
660 | _In_opt_ PVOID* ppvFunc)
661 | {
662 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const
663 | pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext;
664 | return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL);
665 | }
666 |
667 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
668 | _In_opt_ PVOID pContext,
669 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
670 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
671 | {
672 | if (pfImportFile == NULL || pfImportFunc == NULL) {
673 | SetLastError(ERROR_INVALID_PARAMETER);
674 | return FALSE;
675 | }
676 |
677 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
678 |
679 | return DetourEnumerateImportsEx(hModule,
680 | (PVOID)&context,
681 | pfImportFile,
682 | &DetourEnumerateImportsThunk);
683 | }
684 |
685 | static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
686 | {
687 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
688 | if (hModule == NULL) {
689 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
690 | }
691 |
692 | __try {
693 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
694 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
695 | SetLastError(ERROR_BAD_EXE_FORMAT);
696 | return NULL;
697 | }
698 |
699 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
700 | pDosHeader->e_lfanew);
701 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
702 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
703 | return NULL;
704 | }
705 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
706 | SetLastError(ERROR_EXE_MARKED_INVALID);
707 | return NULL;
708 | }
709 |
710 | PIMAGE_SECTION_HEADER pSectionHeaders
711 | = (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
712 | + sizeof(pNtHeader->Signature)
713 | + sizeof(pNtHeader->FileHeader)
714 | + pNtHeader->FileHeader.SizeOfOptionalHeader);
715 |
716 | for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
717 | if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
718 | if (pSectionHeaders[n].VirtualAddress == 0 ||
719 | pSectionHeaders[n].SizeOfRawData == 0) {
720 |
721 | break;
722 | }
723 |
724 | PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
725 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
726 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
727 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
728 |
729 | break;
730 | }
731 |
732 | if (pHeader->nDataOffset == 0) {
733 | pHeader->nDataOffset = pHeader->cbHeaderSize;
734 | }
735 | SetLastError(NO_ERROR);
736 | return (PBYTE)pHeader;
737 | }
738 | }
739 | SetLastError(ERROR_EXE_MARKED_INVALID);
740 | return NULL;
741 | }
742 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
743 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
744 | SetLastError(ERROR_EXE_MARKED_INVALID);
745 | return NULL;
746 | }
747 | }
748 |
749 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule)
750 | {
751 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
752 | if (pBinary == NULL) {
753 | // Error set by GetPayloadSectionFromModule.
754 | return 0;
755 | }
756 |
757 | __try {
758 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
759 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
760 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
761 |
762 | SetLastError(ERROR_INVALID_HANDLE);
763 | return 0;
764 | }
765 | SetLastError(NO_ERROR);
766 | return pHeader->cbDataSize;
767 | }
768 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
769 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
770 | SetLastError(ERROR_INVALID_HANDLE);
771 | return 0;
772 | }
773 | }
774 |
775 | _Writable_bytes_(*pcbData)
776 | _Readable_bytes_(*pcbData)
777 | _Success_(return != NULL)
778 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
779 | _In_ REFGUID rguid,
780 | _Out_opt_ DWORD *pcbData)
781 | {
782 | PBYTE pbData = NULL;
783 | if (pcbData) {
784 | *pcbData = 0;
785 | }
786 |
787 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
788 | if (pBinary == NULL) {
789 | // Error set by GetPayloadSectionFromModule.
790 | return NULL;
791 | }
792 |
793 | __try {
794 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
795 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
796 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
797 |
798 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
799 | return NULL;
800 | }
801 |
802 | PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
803 | PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
804 |
805 | for (pbData = pbBeg; pbData < pbEnd;) {
806 | DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
807 |
808 | if (DetourAreSameGuid(pSection->guid, rguid)) {
809 | if (pcbData) {
810 | *pcbData = pSection->cbBytes - sizeof(*pSection);
811 | }
812 | SetLastError(NO_ERROR);
813 | return (PBYTE)(pSection + 1);
814 | }
815 |
816 | pbData = (PBYTE)pSection + pSection->cbBytes;
817 | }
818 | SetLastError(ERROR_INVALID_HANDLE);
819 | return NULL;
820 | }
821 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
822 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
823 | SetLastError(ERROR_INVALID_HANDLE);
824 | return NULL;
825 | }
826 | }
827 |
828 | _Writable_bytes_(*pcbData)
829 | _Readable_bytes_(*pcbData)
830 | _Success_(return != NULL)
831 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
832 | _Out_opt_ DWORD *pcbData)
833 | {
834 | for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
835 | PVOID pvData;
836 |
837 | pvData = DetourFindPayload(hMod, rguid, pcbData);
838 | if (pvData != NULL) {
839 | return pvData;
840 | }
841 | }
842 | SetLastError(ERROR_MOD_NOT_FOUND);
843 | return NULL;
844 | }
845 |
846 | BOOL WINAPI DetourFreePayload(_In_ PVOID pvData)
847 | {
848 | BOOL fSucceeded = FALSE;
849 |
850 | // If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess.
851 | HMODULE hModule = DetourGetContainingModule(pvData);
852 | DETOUR_ASSERT(hModule != NULL);
853 | if (hModule != NULL) {
854 | fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE);
855 | DETOUR_ASSERT(fSucceeded);
856 | if (fSucceeded) {
857 | hModule = NULL;
858 | }
859 | }
860 |
861 | return fSucceeded;
862 | }
863 |
864 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
865 | _In_ DWORD cbData)
866 | {
867 | PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
868 |
869 | if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
870 | SetLastError(ERROR_BAD_EXE_FORMAT);
871 | return FALSE;
872 | }
873 |
874 | DWORD dwPermIdh = ~0u;
875 | DWORD dwPermInh = ~0u;
876 | DWORD dwPermClr = ~0u;
877 | DWORD dwIgnore;
878 | BOOL fSucceeded = FALSE;
879 | BOOL fUpdated32To64 = FALSE;
880 |
881 | if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
882 | // If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
883 | // that.
884 | fUpdated32To64 = TRUE;
885 | }
886 |
887 | if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh,
888 | PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
889 | if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh,
890 | PAGE_EXECUTE_READWRITE, &dwPermInh)) {
891 |
892 | CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
893 | CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
894 |
895 | if (pder->pclr != NULL && !fUpdated32To64) {
896 | if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
897 | PAGE_EXECUTE_READWRITE, &dwPermClr)) {
898 | CopyMemory(pder->pclr, &pder->clr, pder->cbclr);
899 | VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore);
900 | fSucceeded = TRUE;
901 | }
902 | }
903 | else {
904 | fSucceeded = TRUE;
905 | }
906 | VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore);
907 | }
908 | VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
909 | }
910 | // Delete the payload after successful recovery to prevent repeated restore
911 | if (fSucceeded) {
912 | DetourFreePayload(pder);
913 | pder = NULL;
914 | }
915 | return fSucceeded;
916 | }
917 |
918 | BOOL WINAPI DetourRestoreAfterWith()
919 | {
920 | PVOID pvData;
921 | DWORD cbData;
922 |
923 | pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData);
924 |
925 | if (pvData != NULL && cbData != 0) {
926 | return DetourRestoreAfterWithEx(pvData, cbData);
927 | }
928 | SetLastError(ERROR_MOD_NOT_FOUND);
929 | return FALSE;
930 | }
931 |
932 | // End of File
933 |
--------------------------------------------------------------------------------
/Detours/src/uimports.cpp:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Add DLLs to a module import table (uimports.cpp of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 4.0.1
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 | // Note that this file is included into creatwth.cpp one or more times
10 | // (once for each supported module format).
11 | //
12 |
13 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
14 | #error detours.h version mismatch
15 | #endif
16 |
17 | // UpdateImports32 aka UpdateImports64
18 | static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
19 | HMODULE hModule,
20 | __in_ecount(nDlls) LPCSTR *plpDlls,
21 | DWORD nDlls)
22 | {
23 | BOOL fSucceeded = FALSE;
24 | DWORD cbNew = 0;
25 |
26 | BYTE * pbNew = NULL;
27 | DWORD i;
28 | SIZE_T cbRead;
29 | DWORD n;
30 |
31 | PBYTE pbModule = (PBYTE)hModule;
32 |
33 | IMAGE_DOS_HEADER idh;
34 | ZeroMemory(&idh, sizeof(idh));
35 | if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
36 | || cbRead < sizeof(idh)) {
37 |
38 | DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
39 | pbModule, pbModule + sizeof(idh), GetLastError()));
40 |
41 | finish:
42 | if (pbNew != NULL) {
43 | delete[] pbNew;
44 | pbNew = NULL;
45 | }
46 | return fSucceeded;
47 | }
48 |
49 | IMAGE_NT_HEADERS_XX inh;
50 | ZeroMemory(&inh, sizeof(inh));
51 |
52 | if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
53 | || cbRead < sizeof(inh)) {
54 | DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
55 | pbModule + idh.e_lfanew,
56 | pbModule + idh.e_lfanew + sizeof(inh),
57 | GetLastError()));
58 | goto finish;
59 | }
60 |
61 | if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) {
62 | DETOUR_TRACE(("Wrong size image (%04x != %04x).\n",
63 | inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX));
64 | SetLastError(ERROR_INVALID_BLOCK);
65 | goto finish;
66 | }
67 |
68 | // Zero out the bound table so loader doesn't use it instead of our new table.
69 | inh.BOUND_DIRECTORY.VirtualAddress = 0;
70 | inh.BOUND_DIRECTORY.Size = 0;
71 |
72 | // Find the size of the mapped file.
73 | DWORD dwSec = idh.e_lfanew +
74 | FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) +
75 | inh.FileHeader.SizeOfOptionalHeader;
76 |
77 | for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
78 | IMAGE_SECTION_HEADER ish;
79 | ZeroMemory(&ish, sizeof(ish));
80 |
81 | if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
82 | sizeof(ish), &cbRead)
83 | || cbRead < sizeof(ish)) {
84 |
85 | DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
86 | pbModule + dwSec + sizeof(ish) * i,
87 | pbModule + dwSec + sizeof(ish) * (i + 1),
88 | GetLastError()));
89 | goto finish;
90 | }
91 |
92 | DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData));
93 |
94 | // If the linker didn't suggest an IAT in the data directories, the
95 | // loader will look for the section of the import directory to be used
96 | // for this instead. Since we put out new IMPORT_DIRECTORY outside any
97 | // section boundary, the loader will not find it. So we provide one
98 | // explicitly to avoid the search.
99 | //
100 | if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
101 | inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
102 | inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
103 |
104 | inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
105 | inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
106 | }
107 | }
108 |
109 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) {
110 |
111 | // Don't worry about changing the PE file,
112 | // because the load information of the original PE header has been saved and will be restored.
113 | // The change here is just for the following code to work normally
114 |
115 | PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress);
116 |
117 | do {
118 | IMAGE_IMPORT_DESCRIPTOR ImageImport;
119 | if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) {
120 | DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError()));
121 | goto finish;
122 | }
123 | inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
124 | if (!ImageImport.Name) {
125 | break;
126 | }
127 | ++pImageImport;
128 | } while (TRUE);
129 |
130 | DWORD dwLastError = GetLastError();
131 | OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.")
132 | TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n"));
133 | if (GetLastError() != dwLastError) {
134 | SetLastError(dwLastError);
135 | }
136 | }
137 |
138 | DETOUR_TRACE((" Imports: %p..%p\n",
139 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
140 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
141 | inh.IMPORT_DIRECTORY.Size));
142 |
143 | // Calculate new import directory size. Note that since inh is from another
144 | // process, inh could have been corrupted. We need to protect against
145 | // integer overflow in allocation calculations.
146 | DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
147 | DWORD obRem;
148 | if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) {
149 | DETOUR_TRACE(("too many new DLLs.\n"));
150 | goto finish;
151 | }
152 | DWORD obOld;
153 | if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) {
154 | DETOUR_TRACE(("DLL entries overflow.\n"));
155 | goto finish;
156 | }
157 | DWORD obTab = PadToDwordPtr(obOld);
158 | // Check for integer overflow.
159 | if (obTab < obOld) {
160 | DETOUR_TRACE(("DLL entries padding overflow.\n"));
161 | goto finish;
162 | }
163 | DWORD stSize;
164 | if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) {
165 | DETOUR_TRACE(("String table overflow.\n"));
166 | goto finish;
167 | }
168 | DWORD obDll;
169 | if (DWordAdd(obTab, stSize, &obDll) != S_OK) {
170 | DETOUR_TRACE(("Import table size overflow\n"));
171 | goto finish;
172 | }
173 | DWORD obStr = obDll;
174 | cbNew = obStr;
175 | for (n = 0; n < nDlls; n++) {
176 | if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) {
177 | DETOUR_TRACE(("Overflow adding string table entry\n"));
178 | goto finish;
179 | }
180 | }
181 | pbNew = new BYTE [cbNew];
182 | if (pbNew == NULL) {
183 | DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
184 | goto finish;
185 | }
186 | ZeroMemory(pbNew, cbNew);
187 |
188 | PBYTE pbBase = pbModule;
189 | PBYTE pbNext = pbBase
190 | + inh.OptionalHeader.BaseOfCode
191 | + inh.OptionalHeader.SizeOfCode
192 | + inh.OptionalHeader.SizeOfInitializedData
193 | + inh.OptionalHeader.SizeOfUninitializedData;
194 | if (pbBase < pbNext) {
195 | pbBase = pbNext;
196 | }
197 | DETOUR_TRACE(("pbBase = %p\n", pbBase));
198 |
199 | PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbModule, pbBase, cbNew);
200 | if (pbNewIid == NULL) {
201 | DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
202 | goto finish;
203 | }
204 |
205 | PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
206 | IMAGE_THUNK_DATAXX *pt = NULL;
207 |
208 | DWORD obBase = (DWORD)(pbNewIid - pbModule);
209 | DWORD dwProtect = 0;
210 |
211 | if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
212 | // Read the old import directory if it exists.
213 | DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect));
214 |
215 | if (!ReadProcessMemory(hProcess,
216 | pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
217 | &piid[nDlls],
218 | nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
219 | || cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
220 |
221 | DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError()));
222 | goto finish;
223 | }
224 | }
225 |
226 | for (n = 0; n < nDlls; n++) {
227 | HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
228 | if (FAILED(hrRet)) {
229 | DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
230 | goto finish;
231 | }
232 |
233 | // After copying the string, we patch up the size "??" bits if any.
234 | hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr,
235 | cbNew - obStr,
236 | DETOURS_STRINGIFY(DETOURS_BITS_XX));
237 | if (FAILED(hrRet)) {
238 | DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet));
239 | goto finish;
240 | }
241 |
242 | DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n));
243 | piid[n].OriginalFirstThunk = obBase + nOffset;
244 |
245 | // We need 2 thunks for the import table and 2 thunks for the IAT.
246 | // One for an ordinal import and one to mark the end of the list.
247 | pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
248 | pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
249 | pt[1].u1.Ordinal = 0;
250 |
251 | nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2));
252 | piid[n].FirstThunk = obBase + nOffset;
253 | pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
254 | pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
255 | pt[1].u1.Ordinal = 0;
256 | piid[n].TimeDateStamp = 0;
257 | piid[n].ForwarderChain = 0;
258 | piid[n].Name = obBase + obStr;
259 |
260 | obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
261 | }
262 | _Analysis_assume_(obStr <= cbNew);
263 |
264 | #if 0
265 | for (i = 0; i < nDlls + nOldDlls; i++) {
266 | DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
267 | i,
268 | piid[i].OriginalFirstThunk,
269 | piid[i].TimeDateStamp,
270 | piid[i].ForwarderChain,
271 | piid[i].Name,
272 | piid[i].FirstThunk));
273 | if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
274 | break;
275 | }
276 | }
277 | #endif
278 |
279 | if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
280 | DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError()));
281 | goto finish;
282 | }
283 |
284 | DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n",
285 | inh.IMPORT_DIRECTORY.VirtualAddress,
286 | inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
287 | DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr));
288 |
289 | // In this case the file didn't have an import directory in first place,
290 | // so we couldn't fix the missing IAT above. We still need to explicitly
291 | // provide an IAT to prevent to loader from looking for one.
292 | //
293 | if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
294 | inh.IAT_DIRECTORY.VirtualAddress = obBase;
295 | inh.IAT_DIRECTORY.Size = cbNew;
296 | }
297 |
298 | inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
299 | inh.IMPORT_DIRECTORY.Size = cbNew;
300 |
301 | /////////////////////// Update the NT header for the new import directory.
302 | //
303 | if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
304 | PAGE_EXECUTE_READWRITE, &dwProtect)) {
305 | DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError()));
306 | goto finish;
307 | }
308 |
309 | inh.OptionalHeader.CheckSum = 0;
310 |
311 | if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
312 | DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
313 | goto finish;
314 | }
315 | DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
316 |
317 | if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
318 | DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError()));
319 | goto finish;
320 | }
321 | DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
322 | pbModule + idh.e_lfanew,
323 | pbModule + idh.e_lfanew + sizeof(inh)));
324 |
325 | if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
326 | dwProtect, &dwProtect)) {
327 | DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError()));
328 | goto finish;
329 | }
330 |
331 | fSucceeded = TRUE;
332 | goto finish;
333 | }
334 |
--------------------------------------------------------------------------------
/Detours/src/windows_shim.h:
--------------------------------------------------------------------------------
1 | // Define DETOUR_TRACE macro
2 | // #define DETOUR_DEBUG 1
3 | #ifndef DETOUR_TRACE
4 | #if DETOUR_DEBUG
5 | #define DETOUR_TRACE(x) printf x
6 | #include
7 | #else
8 | #define DETOUR_TRACE(x)
9 | #endif
10 | #endif
11 |
12 | // Definition for Windows related things
13 | #ifndef _WIN32
14 |
15 | #include
16 | #include
17 |
18 | #define CALLBACK
19 | #define WINAPI
20 |
21 | typedef uint32_t DWORD, *PDWORD;
22 | typedef int16_t SHORT, *PSHORT;
23 | typedef uint16_t USHORT, *PUSHORT;
24 |
25 | typedef uint16_t UINT16;
26 | typedef unsigned char UCHAR;
27 | typedef char CHAR;
28 | typedef uint8_t BYTE;
29 | typedef uint8_t *PBYTE;
30 | typedef int16_t SHORT;
31 | typedef uint16_t USHORT, WORD;
32 | typedef int32_t BOOL;
33 | typedef int32_t INT, INT32;
34 | typedef uint32_t UINT, UINT32;
35 | typedef int64_t INT64, LONG64;
36 | typedef int64_t __int64;
37 | typedef uint64_t UINT64, ULONG64;
38 | typedef long long LONGLONG;
39 | typedef void VOID, *HMODULE, *PVOID, *LPVOID;
40 | #define TRUE ((BOOL)1)
41 | #define FALSE ((BOOL)0)
42 | // long is 8bytes in Clang/GCC, but 4bytes on Windows
43 | typedef int LONG;
44 | typedef unsigned int ULONG, *PULONG;
45 | typedef unsigned int ULONG32, * PULONG32;
46 | typedef uintptr_t ULONG_PTR;
47 | typedef intptr_t LONG_PTR;
48 | typedef size_t SIZE_T;
49 |
50 | typedef char *LPSTR;
51 | typedef const char *LPCSTR;
52 | typedef const void *LPCVOID;
53 | typedef void *HANDLE;
54 |
55 | #define ERROR_INVALID_DATA 0x10001
56 | #define ERROR_INVALID_OPERATION 0x10002
57 | #define ERROR_NOT_ENOUGH_MEMORY 0x10003
58 | #define ERROR_INVALID_PARAMETER 0x10004
59 | #define ERROR_INVALID_HANDLE 0x10005
60 | #define ERROR_INVALID_BLOCK 0x10006
61 | #define ERROR_DYNAMIC_CODE_BLOCKED 1655L
62 | #define ERROR_NOT_SAME_THREAD 0x10020
63 |
64 | #define ERROR_MACH_FAIL_BASE 0x20100
65 | #define ERROR_ERRNO_FAIL_BASE 0x20200
66 | #define NO_ERROR 0
67 |
68 | extern "C" {
69 | extern void SetLastError(int err);
70 | extern int GetLastError();
71 | }
72 |
73 | static int GetCurrentThreadId() {
74 | return 0;
75 | }
76 |
77 | static HANDLE GetCurrentThread() {
78 | return (HANDLE)-2;
79 | }
80 |
81 | static HANDLE GetCurrentProcess() {
82 | return (HANDLE)-1;
83 | }
84 |
85 | #else
86 |
87 | #include
88 |
89 | #endif // _WIN32
90 |
91 |
92 | #ifdef DETOURS_INTERNAL
93 |
94 | extern "C" {
95 | static unsigned long DetourGetModuleSize(void *) {
96 | return 0x1337;
97 | }
98 | }
99 |
100 | #include
101 | #undef LONG_MAX
102 | #undef LONG_MIN
103 | #define LONG_MAX INT_MAX
104 | #define LONG_MIN INT_MIN
105 |
106 | // Definition for windows shim functions
107 | #ifdef _WIN32
108 |
109 | static int getpagesize() {
110 | return 0x1000;
111 | }
112 |
113 | #else
114 |
115 | #include
116 | #include
117 | #include
118 |
119 | #include
120 | #include
121 |
122 | #ifdef _LINUX
123 | #include
124 | #include
125 | #endif
126 |
127 | #ifdef _DARWIN
128 | #include
129 | #include
130 | #include
131 | #include
132 | #include
133 | #include
134 | #endif
135 |
136 | #define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
137 | #define ARRAYSIZE(A) (sizeof(A)/sizeof(A[0]))
138 |
139 | #define UNALIGNED
140 |
141 | #define UNREFERENCED_PARAMETER(P) (P)
142 |
143 | static inline
144 | LONG InterlockedCompareExchange(LONG *ptr, LONG nval, LONG oval)
145 | {
146 | return __sync_val_compare_and_swap (ptr, nval, oval);
147 | }
148 |
149 | static inline ULONG PtrToUlong(PVOID ptr) {
150 | return (ULONG)(ULONG_PTR)(ptr);
151 | }
152 |
153 | static void CopyMemory(
154 | PVOID Destination,
155 | const VOID *Source,
156 | SIZE_T Length
157 | ) {
158 | memcpy(Destination, Source, Length);
159 | }
160 |
161 | #define PAGE_NOACCESS 1
162 | #define PAGE_READONLY 2
163 | #define PAGE_READWRITE 4
164 | #define PAGE_EXECUTE 0x10
165 | #define PAGE_WRITECOPY 0x8
166 | #define PAGE_EXECUTE_READ (PAGE_READONLY * PAGE_EXECUTE)
167 | #define PAGE_EXECUTE_READWRITE (PAGE_READWRITE * PAGE_EXECUTE)
168 | #define PAGE_EXECUTE_WRITECOPY (PAGE_WRITECOPY * PAGE_EXECUTE)
169 |
170 | #define MEM_COMMIT 0x00001000
171 | #define MEM_FREE 0x00010000
172 | #define MEM_RESERVE 0x00002000
173 |
174 | #define MEM_RELEASE 0
175 |
176 | typedef struct _MEMORY_BASIC_INFORMATION {
177 | PVOID BaseAddress;
178 | PVOID AllocationBase;
179 | DWORD AllocationProtect;
180 | WORD PartitionId;
181 | SIZE_T RegionSize;
182 | DWORD State;
183 | DWORD Protect;
184 | DWORD Type;
185 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
186 |
187 | static void WinProtToRWX(DWORD flProtect, int *r, int *w, int *x) {
188 | if (flProtect && (flProtect & 0xF) == 0) {
189 | *x = 1;
190 | flProtect >>= 4;
191 | }
192 | switch (flProtect) {
193 | case PAGE_READONLY:
194 | *r = 1;
195 | *w = 0;
196 | break;
197 | case PAGE_READWRITE:
198 | *r = 1;
199 | *w = 1;
200 | break;
201 | default:
202 | *r = 1;
203 | *w = 1;
204 | break;
205 | }
206 | }
207 |
208 | static DWORD RWXToWinProt(int r, int w, int x) {
209 | DWORD ret = PAGE_NOACCESS;
210 | if (r && w) {
211 | ret = PAGE_READWRITE;
212 | } else if (r) {
213 | ret = PAGE_READONLY;
214 | }
215 | if (x) {
216 | ret *= PAGE_EXECUTE;
217 | }
218 | return ret;
219 | }
220 |
221 | static SIZE_T VirtualQuery(
222 | LPCVOID lpAddress,
223 | PMEMORY_BASIC_INFORMATION lpBuffer,
224 | SIZE_T dwLength
225 | ) {
226 | if (!lpBuffer) return 0;
227 | #if defined(_LINUX)
228 | int a = 0;
229 | unsigned int prot = 0;
230 | int f = open("/proc/self/maps", O_RDONLY);
231 | char b[1024] = { 0 };
232 | int b_pos = 0;
233 | unsigned long last_addr0 = 0, last_addr1 = 0;
234 | while ((read(f, &a, 1)) >= 0) {
235 | b[b_pos++] = a;
236 | if (b_pos >= sizeof(b) || a == '\n') {
237 | char*end0 = NULL;
238 | unsigned long addr0 = strtoul(b, &end0, 16);
239 | char*end1 = NULL;
240 | unsigned long addr1 = strtoul(end0+1, &end1, 16);
241 | if ((void*)addr0 <= lpAddress && lpAddress < (void*)addr1) {
242 | lpBuffer->BaseAddress = (PVOID)addr0;
243 | lpBuffer->AllocationBase = (PVOID)addr0;
244 | lpBuffer->RegionSize = addr1 - addr0;
245 | int r = (end1+1)[0] == 'r';
246 | int w = (end1+1)[1] == 'w';
247 | int x = (end1+1)[2] == 'x';
248 | int prot = RWXToWinProt(r,w,x);
249 | lpBuffer->AllocationProtect = prot;
250 | lpBuffer->PartitionId = 0;
251 | lpBuffer->State = MEM_COMMIT;
252 | break;
253 | } else if (lpAddress < (void*)addr0) {
254 | lpBuffer->BaseAddress = (PVOID)last_addr1;
255 | lpBuffer->AllocationBase = (PVOID)addr0;
256 | lpBuffer->RegionSize = addr0 - last_addr1;
257 | lpBuffer->AllocationProtect = 0;
258 | lpBuffer->PartitionId = 0;
259 | lpBuffer->State = MEM_FREE;
260 | break;
261 | }
262 | memset(b, 0, sizeof(b));
263 | b_pos = 0;
264 | last_addr0 = addr0;
265 | last_addr1 = addr1;
266 | }
267 | }
268 |
269 | close(f);
270 | return sizeof(MEMORY_BASIC_INFORMATION);
271 | #elif defined(_DARWIN)
272 | kern_return_t kr = KERN_SUCCESS;
273 | mach_port_t object_name;
274 | mach_vm_size_t size_info;
275 | mach_vm_address_t address_info = (mach_vm_address_t)lpAddress;
276 | mach_msg_type_number_t info_cnt = sizeof (vm_region_basic_info_data_64_t);
277 | vm_region_basic_info_data_64_t info;
278 | kr = mach_vm_region(mach_task_self(), &address_info, &size_info, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_cnt, &object_name);
279 | if (kr) {
280 | SetLastError(kr + ERROR_MACH_FAIL_BASE);
281 | }
282 | if ((ULONG_PTR)address_info <= (ULONG_PTR)lpAddress) {
283 | lpBuffer->BaseAddress = (PVOID)address_info;
284 | lpBuffer->AllocationBase = (PVOID)address_info;
285 | lpBuffer->RegionSize = size_info;
286 | lpBuffer->State = MEM_COMMIT;
287 | } else {
288 | lpBuffer->BaseAddress = (PVOID)lpAddress;
289 | lpBuffer->AllocationBase = (PVOID)lpAddress;
290 | lpBuffer->RegionSize = (ULONG_PTR)address_info - (ULONG_PTR)lpAddress;
291 | lpBuffer->State = MEM_FREE;
292 | }
293 | int r = info.protection & VM_PROT_READ;
294 | int w = info.protection & VM_PROT_WRITE;
295 | int x = info.protection & VM_PROT_EXECUTE;
296 | int prot = RWXToWinProt(r,w,x);
297 | lpBuffer->AllocationProtect = prot;
298 | lpBuffer->PartitionId = 0;
299 | return sizeof(MEMORY_BASIC_INFORMATION);
300 | #endif
301 | return 0;
302 | }
303 |
304 | static BOOL VirtualProtect(PVOID addr, SIZE_T dwSize, DWORD flNewProtect, DWORD *flOld) {
305 | DETOUR_TRACE(("VirtualProtect(%p, %lx, 0x%x)\n", addr, dwSize, flNewProtect));
306 | int newR = 0, newW = 0, newX = 0;
307 | WinProtToRWX(flNewProtect, &newR, &newW, &newX);
308 |
309 | #if defined(_LINUX) || defined(_DARWIN)
310 | ULONG_PTR aligned_addr = (ULONG_PTR)addr & ~(getpagesize() - 1);
311 | SIZE_T aligned_size = (ULONG_PTR)addr - aligned_addr + dwSize;
312 | MEMORY_BASIC_INFORMATION mbi;
313 | if (!VirtualQuery((void *)aligned_addr, &mbi, sizeof(mbi))) {
314 | return FALSE;
315 | }
316 | int oldProt = mbi.AllocationProtect;
317 | *flOld = oldProt;
318 | BOOL ignoreRet = FALSE;
319 | #ifdef _DARWIN
320 | if (newW && newX) {
321 | DETOUR_TRACE(("W^X detected, removing executing bit & ignoring error!\n"));
322 | newX = 0;
323 | ignoreRet = TRUE;
324 | // DETOUR_TRACE(("VirtualProtect: W^X detected, ignoring and directly return!\n"));
325 | // return TRUE;
326 | }
327 | #endif
328 | int newProt = 0;
329 | newProt |= newR ? PROT_READ : 0;
330 | newProt |= newW ? PROT_WRITE : 0;
331 | newProt |= newX ? PROT_EXEC : 0;
332 | int ret = mprotect((void *)aligned_addr, aligned_size, newProt);
333 | if (!ignoreRet && ret == -1){
334 | DETOUR_TRACE(("VirtualProtect mprotect fail... errno=%d\n", errno));
335 | SetLastError(ERROR_ERRNO_FAIL_BASE + errno);
336 | return FALSE;
337 | }
338 | return TRUE;
339 | #else
340 | #error Unknown OS (Please define _LINUX or _DARWIN)
341 | #endif
342 | return FALSE;
343 | }
344 |
345 | static SIZE_T VirtualQueryEx(
346 | HANDLE hProcess,
347 | LPCVOID lpAddress,
348 | PMEMORY_BASIC_INFORMATION lpBuffer,
349 | SIZE_T dwLength
350 | ) {
351 | if (hProcess != GetCurrentProcess()) {
352 | return 0;
353 | }
354 | return VirtualQuery(lpAddress, lpBuffer, dwLength);
355 | }
356 |
357 | static BOOL VirtualProtectEx(HANDLE hProcess, PVOID addr, SIZE_T dwSize, DWORD flNewProtect, DWORD *flOld) {
358 | if (hProcess != GetCurrentProcess()) {
359 | return FALSE;
360 | }
361 | return VirtualProtect(addr, dwSize, flNewProtect, flOld);
362 | }
363 |
364 | static LPVOID VirtualAlloc(
365 | LPVOID lpAddress,
366 | SIZE_T dwSize,
367 | DWORD flAllocationType,
368 | DWORD flProtect
369 | ) {
370 | DETOUR_TRACE(("VirtualAlloc(%p, 0x%lx, %d, 0x%x)\n", lpAddress, dwSize, flAllocationType, flProtect));
371 | int newR = 0, newW = 0, newX = 0;
372 | WinProtToRWX(flProtect, &newR, &newW, &newX);
373 | DETOUR_TRACE(("RWX parsed: %d %d %d\n", newR, newW, newX));
374 | #ifdef _DARWIN
375 | if (newW && newX) {
376 | DETOUR_TRACE(("W^X detected, removing executing bit!\n"));
377 | newX = 0;
378 | }
379 | #endif
380 | int newProt = 0;
381 | newProt |= newR ? PROT_READ : 0;
382 | newProt |= newW ? PROT_WRITE : 0;
383 | newProt |= newX ? PROT_EXEC : 0;
384 |
385 | LPVOID retAddr = mmap(lpAddress, dwSize, newProt, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
386 | DETOUR_TRACE(("mmap(%p, 0x%lx, %d) = %p, errno = %d\n", lpAddress, dwSize, newProt, retAddr, errno));
387 |
388 | if (retAddr == (LPVOID)-1) {
389 | SetLastError(ERROR_ERRNO_FAIL_BASE + errno);
390 | return NULL;
391 | }
392 | return retAddr;
393 | }
394 |
395 | #define FlushInstructionCache _FlushInstructionCache
396 |
397 | #ifdef _DARWIN
398 | #include
399 | #endif
400 | static BOOL FlushInstructionCache(
401 | HANDLE hProcess,
402 | LPCVOID lpBaseAddress,
403 | SIZE_T dwSize
404 | ) {
405 | #ifdef _DARWIN
406 | sys_icache_invalidate(( void *)lpBaseAddress,dwSize);
407 | #endif
408 | return TRUE;
409 | }
410 |
411 | static BOOL VirtualFree(
412 | LPVOID lpAddress,
413 | SIZE_T dwSize,
414 | DWORD dwFreeType
415 | ) {
416 | if(munmap(lpAddress, dwSize)) {
417 | SetLastError(ERROR_ERRNO_FAIL_BASE + errno);
418 | return FALSE;
419 | };
420 | return TRUE;
421 | }
422 |
423 | static DWORD ResumeThread(
424 | HANDLE hThread
425 | ) {
426 | return 1;
427 | }
428 |
429 | static DWORD SuspendThread(
430 | HANDLE hThread
431 | ) {
432 | return 0;
433 | }
434 |
435 | #define ZeroMemory(a,s) memset((a), 0, (s))
436 | #define __debugbreak() (void)0
437 | #define DebugBreak() (void)0
438 |
439 | #endif // _WIN32
440 |
441 | #endif // DETOURS_INTERNAL
442 |
443 | #undef DETOUR_TRACE
444 |
--------------------------------------------------------------------------------
/DetoursTest.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.33529.398
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DetoursTest", "DetoursTest\DetoursTest.vcxproj", "{57941E38-685B-44C3-9D74-2E8B061B5862}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12} = {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}
9 | EndProjectSection
10 | EndProject
11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Detours", "Detours\Detours.vcxproj", "{3B8C6EDE-D8B8-4297-94A4-30C90A850F12}"
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|ARM = Debug|ARM
16 | Debug|ARM64 = Debug|ARM64
17 | Debug|x64 = Debug|x64
18 | Debug|x86 = Debug|x86
19 | Release|ARM = Release|ARM
20 | Release|ARM64 = Release|ARM64
21 | Release|x64 = Release|x64
22 | Release|x86 = Release|x86
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|ARM.ActiveCfg = Debug|ARM
26 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|ARM.Build.0 = Debug|ARM
27 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|ARM64.ActiveCfg = Debug|ARM64
28 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|ARM64.Build.0 = Debug|ARM64
29 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|x64.ActiveCfg = Debug|x64
30 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|x64.Build.0 = Debug|x64
31 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|x86.ActiveCfg = Debug|Win32
32 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Debug|x86.Build.0 = Debug|Win32
33 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|ARM.ActiveCfg = Release|ARM
34 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|ARM.Build.0 = Release|ARM
35 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|ARM64.ActiveCfg = Release|ARM64
36 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|ARM64.Build.0 = Release|ARM64
37 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|x64.ActiveCfg = Release|x64
38 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|x64.Build.0 = Release|x64
39 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|x86.ActiveCfg = Release|Win32
40 | {57941E38-685B-44C3-9D74-2E8B061B5862}.Release|x86.Build.0 = Release|Win32
41 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|ARM.ActiveCfg = Debug|ARM
42 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|ARM.Build.0 = Debug|ARM
43 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|ARM64.ActiveCfg = Debug|ARM64
44 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|ARM64.Build.0 = Debug|ARM64
45 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|x64.ActiveCfg = Debug|x64
46 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|x64.Build.0 = Debug|x64
47 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|x86.ActiveCfg = Debug|Win32
48 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Debug|x86.Build.0 = Debug|Win32
49 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|ARM.ActiveCfg = Release|ARM
50 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|ARM.Build.0 = Release|ARM
51 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|ARM64.ActiveCfg = Release|ARM64
52 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|ARM64.Build.0 = Release|ARM64
53 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|x64.ActiveCfg = Release|x64
54 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|x64.Build.0 = Release|x64
55 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|x86.ActiveCfg = Release|Win32
56 | {3B8C6EDE-D8B8-4297-94A4-30C90A850F12}.Release|x86.Build.0 = Release|Win32
57 | EndGlobalSection
58 | GlobalSection(SolutionProperties) = preSolution
59 | HideSolutionNode = FALSE
60 | EndGlobalSection
61 | GlobalSection(ExtensibilityGlobals) = postSolution
62 | SolutionGuid = {77981E05-F1A3-4E9A-9966-2BB23AC1CA5B}
63 | EndGlobalSection
64 | EndGlobal
65 |
--------------------------------------------------------------------------------
/DetoursTest/DetoursTest.cpp:
--------------------------------------------------------------------------------
1 | // DetoursTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
2 | //
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #ifdef _WIN32
9 | #include
10 | #define TEST_CALL_TYPE __stdcall
11 | #else
12 | #define TEST_CALL_TYPE
13 | #endif
14 |
15 | #include
16 |
17 |
18 | #ifdef _WIN32
19 | __declspec(noinline)
20 | #endif
21 | int TEST_CALL_TYPE test2(int i)
22 | {
23 | std::cout << "test2 start,i=" << i << std::endl;
24 |
25 | std::cout << "test2 end\n";
26 | return 0;
27 | }
28 |
29 | typedef int (TEST_CALL_TYPE* Api_test2)(int i);
30 | Api_test2 true_test2 = NULL;
31 |
32 | int TEST_CALL_TYPE hook_test2(int i)
33 | {
34 | std::cout << "hook_test2 start\n";
35 |
36 | int i_ret = true_test2(i+100);
37 |
38 | std::cout << "hook_test2 end\n";
39 | return i_ret;
40 | }
41 |
42 |
43 |
44 | #ifdef _WIN32
45 | __declspec(noinline)
46 | #endif
47 | int TEST_CALL_TYPE test1(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12, int i13, int i14, int i15, int i16)
48 | {
49 | std::cout << "test1 start\n";
50 |
51 | int i_ret = i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12 + i13 + i14 + i15 + i16;
52 |
53 | test2(i_ret);
54 |
55 | std::cout << "test1 end\n";
56 | return i_ret;
57 | }
58 |
59 |
60 | class TestClass {
61 | public:
62 | TestClass() {};
63 | long TEST_CALL_TYPE call(long a, long b)
64 | {
65 | std::cout << "TestClass::call start\n";
66 | long l_ret = m_i + a + b;
67 |
68 | std::cout << "TestClass::call end ,ret "<< l_ret <<"\n";
69 |
70 | return l_ret;
71 | }
72 |
73 | private:
74 | long m_i = 100;
75 | };
76 |
77 |
78 |
79 |
80 |
81 | class HookTestClass {
82 | public:
83 | long TEST_CALL_TYPE call(long a, long b)
84 | {
85 | std::cout << "HookTestClass::call start\n";
86 | long l_ret = (this->*m_true_call)(a+10,b+10);
87 |
88 | std::cout << "HookTestClass::call end\n";
89 |
90 | return l_ret;
91 | }
92 | public:
93 | typedef long (TEST_CALL_TYPE HookTestClass::*Api_hook_testclass_call)(long, long);
94 | static Api_hook_testclass_call m_true_call;
95 | };
96 |
97 | typedef long (TEST_CALL_TYPE HookTestClass::*Api_hook_testclass_call)(long, long);
98 | typedef long (TEST_CALL_TYPE TestClass::*Api_true_testclass_call)(long, long);
99 |
100 | Api_hook_testclass_call HookTestClass::m_true_call = NULL;
101 |
102 |
103 | BOOL WINAPI DetoursHookNoitfy(_In_ PDETROUS_HOOK_NOTIFY_INFO_STRCUT pInfo)
104 | {
105 | std::string str_context = (char*)(ULONG_PTR)pInfo->pContext;
106 |
107 | if (str_context.find("test1_notify") != -1)
108 | {
109 | std::cout << "DetoursHookNoitfy called,context=" << str_context
110 | << ",i1=" << *(int*)pInfo->pParam1
111 | << ",i16=" << *(int*)pInfo->pParam16
112 | << std::endl;
113 |
114 | *(int*)pInfo->pParam1 = 10086;//如果不在函数的起始位置hook的话,一般不能返回阻止(平衡栈,一些析构函数的执行等),但是修改参数的方式让它失败。
115 |
116 | }
117 | else if (str_context.find("test2_notify") != -1)
118 | {
119 | std::cout << "DetoursHookNoitfy called,context=" << str_context
120 | << ",i1=" << *(int*)pInfo->pParam1
121 | << std::endl;
122 | }
123 | else if (str_context.find("test3_notify") != -1)
124 | {
125 |
126 | std::cout << "DetoursHookNoitfy called,context=" << str_context
127 | << ",i1=" << *(int*)pInfo->pParam2
128 | << std::endl;
129 | }
130 |
131 |
132 | return TRUE;
133 | }
134 |
135 |
136 | //s_rceCopyTable
137 | int main()
138 | {
139 |
140 | #if defined(DETOURS_X86)
141 | std::cout << "x86 start!\n\n";
142 | #elif defined(DETOURS_X64)
143 | std::cout << "x64 start!\n\n";
144 | #elif defined(DETOURS_ARM)
145 | std::cout << "arm start!\n\n";
146 | #elif defined(DETOURS_ARM64)
147 | std::cout << "arm64 start!\n\n";
148 | #endif
149 |
150 | true_test2 = test2;
151 |
152 | auto true_tmp = &TestClass::call;
153 | HookTestClass::m_true_call = (Api_hook_testclass_call)true_tmp;
154 |
155 | auto hook_tmp = &HookTestClass::call;
156 | UCHAR *hook_call = (UCHAR *)*(&(PVOID&)hook_tmp);
157 |
158 | UCHAR *true_test1_notify = (UCHAR *)test1;
159 | UCHAR *true_test2_notify = (UCHAR *)true_test2;
160 | UCHAR *true_test3_notify = (UCHAR *)*(&(PVOID&)true_tmp);
161 |
162 |
163 |
164 | std::unique_ptr test_class = std::make_unique();
165 |
166 | //#define TEST_ORG_HOOK
167 |
168 | //hook
169 | DetourTransactionBegin();
170 | DetourUpdateThread(GetCurrentThread());
171 | #ifdef TEST_ORG_HOOK
172 | DetourAttach(&(PVOID&)true_test2, (PVOID)hook_test2);
173 | DetourAttach(&(PVOID&)HookTestClass::m_true_call, (PVOID)hook_call);
174 | #else
175 | DetourInstallNotify(&(PVOID&)true_test1_notify, DetoursHookNoitfy, (PVOID)"test1_notify");
176 | DetourInstallNotify(&(PVOID&)true_test2_notify, DetoursHookNoitfy, (PVOID)"test2_notify");
177 | DetourInstallNotify(&(PVOID&)true_test3_notify, DetoursHookNoitfy, (PVOID)"test3_notify");
178 | #endif
179 | DetourTransactionCommit();
180 |
181 | test1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
182 | test_class->call(10, 20);
183 |
184 | std::cout << "\nunhook\n\n";
185 | //unhook
186 | DetourTransactionBegin();
187 | DetourUpdateThread(GetCurrentThread());
188 | #ifdef TEST_ORG_HOOK
189 | DetourDetach(&(PVOID&)true_test2, (PVOID)hook_test2);
190 | DetourDetach(&(PVOID&)HookTestClass::m_true_call, (PVOID)hook_call);
191 | #else
192 | DetourUnInstallNotify(&(PVOID&)true_test1_notify, DetoursHookNoitfy);
193 | DetourUnInstallNotify(&(PVOID&)true_test2_notify, DetoursHookNoitfy);
194 | DetourUnInstallNotify(&(PVOID&)true_test3_notify, DetoursHookNoitfy);
195 | #endif
196 | DetourTransactionCommit();
197 |
198 | test1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
199 | test_class->call(10, 20);
200 |
201 |
202 |
203 | std::cout << "\nend!\n";
204 | return 0;
205 | }
206 |
--------------------------------------------------------------------------------
/DetoursTest/DetoursTest.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | ARM
7 |
8 |
9 | Debug
10 | ARM64
11 |
12 |
13 | Debug
14 | Win32
15 |
16 |
17 | Release
18 | ARM
19 |
20 |
21 | Release
22 | ARM64
23 |
24 |
25 | Release
26 | Win32
27 |
28 |
29 | Debug
30 | x64
31 |
32 |
33 | Release
34 | x64
35 |
36 |
37 |
38 | 15.0
39 | {57941E38-685B-44C3-9D74-2E8B061B5862}
40 | Win32Proj
41 | DetoursTest
42 | 10.0.17763.0
43 |
44 |
45 |
46 | Application
47 | true
48 | v141
49 | Unicode
50 |
51 |
52 | Application
53 | true
54 | v141
55 | Unicode
56 |
57 |
58 | Application
59 | true
60 | v141
61 | Unicode
62 |
63 |
64 | Application
65 | false
66 | v141
67 | true
68 | Unicode
69 |
70 |
71 | Application
72 | false
73 | v141
74 | true
75 | Unicode
76 |
77 |
78 | Application
79 | false
80 | v141
81 | true
82 | Unicode
83 |
84 |
85 | Application
86 | true
87 | v141
88 | Unicode
89 |
90 |
91 | Application
92 | false
93 | v141
94 | true
95 | Unicode
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 | true
137 |
138 |
139 | true
140 |
141 |
142 | true
143 |
144 |
145 | true
146 |
147 |
148 | false
149 |
150 |
151 | false
152 |
153 |
154 | false
155 |
156 |
157 | false
158 |
159 |
160 |
161 | NotUsing
162 | Level3
163 | Disabled
164 |
165 |
166 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
167 | false
168 | false
169 | MultiThreadedDebug
170 | ..\Detours\src;%(AdditionalIncludeDirectories)
171 | true
172 |
173 |
174 | Console
175 | true
176 | Detours.lib;%(AdditionalDependencies)
177 |
178 |
179 |
180 |
181 | NotUsing
182 | Level3
183 | Disabled
184 |
185 |
186 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
187 | false
188 | false
189 | MultiThreadedDebug
190 | ..\Detours\src;%(AdditionalIncludeDirectories)
191 | true
192 |
193 |
194 | Console
195 | true
196 | Detours.lib;%(AdditionalDependencies)
197 |
198 |
199 |
200 |
201 | NotUsing
202 | Level3
203 | Disabled
204 |
205 |
206 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
207 | false
208 | false
209 | MultiThreadedDebug
210 | ..\Detours\src;%(AdditionalIncludeDirectories)
211 | true
212 |
213 |
214 | Console
215 | true
216 | Detours.lib;%(AdditionalDependencies)
217 |
218 |
219 |
220 |
221 | NotUsing
222 | Level3
223 | Disabled
224 |
225 |
226 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
227 | false
228 | false
229 | MultiThreadedDebug
230 | ..\Detours\src;%(AdditionalIncludeDirectories)
231 | true
232 |
233 |
234 | Console
235 | true
236 | Detours.lib;%(AdditionalDependencies)
237 |
238 |
239 |
240 |
241 | NotUsing
242 | Level3
243 | true
244 | true
245 |
246 |
247 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
248 | false
249 | false
250 | MultiThreaded
251 | ..\Detours\src;%(AdditionalIncludeDirectories)
252 | true
253 |
254 |
255 | Console
256 | true
257 | true
258 | true
259 |
260 | Detours.lib;%(AdditionalDependencies)
261 |
262 |
263 |
264 |
265 | NotUsing
266 | Level3
267 | MaxSpeed
268 | true
269 | true
270 |
271 |
272 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
273 | false
274 | false
275 | MultiThreaded
276 | ..\Detours\src;%(AdditionalIncludeDirectories)
277 | true
278 |
279 |
280 | Console
281 | true
282 | true
283 | true
284 | Detours.lib;%(AdditionalDependencies)
285 |
286 |
287 |
288 |
289 | NotUsing
290 | Level3
291 | MaxSpeed
292 | true
293 | true
294 |
295 |
296 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
297 | false
298 | false
299 | MultiThreaded
300 | ..\Detours\src;%(AdditionalIncludeDirectories)
301 | true
302 |
303 |
304 | Console
305 | true
306 | true
307 | true
308 | Detours.lib;%(AdditionalDependencies)
309 |
310 |
311 |
312 |
313 | NotUsing
314 | Level3
315 | MaxSpeed
316 | true
317 | true
318 |
319 |
320 | KEYSTONE_STATIC;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;LLVM_ENABLE_ARCH_AArch64;LLVM_ENABLE_ARCH_ARM;LLVM_ENABLE_ARCH_X86;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
321 | false
322 | false
323 | MultiThreaded
324 | ..\Detours\src;%(AdditionalIncludeDirectories)
325 | true
326 |
327 |
328 | Console
329 | true
330 | true
331 | true
332 | Detours.lib;%(AdditionalDependencies)
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
--------------------------------------------------------------------------------
/DetoursTest/DetoursTest.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | 源文件
20 |
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DetoursEx
2 | Modified by Mircosoft detours.Support Window/Linux/Macos. Support X86/x64/ARM64/ARM/MIPS/LongArch.
3 | Can Hook in any address but not only the function beginning address.
4 |
5 | ## Usage
6 |
7 | ```c++
8 | __declspec(noinline) int test1(int i1, int i2, int i3, int i4, int i5)
9 | {
10 | std::cout << "test1 start\n";
11 |
12 | test2(i1);
13 | int i_ret = i1 + i2 + i3 + i4 + i5;
14 |
15 | std::cout << "test1 end\n";
16 | return i_ret;
17 | }
18 |
19 | int hook_test1(int i1, int i2, int i3, int i4, int i5)
20 | {
21 | std::cout << "hook_test1 start\n";
22 |
23 | int i_ret = true_test1(i1, i2, i3, i4, i5);
24 |
25 | std::cout << "hook_test1 end\n";
26 | return i_ret;
27 | }
28 |
29 | BOOL CALLBACK DetoursHookNoitfy(_In_ PDETROUS_HOOK_NOTIFY_INFO_STRCUT pInfo)
30 | {
31 | std::cout << "DetoursHookNoitfy called,context=" << (int)(ULONG_PTR)pInfo->pContext << std::endl;
32 |
33 | return TRUE;//return FALSE means block
34 | }
35 |
36 | typedef int(*pfn_test1)(int i1, int i2, int i3, int i4, int i5);
37 | pfn_test1 true_test1 = nullptr;
38 |
39 | int test_hook()
40 | {
41 | DetourRestoreAfterWith();
42 | DetourTransactionBegin();
43 | DetourUpdateThread(GetCurrentThread());
44 | #if 0
45 | DetourAttach(&(PVOID&)true_test1, hook_test1);
46 | #else
47 | DetourInstallNotify(&(PVOID&)true_test1, DetoursHookNoitfy, (PVOID)1);
48 | #endif
49 | DetourTransactionCommit();
50 | }
51 | ```
52 |
--------------------------------------------------------------------------------
/config.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 5.01
6 | 5.02
7 |
8 |
9 |
10 | NoName
11 | $(SolutionDir)..\
12 | $(ProductRootDir)Output\
13 |
14 |
15 | $(OutputBaseDir)BinDebugX86\$(SolutionName)\
16 | $(OutputBaseDir)LibDebugX86\$(SolutionName)\
17 | $(OutputBaseDir)PdbDebugX86\$(SolutionName)\
18 | $(OutputBaseDir)TmpDebugX86\$(SolutionName)\
19 |
20 |
21 | $(OutputBaseDir)BinX86\$(SolutionName)\
22 | $(OutputBaseDir)LibX86\$(SolutionName)\
23 | $(OutputBaseDir)PdbX86\$(SolutionName)\
24 | $(OutputBaseDir)TmpX86\$(SolutionName)\
25 |
26 |
27 | $(OutputBaseDir)BinDebugX64\$(SolutionName)\
28 | $(OutputBaseDir)LibDebugX64\$(SolutionName)\
29 | $(OutputBaseDir)PdbDebugX64\$(SolutionName)\
30 | $(OutputBaseDir)TmpDebugX64\$(SolutionName)\
31 |
32 |
33 | $(OutputBaseDir)BinX64\$(SolutionName)\
34 | $(OutputBaseDir)LibX64\$(SolutionName)\
35 | $(OutputBaseDir)PdbX64\$(SolutionName)\
36 | $(OutputBaseDir)TmpX64\$(SolutionName)\
37 |
38 |
39 | $(OutputBaseDir)BinDebugARM64\$(SolutionName)\
40 | $(OutputBaseDir)LibDebugARM64\$(SolutionName)\
41 | $(OutputBaseDir)PdbDebugARM64\$(SolutionName)\
42 | $(OutputBaseDir)TmpDebugARM64\$(SolutionName)\
43 |
44 |
45 | $(OutputBaseDir)BinARM64\$(SolutionName)\
46 | $(OutputBaseDir)LibARM64\$(SolutionName)\
47 | $(OutputBaseDir)PdbARM64\$(SolutionName)\
48 | $(OutputBaseDir)TmpARM64\$(SolutionName)\
49 |
50 |
51 | $(OutputBaseDir)BinDebugARM\$(SolutionName)\
52 | $(OutputBaseDir)LibDebugARM\$(SolutionName)\
53 | $(OutputBaseDir)PdbDebugARM\$(SolutionName)\
54 | $(OutputBaseDir)TmpDebugARM\$(SolutionName)\
55 |
56 |
57 | $(OutputBaseDir)BinARM\$(SolutionName)\
58 | $(OutputBaseDir)LibARM\$(SolutionName)\
59 | $(OutputBaseDir)PdbARM\$(SolutionName)\
60 | $(OutputBaseDir)TmpARM\$(SolutionName)\
61 |
62 |
63 | <_PropertySheetDisplayName>global_setting
64 | $(LibPath)
65 | $(BinPath)
66 | $(ObjPath)$(ProjectName)\
67 | $(ProjectName)
68 |
69 |
70 | false
71 |
72 |
73 |
74 | $(LibPath)
75 | $(PdbPath)$(TargetName).pdb
76 | $(LibPath)$(TargetName).lib
77 |
78 |
79 | $(PdbPath)$(TargetName).pdb
80 | true
81 | true
82 | /Zc:sizedDealloc- /Zc:threadSafeInit- /Zc:strictStrings- %(AdditionalOptions)
83 | $(IntDir)%(RelativeDir)\
84 | $(ProductRootDir)include;%(AdditionalIncludeDirectories)
85 |
86 |
87 |
88 |
89 | $(ProductRootDir)
90 |
91 |
92 | $(OutputBaseDir)
93 |
94 |
95 | $(ProductName)
96 |
97 |
98 | $(BinPath)
99 |
100 |
101 | $(LibPath)
102 |
103 |
104 | $(PdbPath)
105 |
106 |
107 | $(ObjPath)
108 |
109 |
110 |
--------------------------------------------------------------------------------