├── README.md
├── ShooterGameCheat.sln
└── ShooterGameCheat
├── ShooterGameCheat.vcxproj
├── ShooterGameCheat.vcxproj.filters
├── detours
├── detours.cpp
├── detours.h
├── detver.h
├── disasm.cpp
├── disolarm.cpp
├── disolarm64.cpp
├── disolia64.cpp
├── disolx64.cpp
├── disolx86.cpp
├── image.cpp
└── modules.cpp
├── dllmain.cpp
├── game
├── adapt_data.h
├── base_struct.h
├── game.cpp
└── game.h
├── shooter_game_cheat.cpp
└── utils.h
/README.md:
--------------------------------------------------------------------------------
1 | A Simple Cheat for ShooterGame.
--------------------------------------------------------------------------------
/ShooterGameCheat.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28010.2003
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShooterGameCheat", "ShooterGameCheat\ShooterGameCheat.vcxproj", "{C3C43A8E-EBDB-4E29-985E-E94E7D419459}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | exe|x64 = exe|x64
13 | exe|x86 = exe|x86
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x64.ActiveCfg = Debug|x64
19 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x64.Build.0 = Debug|x64
20 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x86.ActiveCfg = Debug|Win32
21 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x86.Build.0 = Debug|Win32
22 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x64.ActiveCfg = exe|x64
23 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x64.Build.0 = exe|x64
24 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x86.ActiveCfg = exe|Win32
25 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x86.Build.0 = exe|Win32
26 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x64.ActiveCfg = Release|x64
27 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x64.Build.0 = Release|x64
28 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x86.ActiveCfg = Release|Win32
29 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x86.Build.0 = Release|Win32
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {AD903B6B-3EAD-4068-AF1A-AC7892D9B2E4}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/ShooterGameCheat/ShooterGameCheat.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | exe
10 | Win32
11 |
12 |
13 | exe
14 | x64
15 |
16 |
17 | Release
18 | Win32
19 |
20 |
21 | Debug
22 | x64
23 |
24 |
25 | Release
26 | x64
27 |
28 |
29 |
30 | 15.0
31 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}
32 | Win32Proj
33 | ShooterGameCheat
34 | 10.0
35 |
36 |
37 |
38 | DynamicLibrary
39 | true
40 | v142
41 | Unicode
42 |
43 |
44 | DynamicLibrary
45 | true
46 | v142
47 | Unicode
48 |
49 |
50 | DynamicLibrary
51 | false
52 | v142
53 | true
54 | Unicode
55 |
56 |
57 | DynamicLibrary
58 | true
59 | v142
60 | Unicode
61 |
62 |
63 | Application
64 | true
65 | v142
66 | Unicode
67 |
68 |
69 | DynamicLibrary
70 | false
71 | v142
72 | true
73 | Unicode
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | true
101 |
102 |
103 | true
104 |
105 |
106 | true
107 | $(SolutionDir)$(Configuration)\
108 |
109 |
110 | true
111 |
112 |
113 | false
114 |
115 |
116 | false
117 |
118 |
119 |
120 | Use
121 | Level3
122 | Disabled
123 | true
124 | WIN32;_DEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
125 | true
126 |
127 |
128 | Windows
129 | true
130 |
131 |
132 |
133 |
134 | Use
135 | Level3
136 | Disabled
137 | true
138 | WIN32;_DEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
139 | true
140 |
141 |
142 | Windows
143 | true
144 |
145 |
146 |
147 |
148 | NotUsing
149 | Level3
150 | Disabled
151 | true
152 | _DEBUG;SHOOTERGAMECHEAT_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
153 | true
154 | 4099;4267;4996;%(DisableSpecificWarnings)
155 | true
156 | false
157 | EditAndContinue
158 | MultiThreadedDebug
159 | false
160 | Default
161 |
162 |
163 | Windows
164 | true
165 |
166 |
167 |
168 |
169 | NotUsing
170 | Level3
171 | Disabled
172 | true
173 | _DEBUG;SHOOTERGAMECHEAT_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
174 | true
175 | 4099;4267;%(DisableSpecificWarnings)
176 | true
177 | false
178 | EditAndContinue
179 | MultiThreadedDebug
180 | false
181 |
182 |
183 | Console
184 | true
185 |
186 |
187 |
188 |
189 | Use
190 | Level3
191 | MaxSpeed
192 | true
193 | true
194 | true
195 | WIN32;NDEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
196 | true
197 |
198 |
199 | Windows
200 | true
201 | true
202 | true
203 |
204 |
205 |
206 |
207 | Use
208 | Level3
209 | MaxSpeed
210 | true
211 | true
212 | true
213 | NDEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
214 | true
215 |
216 |
217 | Windows
218 | true
219 | true
220 | true
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
--------------------------------------------------------------------------------
/ShooterGameCheat/ShooterGameCheat.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 | {77bc882b-44cc-4946-8d01-cfd1c47bc059}
18 |
19 |
20 | {8a212da0-0d19-4d6a-8436-fbc9a937cb86}
21 |
22 |
23 |
24 |
25 | 源文件\detours
26 |
27 |
28 | 源文件\detours
29 |
30 |
31 | 源文件
32 |
33 |
34 | 源文件\game
35 |
36 |
37 | 源文件\game
38 |
39 |
40 | 源文件\game
41 |
42 |
43 |
44 |
45 | 源文件
46 |
47 |
48 | 源文件\detours
49 |
50 |
51 | 源文件\detours
52 |
53 |
54 | 源文件\detours
55 |
56 |
57 | 源文件\detours
58 |
59 |
60 | 源文件\detours
61 |
62 |
63 | 源文件\detours
64 |
65 |
66 | 源文件\detours
67 |
68 |
69 | 源文件\detours
70 |
71 |
72 | 源文件\detours
73 |
74 |
75 | 源文件\game
76 |
77 |
78 | 源文件
79 |
80 |
81 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/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 | #undef DETOURS_X64
20 | #undef DETOURS_X86
21 | #undef DETOURS_IA64
22 | #undef DETOURS_ARM
23 | #undef DETOURS_ARM64
24 | #undef DETOURS_BITS
25 | #undef DETOURS_32BIT
26 | #undef DETOURS_64BIT
27 |
28 | #if defined(_X86_)
29 | #define DETOURS_X86
30 | #define DETOURS_OPTION_BITS 64
31 |
32 | #elif defined(_AMD64_)
33 | #define DETOURS_X64
34 | #define DETOURS_OPTION_BITS 32
35 |
36 | #elif defined(_IA64_)
37 | #define DETOURS_IA64
38 | #define DETOURS_OPTION_BITS 32
39 |
40 | #elif defined(_ARM_)
41 | #define DETOURS_ARM
42 |
43 | #elif defined(_ARM64_)
44 | #define DETOURS_ARM64
45 |
46 | #else
47 | #error Unknown architecture (x86, amd64, ia64, arm, arm64)
48 | #endif
49 |
50 | #ifdef _WIN64
51 | #undef DETOURS_32BIT
52 | #define DETOURS_64BIT 1
53 | #define DETOURS_BITS 64
54 | // If all 64bit kernels can run one and only one 32bit architecture.
55 | //#define DETOURS_OPTION_BITS 32
56 | #else
57 | #define DETOURS_32BIT 1
58 | #undef DETOURS_64BIT
59 | #define DETOURS_BITS 32
60 | // If all 64bit kernels can run one and only one 32bit architecture.
61 | //#define DETOURS_OPTION_BITS 32
62 | #endif
63 |
64 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS)
65 |
66 | //////////////////////////////////////////////////////////////////////////////
67 | //
68 |
69 | #if (_MSC_VER < 1299)
70 | typedef LONG LONG_PTR;
71 | typedef ULONG ULONG_PTR;
72 | #endif
73 |
74 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL.
75 | //
76 | // These definitions are include so that Detours will build even if the
77 | // compiler doesn't have full SAL 2.0 support.
78 | //
79 | #ifndef DETOURS_DONT_REMOVE_SAL_20
80 |
81 | #ifdef DETOURS_TEST_REMOVE_SAL_20
82 | #undef _Analysis_assume_
83 | #undef _Benign_race_begin_
84 | #undef _Benign_race_end_
85 | #undef _Field_range_
86 | #undef _Field_size_
87 | #undef _In_
88 | #undef _In_bytecount_
89 | #undef _In_count_
90 | #undef _In_opt_
91 | #undef _In_opt_bytecount_
92 | #undef _In_opt_count_
93 | #undef _In_opt_z_
94 | #undef _In_range_
95 | #undef _In_reads_
96 | #undef _In_reads_bytes_
97 | #undef _In_reads_opt_
98 | #undef _In_reads_opt_bytes_
99 | #undef _In_reads_or_z_
100 | #undef _In_z_
101 | #undef _Inout_
102 | #undef _Inout_opt_
103 | #undef _Inout_z_count_
104 | #undef _Out_
105 | #undef _Out_opt_
106 | #undef _Out_writes_
107 | #undef _Outptr_result_maybenull_
108 | #undef _Readable_bytes_
109 | #undef _Success_
110 | #undef _Writable_bytes_
111 | #undef _Pre_notnull_
112 | #endif
113 |
114 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_)
115 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_
116 | #endif
117 |
118 | #if defined(_In_count_) && !defined(_In_reads_)
119 | #define _In_reads_(x) _In_count_(x)
120 | #endif
121 |
122 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_)
123 | #define _In_reads_opt_(x) _In_opt_count_(x)
124 | #endif
125 |
126 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_)
127 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x)
128 | #endif
129 |
130 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_)
131 | #define _In_reads_bytes_(x) _In_bytecount_(x)
132 | #endif
133 |
134 | #ifndef _In_
135 | #define _In_
136 | #endif
137 |
138 | #ifndef _In_bytecount_
139 | #define _In_bytecount_(x)
140 | #endif
141 |
142 | #ifndef _In_count_
143 | #define _In_count_(x)
144 | #endif
145 |
146 | #ifndef _In_opt_
147 | #define _In_opt_
148 | #endif
149 |
150 | #ifndef _In_opt_bytecount_
151 | #define _In_opt_bytecount_(x)
152 | #endif
153 |
154 | #ifndef _In_opt_count_
155 | #define _In_opt_count_(x)
156 | #endif
157 |
158 | #ifndef _In_opt_z_
159 | #define _In_opt_z_
160 | #endif
161 |
162 | #ifndef _In_range_
163 | #define _In_range_(x,y)
164 | #endif
165 |
166 | #ifndef _In_reads_
167 | #define _In_reads_(x)
168 | #endif
169 |
170 | #ifndef _In_reads_bytes_
171 | #define _In_reads_bytes_(x)
172 | #endif
173 |
174 | #ifndef _In_reads_opt_
175 | #define _In_reads_opt_(x)
176 | #endif
177 |
178 | #ifndef _In_reads_opt_bytes_
179 | #define _In_reads_opt_bytes_(x)
180 | #endif
181 |
182 | #ifndef _In_reads_or_z_
183 | #define _In_reads_or_z_
184 | #endif
185 |
186 | #ifndef _In_z_
187 | #define _In_z_
188 | #endif
189 |
190 | #ifndef _Inout_
191 | #define _Inout_
192 | #endif
193 |
194 | #ifndef _Inout_opt_
195 | #define _Inout_opt_
196 | #endif
197 |
198 | #ifndef _Inout_z_count_
199 | #define _Inout_z_count_(x)
200 | #endif
201 |
202 | #ifndef _Out_
203 | #define _Out_
204 | #endif
205 |
206 | #ifndef _Out_opt_
207 | #define _Out_opt_
208 | #endif
209 |
210 | #ifndef _Out_writes_
211 | #define _Out_writes_(x)
212 | #endif
213 |
214 | #ifndef _Outptr_result_maybenull_
215 | #define _Outptr_result_maybenull_
216 | #endif
217 |
218 | #ifndef _Writable_bytes_
219 | #define _Writable_bytes_(x)
220 | #endif
221 |
222 | #ifndef _Readable_bytes_
223 | #define _Readable_bytes_(x)
224 | #endif
225 |
226 | #ifndef _Success_
227 | #define _Success_(x)
228 | #endif
229 |
230 | #ifndef _Pre_notnull_
231 | #define _Pre_notnull_
232 | #endif
233 |
234 | #ifdef DETOURS_INTERNAL
235 |
236 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers)
237 |
238 | #ifndef _Benign_race_begin_
239 | #define _Benign_race_begin_
240 | #endif
241 |
242 | #ifndef _Benign_race_end_
243 | #define _Benign_race_end_
244 | #endif
245 |
246 | #ifndef _Field_size_
247 | #define _Field_size_(x)
248 | #endif
249 |
250 | #ifndef _Field_range_
251 | #define _Field_range_(x,y)
252 | #endif
253 |
254 | #ifndef _Analysis_assume_
255 | #define _Analysis_assume_(x)
256 | #endif
257 |
258 | #endif // DETOURS_INTERNAL
259 | #endif // DETOURS_DONT_REMOVE_SAL_20
260 |
261 | //////////////////////////////////////////////////////////////////////////////
262 | //
263 | #ifndef GUID_DEFINED
264 | #define GUID_DEFINED
265 | typedef struct _GUID
266 | {
267 | DWORD Data1;
268 | WORD Data2;
269 | WORD Data3;
270 | BYTE Data4[ 8 ];
271 | } GUID;
272 |
273 | #ifdef INITGUID
274 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
275 | const GUID name \
276 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
277 | #else
278 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
279 | const GUID name
280 | #endif // INITGUID
281 | #endif // !GUID_DEFINED
282 |
283 | #if defined(__cplusplus)
284 | #ifndef _REFGUID_DEFINED
285 | #define _REFGUID_DEFINED
286 | #define REFGUID const GUID &
287 | #endif // !_REFGUID_DEFINED
288 | #else // !__cplusplus
289 | #ifndef _REFGUID_DEFINED
290 | #define _REFGUID_DEFINED
291 | #define REFGUID const GUID * const
292 | #endif // !_REFGUID_DEFINED
293 | #endif // !__cplusplus
294 |
295 | #ifndef ARRAYSIZE
296 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
297 | #endif
298 |
299 | //
300 | //////////////////////////////////////////////////////////////////////////////
301 |
302 | #ifdef __cplusplus
303 | extern "C" {
304 | #endif // __cplusplus
305 |
306 | /////////////////////////////////////////////////// Instruction Target Macros.
307 | //
308 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0)
309 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1)
310 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0"
311 |
312 | extern const GUID DETOUR_EXE_RESTORE_GUID;
313 | extern const GUID DETOUR_EXE_HELPER_GUID;
314 |
315 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
316 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
317 |
318 | /////////////////////////////////////////////////////////// Binary Structures.
319 | //
320 | #pragma pack(push, 8)
321 | typedef struct _DETOUR_SECTION_HEADER
322 | {
323 | DWORD cbHeaderSize;
324 | DWORD nSignature;
325 | DWORD nDataOffset;
326 | DWORD cbDataSize;
327 |
328 | DWORD nOriginalImportVirtualAddress;
329 | DWORD nOriginalImportSize;
330 | DWORD nOriginalBoundImportVirtualAddress;
331 | DWORD nOriginalBoundImportSize;
332 |
333 | DWORD nOriginalIatVirtualAddress;
334 | DWORD nOriginalIatSize;
335 | DWORD nOriginalSizeOfImage;
336 | DWORD cbPrePE;
337 |
338 | DWORD nOriginalClrFlags;
339 | DWORD reserved1;
340 | DWORD reserved2;
341 | DWORD reserved3;
342 |
343 | // Followed by cbPrePE bytes of data.
344 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER;
345 |
346 | typedef struct _DETOUR_SECTION_RECORD
347 | {
348 | DWORD cbBytes;
349 | DWORD nReserved;
350 | GUID guid;
351 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD;
352 |
353 | typedef struct _DETOUR_CLR_HEADER
354 | {
355 | // Header versioning
356 | ULONG cb;
357 | USHORT MajorRuntimeVersion;
358 | USHORT MinorRuntimeVersion;
359 |
360 | // Symbol table and startup information
361 | IMAGE_DATA_DIRECTORY MetaData;
362 | ULONG Flags;
363 |
364 | // Followed by the rest of the IMAGE_COR20_HEADER
365 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER;
366 |
367 | typedef struct _DETOUR_EXE_RESTORE
368 | {
369 | DWORD cb;
370 | DWORD cbidh;
371 | DWORD cbinh;
372 | DWORD cbclr;
373 |
374 | PBYTE pidh;
375 | PBYTE pinh;
376 | PBYTE pclr;
377 |
378 | IMAGE_DOS_HEADER idh;
379 | union {
380 | IMAGE_NT_HEADERS inh;
381 | IMAGE_NT_HEADERS32 inh32;
382 | IMAGE_NT_HEADERS64 inh64;
383 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) +
384 | sizeof(IMAGE_SECTION_HEADER) * 32];
385 | };
386 | DETOUR_CLR_HEADER clr;
387 |
388 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE;
389 |
390 | typedef struct _DETOUR_EXE_HELPER
391 | {
392 | DWORD cb;
393 | DWORD pid;
394 | DWORD nDlls;
395 | CHAR rDlls[4];
396 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER;
397 |
398 | #pragma pack(pop)
399 |
400 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \
401 | { \
402 | sizeof(DETOUR_SECTION_HEADER),\
403 | DETOUR_SECTION_HEADER_SIGNATURE,\
404 | sizeof(DETOUR_SECTION_HEADER),\
405 | (cbSectionSize),\
406 | \
407 | 0,\
408 | 0,\
409 | 0,\
410 | 0,\
411 | \
412 | 0,\
413 | 0,\
414 | 0,\
415 | 0,\
416 | }
417 |
418 | /////////////////////////////////////////////////////////////// Helper Macros.
419 | //
420 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
421 | #define DETOURS_STRINGIFY_(x) #x
422 |
423 | ///////////////////////////////////////////////////////////// Binary Typedefs.
424 | //
425 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(
426 | _In_opt_ PVOID pContext,
427 | _In_opt_ LPCSTR pszFile,
428 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile);
429 |
430 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)(
431 | _In_opt_ PVOID pContext,
432 | _In_ LPCSTR pszOrigFile,
433 | _In_ LPCSTR pszFile,
434 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile);
435 |
436 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)(
437 | _In_opt_ PVOID pContext,
438 | _In_ ULONG nOrigOrdinal,
439 | _In_ ULONG nOrdinal,
440 | _Out_ ULONG *pnOutOrdinal,
441 | _In_opt_ LPCSTR pszOrigSymbol,
442 | _In_opt_ LPCSTR pszSymbol,
443 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol);
444 |
445 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)(
446 | _In_opt_ PVOID pContext);
447 |
448 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext,
449 | _In_ ULONG nOrdinal,
450 | _In_opt_ LPCSTR pszName,
451 | _In_opt_ PVOID pCode);
452 |
453 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext,
454 | _In_opt_ HMODULE hModule,
455 | _In_opt_ LPCSTR pszFile);
456 |
457 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext,
458 | _In_ DWORD nOrdinal,
459 | _In_opt_ LPCSTR pszFunc,
460 | _In_opt_ PVOID pvFunc);
461 |
462 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter.
463 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext,
464 | _In_ DWORD nOrdinal,
465 | _In_opt_ LPCSTR pszFunc,
466 | _In_opt_ PVOID* ppvFunc);
467 |
468 | typedef VOID * PDETOUR_BINARY;
469 | typedef VOID * PDETOUR_LOADED_BINARY;
470 |
471 | //////////////////////////////////////////////////////////// Transaction APIs.
472 | //
473 | LONG WINAPI DetourTransactionBegin(VOID);
474 | LONG WINAPI DetourTransactionAbort(VOID);
475 | LONG WINAPI DetourTransactionCommit(VOID);
476 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer);
477 |
478 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread);
479 |
480 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer,
481 | _In_ PVOID pDetour);
482 |
483 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
484 | _In_ PVOID pDetour,
485 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline,
486 | _Out_opt_ PVOID *ppRealTarget,
487 | _Out_opt_ PVOID *ppRealDetour);
488 |
489 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer,
490 | _In_ PVOID pDetour);
491 |
492 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore);
493 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain);
494 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound);
495 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound);
496 |
497 | ////////////////////////////////////////////////////////////// Code Functions.
498 | //
499 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
500 | _In_ LPCSTR pszFunction);
501 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer,
502 | _Out_opt_ PVOID *ppGlobals);
503 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
504 | _Inout_opt_ PVOID *ppDstPool,
505 | _In_ PVOID pSrc,
506 | _Out_opt_ PVOID *ppTarget,
507 | _Out_opt_ LONG *plExtra);
508 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
509 | _In_ BOOL fLimitReferencesToModule);
510 |
511 | ///////////////////////////////////////////////////// Loaded Binary Functions.
512 | //
513 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr);
514 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast);
515 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule);
516 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule);
517 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
518 | _In_opt_ PVOID pContext,
519 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport);
520 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
521 | _In_opt_ PVOID pContext,
522 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
523 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc);
524 |
525 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
526 | _In_opt_ PVOID pContext,
527 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
528 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx);
529 |
530 | _Writable_bytes_(*pcbData)
531 | _Readable_bytes_(*pcbData)
532 | _Success_(return != NULL)
533 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
534 | _In_ REFGUID rguid,
535 | _Out_ DWORD *pcbData);
536 |
537 | _Writable_bytes_(*pcbData)
538 | _Readable_bytes_(*pcbData)
539 | _Success_(return != NULL)
540 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
541 | _Out_ DWORD * pcbData);
542 |
543 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule);
544 |
545 | ///////////////////////////////////////////////// Persistent Binary Functions.
546 | //
547 |
548 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile);
549 |
550 | _Writable_bytes_(*pcbData)
551 | _Readable_bytes_(*pcbData)
552 | _Success_(return != NULL)
553 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary,
554 | _Out_opt_ GUID *pGuid,
555 | _Out_ DWORD *pcbData,
556 | _Inout_ DWORD *pnIterator);
557 |
558 | _Writable_bytes_(*pcbData)
559 | _Readable_bytes_(*pcbData)
560 | _Success_(return != NULL)
561 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary,
562 | _In_ REFGUID rguid,
563 | _Out_ DWORD *pcbData);
564 |
565 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary,
566 | _In_ REFGUID rguid,
567 | _In_reads_opt_(cbData) PVOID pData,
568 | _In_ DWORD cbData);
569 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid);
570 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary);
571 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary);
572 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary,
573 | _In_opt_ PVOID pContext,
574 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway,
575 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile,
576 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol,
577 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit);
578 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile);
579 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary);
580 |
581 | /////////////////////////////////////////////////// Create Process & Load Dll.
582 | //
583 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)(
584 | _In_opt_ LPCSTR lpApplicationName,
585 | _Inout_opt_ LPSTR lpCommandLine,
586 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
587 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
588 | _In_ BOOL bInheritHandles,
589 | _In_ DWORD dwCreationFlags,
590 | _In_opt_ LPVOID lpEnvironment,
591 | _In_opt_ LPCSTR lpCurrentDirectory,
592 | _In_ LPSTARTUPINFOA lpStartupInfo,
593 | _Out_ LPPROCESS_INFORMATION lpProcessInformation);
594 |
595 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)(
596 | _In_opt_ LPCWSTR lpApplicationName,
597 | _Inout_opt_ LPWSTR lpCommandLine,
598 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
599 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
600 | _In_ BOOL bInheritHandles,
601 | _In_ DWORD dwCreationFlags,
602 | _In_opt_ LPVOID lpEnvironment,
603 | _In_opt_ LPCWSTR lpCurrentDirectory,
604 | _In_ LPSTARTUPINFOW lpStartupInfo,
605 | _Out_ LPPROCESS_INFORMATION lpProcessInformation);
606 |
607 | BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName,
608 | _Inout_opt_ LPSTR lpCommandLine,
609 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
610 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
611 | _In_ BOOL bInheritHandles,
612 | _In_ DWORD dwCreationFlags,
613 | _In_opt_ LPVOID lpEnvironment,
614 | _In_opt_ LPCSTR lpCurrentDirectory,
615 | _In_ LPSTARTUPINFOA lpStartupInfo,
616 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
617 | _In_ LPCSTR lpDllName,
618 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
619 |
620 | BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName,
621 | _Inout_opt_ LPWSTR lpCommandLine,
622 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
623 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
624 | _In_ BOOL bInheritHandles,
625 | _In_ DWORD dwCreationFlags,
626 | _In_opt_ LPVOID lpEnvironment,
627 | _In_opt_ LPCWSTR lpCurrentDirectory,
628 | _In_ LPSTARTUPINFOW lpStartupInfo,
629 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
630 | _In_ LPCSTR lpDllName,
631 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
632 |
633 | #ifdef UNICODE
634 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW
635 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW
636 | #else
637 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA
638 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA
639 | #endif // !UNICODE
640 |
641 | BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName,
642 | _Inout_opt_ LPSTR lpCommandLine,
643 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
644 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
645 | _In_ BOOL bInheritHandles,
646 | _In_ DWORD dwCreationFlags,
647 | _In_opt_ LPVOID lpEnvironment,
648 | _In_opt_ LPCSTR lpCurrentDirectory,
649 | _In_ LPSTARTUPINFOA lpStartupInfo,
650 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
651 | _In_ LPCSTR lpDllName,
652 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
653 |
654 | BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName,
655 | _Inout_opt_ LPWSTR lpCommandLine,
656 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
657 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
658 | _In_ BOOL bInheritHandles,
659 | _In_ DWORD dwCreationFlags,
660 | _In_opt_ LPVOID lpEnvironment,
661 | _In_opt_ LPCWSTR lpCurrentDirectory,
662 | _In_ LPSTARTUPINFOW lpStartupInfo,
663 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
664 | _In_ LPCSTR lpDllName,
665 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
666 |
667 | #ifdef UNICODE
668 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW
669 | #else
670 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA
671 | #endif // !UNICODE
672 |
673 | BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName,
674 | _Inout_opt_ LPSTR lpCommandLine,
675 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
676 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
677 | _In_ BOOL bInheritHandles,
678 | _In_ DWORD dwCreationFlags,
679 | _In_opt_ LPVOID lpEnvironment,
680 | _In_opt_ LPCSTR lpCurrentDirectory,
681 | _In_ LPSTARTUPINFOA lpStartupInfo,
682 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
683 | _In_ DWORD nDlls,
684 | _In_reads_(nDlls) LPCSTR *rlpDlls,
685 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
686 |
687 | BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName,
688 | _Inout_opt_ LPWSTR lpCommandLine,
689 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
690 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
691 | _In_ BOOL bInheritHandles,
692 | _In_ DWORD dwCreationFlags,
693 | _In_opt_ LPVOID lpEnvironment,
694 | _In_opt_ LPCWSTR lpCurrentDirectory,
695 | _In_ LPSTARTUPINFOW lpStartupInfo,
696 | _Out_ LPPROCESS_INFORMATION lpProcessInformation,
697 | _In_ DWORD nDlls,
698 | _In_reads_(nDlls) LPCSTR *rlpDlls,
699 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
700 |
701 | #ifdef UNICODE
702 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW
703 | #else
704 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA
705 | #endif // !UNICODE
706 |
707 | BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid,
708 | _In_ LPCSTR lpDllName,
709 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
710 |
711 | BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid,
712 | _In_ LPCSTR lpDllName,
713 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
714 |
715 | #ifdef UNICODE
716 | #define DetourProcessViaHelper DetourProcessViaHelperW
717 | #else
718 | #define DetourProcessViaHelper DetourProcessViaHelperA
719 | #endif // !UNICODE
720 |
721 | BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid,
722 | _In_ DWORD nDlls,
723 | _In_reads_(nDlls) LPCSTR *rlpDlls,
724 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
725 |
726 | BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid,
727 | _In_ DWORD nDlls,
728 | _In_reads_(nDlls) LPCSTR *rlpDlls,
729 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
730 |
731 | #ifdef UNICODE
732 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW
733 | #else
734 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA
735 | #endif // !UNICODE
736 |
737 | BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess,
738 | _In_reads_(nDlls) LPCSTR *rlpDlls,
739 | _In_ DWORD nDlls);
740 |
741 | BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess,
742 | _In_ HMODULE hImage,
743 | _In_ BOOL bIs32Bit,
744 | _In_reads_(nDlls) LPCSTR *rlpDlls,
745 | _In_ DWORD nDlls);
746 |
747 | BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess,
748 | _In_ REFGUID rguid,
749 | _In_reads_bytes_(cbData) PVOID pvData,
750 | _In_ DWORD cbData);
751 | BOOL WINAPI DetourRestoreAfterWith(VOID);
752 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
753 | _In_ DWORD cbData);
754 | BOOL WINAPI DetourIsHelperProcess(VOID);
755 | VOID CALLBACK DetourFinishHelperProcess(_In_ HWND,
756 | _In_ HINSTANCE,
757 | _In_ LPSTR,
758 | _In_ INT);
759 |
760 | //
761 | //////////////////////////////////////////////////////////////////////////////
762 | #ifdef __cplusplus
763 | }
764 | #endif // __cplusplus
765 |
766 | //////////////////////////////////////////////// Detours Internal Definitions.
767 | //
768 | #ifdef __cplusplus
769 | #ifdef DETOURS_INTERNAL
770 |
771 | #define NOTHROW
772 | // #define NOTHROW (nothrow)
773 |
774 | //////////////////////////////////////////////////////////////////////////////
775 | //
776 | #if (_MSC_VER < 1299)
777 | #include
778 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
779 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
780 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO;
781 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO;
782 |
783 | static inline
784 | LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval)
785 | {
786 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval);
787 | }
788 | #else
789 | #pragma warning(push)
790 | #pragma warning(disable:4091) // empty typedef
791 | #include
792 | #pragma warning(pop)
793 | #endif
794 |
795 | #ifdef IMAGEAPI // defined by DBGHELP.H
796 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion);
797 |
798 | typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess,
799 | _In_opt_ LPCSTR UserSearchPath,
800 | _In_ BOOL fInvadeProcess);
801 | typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions);
802 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
803 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess,
804 | _In_opt_ HANDLE hFile,
805 | _In_ LPSTR ImageName,
806 | _In_opt_ LPSTR ModuleName,
807 | _In_ DWORD64 BaseOfDll,
808 | _In_opt_ DWORD SizeOfDll);
809 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess,
810 | _In_ DWORD64 qwAddr,
811 | _Out_ PIMAGEHLP_MODULE64 ModuleInfo);
812 | typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess,
813 | _In_ LPSTR Name,
814 | _Out_ PSYMBOL_INFO Symbol);
815 |
816 | typedef struct _DETOUR_SYM_INFO
817 | {
818 | HANDLE hProcess;
819 | HMODULE hDbgHelp;
820 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx;
821 | PF_SymInitialize pfSymInitialize;
822 | PF_SymSetOptions pfSymSetOptions;
823 | PF_SymGetOptions pfSymGetOptions;
824 | PF_SymLoadModule64 pfSymLoadModule64;
825 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64;
826 | PF_SymFromName pfSymFromName;
827 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO;
828 |
829 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID);
830 |
831 | #endif // IMAGEAPI
832 |
833 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS)
834 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier)
835 | #endif
836 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
837 |
838 | #ifndef DETOUR_TRACE
839 | #if DETOUR_DEBUG
840 | #define DETOUR_TRACE(x) printf x
841 | #define DETOUR_BREAK() __debugbreak()
842 | #include
843 | #include
844 | #else
845 | #define DETOUR_TRACE(x)
846 | #define DETOUR_BREAK()
847 | #endif
848 | #endif
849 |
850 | #if 1 || defined(DETOURS_IA64)
851 |
852 | //
853 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle.
854 | //
855 |
856 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3)
857 |
858 | #define DETOUR_IA64_TEMPLATE_OFFSET (0)
859 | #define DETOUR_IA64_TEMPLATE_SIZE (5)
860 |
861 | #define DETOUR_IA64_INSTRUCTION_SIZE (41)
862 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE)
863 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE)
864 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE)
865 |
866 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128);
867 |
868 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE
869 | {
870 | public:
871 | union
872 | {
873 | BYTE data[16];
874 | UINT64 wide[2];
875 | };
876 |
877 | enum {
878 | A_UNIT = 1u,
879 | I_UNIT = 2u,
880 | M_UNIT = 3u,
881 | B_UNIT = 4u,
882 | F_UNIT = 5u,
883 | L_UNIT = 6u,
884 | X_UNIT = 7u,
885 | };
886 | struct DETOUR_IA64_METADATA
887 | {
888 | ULONG nTemplate : 8; // Instruction template.
889 | ULONG nUnit0 : 4; // Unit for slot 0
890 | ULONG nUnit1 : 4; // Unit for slot 1
891 | ULONG nUnit2 : 4; // Unit for slot 2
892 | };
893 |
894 | protected:
895 | static const DETOUR_IA64_METADATA s_rceCopyTable[33];
896 |
897 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const;
898 |
899 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst,
900 | _In_ BYTE slot,
901 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const;
902 |
903 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0
904 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0.
905 |
906 | // 00
907 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0.
908 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0]
909 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5]
910 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42]
911 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46]
912 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83]
913 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87]
914 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124]
915 | BYTE GetTemplate() const;
916 | // Get 4 bit opcodes.
917 | BYTE GetInst0() const;
918 | BYTE GetInst1() const;
919 | BYTE GetInst2() const;
920 | BYTE GetUnit(BYTE slot) const;
921 | BYTE GetUnit0() const;
922 | BYTE GetUnit1() const;
923 | BYTE GetUnit2() const;
924 | // Get 37 bit data.
925 | UINT64 GetData0() const;
926 | UINT64 GetData1() const;
927 | UINT64 GetData2() const;
928 |
929 | // Get/set the full 41 bit instructions.
930 | UINT64 GetInstruction(BYTE slot) const;
931 | UINT64 GetInstruction0() const;
932 | UINT64 GetInstruction1() const;
933 | UINT64 GetInstruction2() const;
934 | void SetInstruction(BYTE slot, UINT64 instruction);
935 | void SetInstruction0(UINT64 instruction);
936 | void SetInstruction1(UINT64 instruction);
937 | void SetInstruction2(UINT64 instruction);
938 |
939 | // Get/set bitfields.
940 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count);
941 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field);
942 |
943 | // Get specific read-only fields.
944 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode
945 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension
946 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension
947 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension
948 |
949 | // Get/set specific fields.
950 | static UINT64 GetImm7a(UINT64 instruction);
951 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a);
952 | static UINT64 GetImm13c(UINT64 instruction);
953 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c);
954 | static UINT64 GetSignBit(UINT64 instruction);
955 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit);
956 | static UINT64 GetImm20a(UINT64 instruction);
957 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a);
958 | static UINT64 GetImm20b(UINT64 instruction);
959 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b);
960 |
961 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset);
962 |
963 | BOOL IsMovlGp() const;
964 |
965 | VOID SetInst(BYTE Slot, BYTE nInst);
966 | VOID SetInst0(BYTE nInst);
967 | VOID SetInst1(BYTE nInst);
968 | VOID SetInst2(BYTE nInst);
969 | VOID SetData(BYTE Slot, UINT64 nData);
970 | VOID SetData0(UINT64 nData);
971 | VOID SetData1(UINT64 nData);
972 | VOID SetData2(UINT64 nData);
973 | BOOL SetNop(BYTE Slot);
974 | BOOL SetNop0();
975 | BOOL SetNop1();
976 | BOOL SetNop2();
977 |
978 | public:
979 | BOOL IsBrl() const;
980 | VOID SetBrl();
981 | VOID SetBrl(UINT64 target);
982 | UINT64 GetBrlTarget() const;
983 | VOID SetBrlTarget(UINT64 target);
984 | VOID SetBrlImm(UINT64 imm);
985 | UINT64 GetBrlImm() const;
986 |
987 | UINT64 GetMovlGp() const;
988 | VOID SetMovlGp(UINT64 gp);
989 |
990 | VOID SetStop();
991 |
992 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const;
993 | };
994 | #endif // DETOURS_IA64
995 |
996 | #ifdef DETOURS_ARM
997 |
998 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1))
999 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1))
1000 |
1001 | #endif // DETOURS_ARM
1002 |
1003 | //////////////////////////////////////////////////////////////////////////////
1004 |
1005 | #ifdef __cplusplus
1006 | extern "C" {
1007 | #endif // __cplusplus
1008 |
1009 | #define DETOUR_OFFLINE_LIBRARY(x) \
1010 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \
1011 | _Inout_opt_ PVOID *ppDstPool, \
1012 | _In_ PVOID pSrc, \
1013 | _Out_opt_ PVOID *ppTarget, \
1014 | _Out_opt_ LONG *plExtra); \
1015 | \
1016 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \
1017 | _In_ BOOL fLimitReferencesToModule); \
1018 |
1019 | DETOUR_OFFLINE_LIBRARY(X86)
1020 | DETOUR_OFFLINE_LIBRARY(X64)
1021 | DETOUR_OFFLINE_LIBRARY(ARM)
1022 | DETOUR_OFFLINE_LIBRARY(ARM64)
1023 | DETOUR_OFFLINE_LIBRARY(IA64)
1024 |
1025 | #undef DETOUR_OFFLINE_LIBRARY
1026 |
1027 | //////////////////////////////////////////////////////////////////////////////
1028 | //
1029 | // Helpers for manipulating page protection.
1030 | //
1031 |
1032 | _Success_(return != FALSE)
1033 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess,
1034 | _In_ PVOID pAddress,
1035 | _In_ SIZE_T nSize,
1036 | _In_ DWORD dwNewProtect,
1037 | _Out_ PDWORD pdwOldProtect);
1038 |
1039 | _Success_(return != FALSE)
1040 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress,
1041 | _In_ SIZE_T nSize,
1042 | _In_ DWORD dwNewProtect,
1043 | _Out_ PDWORD pdwOldProtect);
1044 | #ifdef __cplusplus
1045 | }
1046 | #endif // __cplusplus
1047 |
1048 | //////////////////////////////////////////////////////////////////////////////
1049 |
1050 | #define MM_ALLOCATION_GRANULARITY 0x10000
1051 |
1052 | //////////////////////////////////////////////////////////////////////////////
1053 |
1054 | #endif // DETOURS_INTERNAL
1055 | #endif // __cplusplus
1056 |
1057 | #endif // _DETOURS_H_
1058 | //
1059 | //////////////////////////////////////////////////////////////// End of File.
1060 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/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
15 | #else
16 | #ifndef DETOURS_STRINGIFY
17 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
18 | #define DETOURS_STRINGIFY_(x) #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 DETOUR_STRINGIFY(DETOURS_BITS)
28 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/disolarm.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_ARM_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/disolarm64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_ARM64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/disolia64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_IA64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/disolx64.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_X64_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/disolx86.cpp:
--------------------------------------------------------------------------------
1 | #define DETOURS_X86_OFFLINE_LIBRARY
2 | #include "disasm.cpp"
3 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/image.cpp:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Image manipulation functions (image.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 | // Used for for payloads, byways, and imports.
10 | //
11 |
12 | #if _MSC_VER >= 1900
13 | #pragma warning(push)
14 | #pragma warning(disable:4091) // empty typedef
15 | #endif
16 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
17 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
18 | #include
19 | #if _MSC_VER >= 1310
20 | #pragma warning(push)
21 | #if _MSC_VER > 1400
22 | #pragma warning(disable:6102 6103) // /analyze warnings
23 | #endif
24 | #include
25 | #pragma warning(pop)
26 | #endif
27 |
28 | #if (_MSC_VER < 1299)
29 | #pragma warning(disable: 4710)
30 | #endif
31 |
32 | // #define DETOUR_DEBUG 1
33 | #define DETOURS_INTERNAL
34 |
35 | #include "detours.h"
36 |
37 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
38 | #error detours.h version mismatch
39 | #endif
40 |
41 | #if _MSC_VER >= 1900
42 | #pragma warning(pop)
43 | #endif
44 |
45 | namespace Detour
46 | {
47 | //////////////////////////////////////////////////////////////////////////////
48 | //
49 | #ifndef _STRSAFE_H_INCLUDED_
50 | _Must_inspect_result_
51 | static inline HRESULT StringCchLengthA(
52 | _In_reads_or_z_(cchMax) LPCSTR psz,
53 | _In_
54 | _In_range_(1, STRSAFE_MAX_CCH) size_t cchMax,
55 | _Out_opt_
56 | _Deref_out_range_(<, cchMax)
57 | _Deref_out_range_(<=, _String_length_(psz))
58 | _Out_ size_t* pcch)
59 | {
60 | HRESULT hr = S_OK;
61 | size_t cchMaxPrev = cchMax;
62 |
63 | if (cchMax > 2147483647) {
64 | return ERROR_INVALID_PARAMETER;
65 | }
66 |
67 | while (cchMax && (*psz != '\0')) {
68 | psz++;
69 | cchMax--;
70 | }
71 |
72 | if (cchMax == 0) {
73 | // the string is longer than cchMax
74 | hr = ERROR_INVALID_PARAMETER;
75 | }
76 |
77 | if (SUCCEEDED(hr) && pcch) {
78 | *pcch = cchMaxPrev - cchMax;
79 | }
80 |
81 | return hr;
82 | }
83 |
84 | _Must_inspect_result_
85 | static inline HRESULT StringCchCopyA(
86 | _Out_writes_(cchDest) _Always_(_Post_z_) LPSTR pszDest,
87 | _In_ size_t cchDest,
88 | _In_ LPCSTR pszSrc)
89 | {
90 | HRESULT hr = S_OK;
91 |
92 | if (cchDest == 0) {
93 | // can not null terminate a zero-byte dest buffer
94 | hr = ERROR_INVALID_PARAMETER;
95 | }
96 | else {
97 | while (cchDest && (*pszSrc != '\0')) {
98 | *pszDest++ = *pszSrc++;
99 | cchDest--;
100 | }
101 |
102 | if (cchDest == 0) {
103 | // we are going to truncate pszDest
104 | pszDest--;
105 | hr = ERROR_INVALID_PARAMETER;
106 | }
107 |
108 | *pszDest= '\0';
109 | }
110 |
111 | return hr;
112 | }
113 |
114 | _Must_inspect_result_
115 | static inline HRESULT StringCchCatA(
116 | _Out_writes_(cchDest) _Always_(_Post_z_) LPSTR pszDest,
117 | _In_ size_t cchDest,
118 | _In_ LPCSTR pszSrc)
119 | {
120 | HRESULT hr;
121 | size_t cchDestCurrent;
122 |
123 | if (cchDest > 2147483647){
124 | return ERROR_INVALID_PARAMETER;
125 | }
126 |
127 | hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent);
128 |
129 | if (SUCCEEDED(hr) && cchDestCurrent < cchDest) {
130 | hr = StringCchCopyA(pszDest + cchDestCurrent,
131 | cchDest - cchDestCurrent,
132 | pszSrc);
133 | }
134 |
135 | return hr;
136 | }
137 |
138 | #endif
139 |
140 | ///////////////////////////////////////////////////////////////////////////////
141 | //
142 | class CImageData
143 | {
144 | friend class CImage;
145 |
146 | public:
147 | CImageData(PBYTE pbData, DWORD cbData);
148 | ~CImageData();
149 |
150 | PBYTE Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
151 | PBYTE Find(REFGUID rguid, DWORD *pcbData);
152 | PBYTE Set(REFGUID rguid, PBYTE pbData, DWORD cbData);
153 |
154 | BOOL Delete(REFGUID rguid);
155 | BOOL Purge();
156 |
157 | BOOL IsEmpty() { return m_cbData == 0; }
158 | BOOL IsValid();
159 |
160 | protected:
161 | BOOL SizeTo(DWORD cbData);
162 |
163 | protected:
164 | _Field_size_(m_cbAlloc)
165 | PBYTE m_pbData;
166 | DWORD m_cbData;
167 | DWORD m_cbAlloc;
168 | };
169 |
170 | class CImageImportFile
171 | {
172 | friend class CImage;
173 | friend class CImageImportName;
174 |
175 | public:
176 | CImageImportFile();
177 | ~CImageImportFile();
178 |
179 | public:
180 | CImageImportFile * m_pNextFile;
181 | BOOL m_fByway;
182 |
183 | _Field_size_(m_nImportNames)
184 | CImageImportName * m_pImportNames;
185 | DWORD m_nImportNames;
186 |
187 | DWORD m_rvaOriginalFirstThunk;
188 | DWORD m_rvaFirstThunk;
189 |
190 | DWORD m_nForwarderChain;
191 | LPCSTR m_pszOrig;
192 | LPCSTR m_pszName;
193 | };
194 |
195 | class CImageImportName
196 | {
197 | friend class CImage;
198 | friend class CImageImportFile;
199 |
200 | public:
201 | CImageImportName();
202 | ~CImageImportName();
203 |
204 | public:
205 | WORD m_nHint;
206 | ULONG m_nOrig;
207 | ULONG m_nOrdinal;
208 | LPCSTR m_pszOrig;
209 | LPCSTR m_pszName;
210 | };
211 |
212 | class CImage
213 | {
214 | friend class CImageThunks;
215 | friend class CImageChars;
216 | friend class CImageImportFile;
217 | friend class CImageImportName;
218 |
219 | public:
220 | CImage();
221 | ~CImage();
222 |
223 | static CImage * IsValid(PDETOUR_BINARY pBinary);
224 |
225 | public: // File Functions
226 | BOOL Read(HANDLE hFile);
227 | BOOL Write(HANDLE hFile);
228 | BOOL Close();
229 |
230 | public: // Manipulation Functions
231 | PBYTE DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
232 | PBYTE DataFind(REFGUID rguid, DWORD *pcbData);
233 | PBYTE DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData);
234 | BOOL DataDelete(REFGUID rguid);
235 | BOOL DataPurge();
236 |
237 | BOOL EditImports(PVOID pContext,
238 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
239 | PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
240 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
241 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback);
242 |
243 | protected:
244 | BOOL WriteFile(HANDLE hFile,
245 | LPCVOID lpBuffer,
246 | DWORD nNumberOfBytesToWrite,
247 | LPDWORD lpNumberOfBytesWritten);
248 | BOOL CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData);
249 | BOOL ZeroFileData(HANDLE hFile, DWORD cbData);
250 | BOOL AlignFileData(HANDLE hFile);
251 |
252 | BOOL SizeOutputBuffer(DWORD cbData);
253 | PBYTE AllocateOutput(DWORD cbData, DWORD *pnVirtAddr);
254 |
255 | PVOID RvaToVa(ULONG_PTR nRva);
256 | DWORD RvaToFileOffset(DWORD nRva);
257 |
258 | DWORD FileAlign(DWORD nAddr);
259 | DWORD SectionAlign(DWORD nAddr);
260 |
261 | BOOL CheckImportsNeeded(DWORD *pnTables,
262 | DWORD *pnThunks,
263 | DWORD *pnChars);
264 |
265 | CImageImportFile * NewByway(_In_ LPCSTR pszName);
266 |
267 | private:
268 | DWORD m_dwValidSignature;
269 | CImageData * m_pImageData; // Read & Write
270 |
271 | HANDLE m_hMap; // Read & Write
272 | PBYTE m_pMap; // Read & Write
273 |
274 | DWORD m_nNextFileAddr; // Write
275 | DWORD m_nNextVirtAddr; // Write
276 |
277 | IMAGE_DOS_HEADER m_DosHeader; // Read & Write
278 | IMAGE_NT_HEADERS m_NtHeader; // Read & Write
279 | IMAGE_SECTION_HEADER m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
280 |
281 | DWORD m_nPrePE;
282 | DWORD m_cbPrePE;
283 | DWORD m_cbPostPE;
284 |
285 | DWORD m_nPeOffset;
286 | DWORD m_nSectionsOffset;
287 | DWORD m_nExtraOffset;
288 | DWORD m_nFileSize;
289 |
290 | DWORD m_nOutputVirtAddr;
291 | DWORD m_nOutputVirtSize;
292 | DWORD m_nOutputFileAddr;
293 |
294 | _Field_size_(m_cbOutputBuffer)
295 | PBYTE m_pbOutputBuffer;
296 | DWORD m_cbOutputBuffer;
297 |
298 | CImageImportFile * m_pImportFiles;
299 | DWORD m_nImportFiles;
300 |
301 | BOOL m_fHadDetourSection;
302 |
303 | private:
304 | enum {
305 | DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01, // "Dtr\0"
306 | };
307 | };
308 |
309 | //////////////////////////////////////////////////////////////////////////////
310 | //
311 | static BYTE s_rbDosCode[0x10] = {
312 | 0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD,
313 | 0x21,0xB8,0x01,0x4C,0xCD,0x21,'*','*'
314 | };
315 |
316 | static inline DWORD Max(DWORD a, DWORD b)
317 | {
318 | return a > b ? a : b;
319 | }
320 |
321 | static inline DWORD Align(DWORD a, DWORD size)
322 | {
323 | size--;
324 | return (a + size) & ~size;
325 | }
326 |
327 | static inline DWORD QuadAlign(DWORD a)
328 | {
329 | return Align(a, 8);
330 | }
331 |
332 | static LPCSTR DuplicateString(_In_ LPCSTR pszIn)
333 | {
334 | if (pszIn == NULL) {
335 | return NULL;
336 | }
337 |
338 | size_t cch;
339 | HRESULT hr = StringCchLengthA(pszIn, 8192, &cch);
340 | if (FAILED(hr)) {
341 | SetLastError(ERROR_INVALID_PARAMETER);
342 | return NULL;
343 | }
344 |
345 | PCHAR pszOut = new NOTHROW CHAR [cch + 1];
346 | if (pszOut == NULL) {
347 | SetLastError(ERROR_OUTOFMEMORY);
348 | return NULL;
349 | }
350 |
351 | hr = StringCchCopyA(pszOut, cch + 1, pszIn);
352 | if (FAILED(hr)) {
353 | delete[] pszOut;
354 | return NULL;
355 | }
356 |
357 | return pszOut;
358 | }
359 |
360 | static VOID ReleaseString(_In_opt_ LPCSTR psz)
361 | {
362 | if (psz != NULL) {
363 | delete[] psz;
364 | }
365 | }
366 |
367 | //////////////////////////////////////////////////////////////////////////////
368 | //
369 | CImageImportFile::CImageImportFile()
370 | {
371 | m_pNextFile = NULL;
372 | m_fByway = FALSE;
373 |
374 | m_pImportNames = NULL;
375 | m_nImportNames = 0;
376 |
377 | m_rvaOriginalFirstThunk = 0;
378 | m_rvaFirstThunk = 0;
379 |
380 | m_nForwarderChain = (UINT)0;
381 | m_pszName = NULL;
382 | m_pszOrig = NULL;
383 | }
384 |
385 | CImageImportFile::~CImageImportFile()
386 | {
387 | if (m_pNextFile) {
388 | delete m_pNextFile;
389 | m_pNextFile = NULL;
390 | }
391 | if (m_pImportNames) {
392 | delete[] m_pImportNames;
393 | m_pImportNames = NULL;
394 | m_nImportNames = 0;
395 | }
396 | if (m_pszName) {
397 | delete[] m_pszName;
398 | m_pszName = NULL;
399 | }
400 | if (m_pszOrig) {
401 | delete[] m_pszOrig;
402 | m_pszOrig = NULL;
403 | }
404 | }
405 |
406 | CImageImportName::CImageImportName()
407 | {
408 | m_nOrig = 0;
409 | m_nOrdinal = 0;
410 | m_nHint = 0;
411 | m_pszName = NULL;
412 | m_pszOrig = NULL;
413 | }
414 |
415 | CImageImportName::~CImageImportName()
416 | {
417 | if (m_pszName) {
418 | delete[] m_pszName;
419 | m_pszName = NULL;
420 | }
421 | if (m_pszOrig) {
422 | delete[] m_pszOrig;
423 | m_pszOrig = NULL;
424 | }
425 | }
426 |
427 | //////////////////////////////////////////////////////////////////////////////
428 | //
429 | CImageData::CImageData(PBYTE pbData, DWORD cbData)
430 | {
431 | m_pbData = pbData;
432 | m_cbData = cbData;
433 | m_cbAlloc = 0;
434 | }
435 |
436 | CImageData::~CImageData()
437 | {
438 | IsValid();
439 |
440 | if (m_cbAlloc == 0) {
441 | m_pbData = NULL;
442 | }
443 | if (m_pbData) {
444 | delete[] m_pbData;
445 | m_pbData = NULL;
446 | }
447 | m_cbData = 0;
448 | m_cbAlloc = 0;
449 | }
450 |
451 | BOOL CImageData::SizeTo(DWORD cbData)
452 | {
453 | IsValid();
454 |
455 | if (cbData <= m_cbAlloc) {
456 | return TRUE;
457 | }
458 |
459 | PBYTE pbNew = new NOTHROW BYTE [cbData];
460 | if (pbNew == NULL) {
461 | SetLastError(ERROR_OUTOFMEMORY);
462 | return FALSE;
463 | }
464 |
465 | if (m_pbData) {
466 | CopyMemory(pbNew, m_pbData, m_cbData);
467 | if (m_cbAlloc > 0) {
468 | delete[] m_pbData;
469 | }
470 | m_pbData = NULL;
471 | }
472 | m_pbData = pbNew;
473 | m_cbAlloc = cbData;
474 |
475 | IsValid();
476 |
477 | return TRUE;
478 | }
479 |
480 | BOOL CImageData::Purge()
481 | {
482 | m_cbData = 0;
483 |
484 | IsValid();
485 |
486 | return TRUE;
487 | }
488 |
489 | BOOL CImageData::IsValid()
490 | {
491 | if (m_pbData == NULL) {
492 | return TRUE;
493 | }
494 |
495 | PBYTE pbBeg = m_pbData;
496 | PBYTE pbEnd = m_pbData + m_cbData;
497 |
498 | for (PBYTE pbIter = pbBeg; pbIter < pbEnd;) {
499 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)pbIter;
500 |
501 | if (pRecord->cbBytes < sizeof(DETOUR_SECTION_RECORD)) {
502 | return FALSE;
503 | }
504 | if (pRecord->nReserved != 0) {
505 | return FALSE;
506 | }
507 |
508 | pbIter += pRecord->cbBytes;
509 | }
510 | return TRUE;
511 | }
512 |
513 | PBYTE CImageData::Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
514 | {
515 | IsValid();
516 |
517 | if (pnIterator == NULL ||
518 | m_cbData < *pnIterator + sizeof(DETOUR_SECTION_RECORD)) {
519 |
520 | if (pcbData) {
521 | *pcbData = 0;
522 | }
523 | if (pGuid) {
524 | ZeroMemory(pGuid, sizeof(*pGuid));
525 | }
526 | return NULL;
527 | }
528 |
529 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + *pnIterator);
530 |
531 | if (pGuid) {
532 | *pGuid = pRecord->guid;
533 | }
534 | if (pcbData) {
535 | *pcbData = pRecord->cbBytes - sizeof(DETOUR_SECTION_RECORD);
536 | }
537 | *pnIterator = (LONG)(((PBYTE)pRecord - m_pbData) + pRecord->cbBytes);
538 |
539 | return (PBYTE)(pRecord + 1);
540 | }
541 |
542 | PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)
543 | {
544 | IsValid();
545 |
546 | DWORD cbBytes = sizeof(DETOUR_SECTION_RECORD);
547 | for (DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes) {
548 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + nOffset);
549 |
550 | cbBytes = pRecord->cbBytes;
551 | if (cbBytes > m_cbData) {
552 | break;
553 | }
554 | if (cbBytes < sizeof(DETOUR_SECTION_RECORD)) {
555 | continue;
556 | }
557 |
558 | if (pRecord->guid.Data1 == rguid.Data1 &&
559 | pRecord->guid.Data2 == rguid.Data2 &&
560 | pRecord->guid.Data3 == rguid.Data3 &&
561 | pRecord->guid.Data4[0] == rguid.Data4[0] &&
562 | pRecord->guid.Data4[1] == rguid.Data4[1] &&
563 | pRecord->guid.Data4[2] == rguid.Data4[2] &&
564 | pRecord->guid.Data4[3] == rguid.Data4[3] &&
565 | pRecord->guid.Data4[4] == rguid.Data4[4] &&
566 | pRecord->guid.Data4[5] == rguid.Data4[5] &&
567 | pRecord->guid.Data4[6] == rguid.Data4[6] &&
568 | pRecord->guid.Data4[7] == rguid.Data4[7]) {
569 |
570 | *pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
571 | return (PBYTE)(pRecord + 1);
572 | }
573 | }
574 |
575 | if (pcbData) {
576 | *pcbData = 0;
577 | }
578 | return NULL;
579 | }
580 |
581 | BOOL CImageData::Delete(REFGUID rguid)
582 | {
583 | IsValid();
584 |
585 | PBYTE pbFound = NULL;
586 | DWORD cbFound = 0;
587 |
588 | pbFound = Find(rguid, &cbFound);
589 | if (pbFound == NULL) {
590 | SetLastError(ERROR_MOD_NOT_FOUND);
591 | return FALSE;
592 | }
593 |
594 | pbFound -= sizeof(DETOUR_SECTION_RECORD);
595 | cbFound += sizeof(DETOUR_SECTION_RECORD);
596 |
597 | PBYTE pbRestData = pbFound + cbFound;
598 | DWORD cbRestData = m_cbData - (LONG)(pbRestData - m_pbData);
599 |
600 | if (cbRestData) {
601 | MoveMemory(pbFound, pbRestData, cbRestData);
602 | }
603 | m_cbData -= cbFound;
604 |
605 | IsValid();
606 | return TRUE;
607 | }
608 |
609 | PBYTE CImageData::Set(REFGUID rguid, PBYTE pbData, DWORD cbData)
610 | {
611 | IsValid();
612 | Delete(rguid);
613 |
614 | DWORD cbAlloc = QuadAlign(cbData);
615 |
616 | if (!SizeTo(m_cbData + cbAlloc + sizeof(DETOUR_SECTION_RECORD))) {
617 | return NULL;
618 | }
619 |
620 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + m_cbData);
621 | pRecord->cbBytes = cbAlloc + sizeof(DETOUR_SECTION_RECORD);
622 | pRecord->nReserved = 0;
623 | pRecord->guid = rguid;
624 |
625 | PBYTE pbDest = (PBYTE)(pRecord + 1);
626 | if (pbData) {
627 | CopyMemory(pbDest, pbData, cbData);
628 | if (cbData < cbAlloc) {
629 | ZeroMemory(pbDest + cbData, cbAlloc - cbData);
630 | }
631 | }
632 | else {
633 | if (cbAlloc > 0) {
634 | ZeroMemory(pbDest, cbAlloc);
635 | }
636 | }
637 |
638 | m_cbData += cbAlloc + sizeof(DETOUR_SECTION_RECORD);
639 |
640 | IsValid();
641 | return pbDest;
642 | }
643 |
644 | //////////////////////////////////////////////////////////////////////////////
645 | //
646 | class CImageThunks
647 | {
648 | private:
649 | CImage * m_pImage;
650 | PIMAGE_THUNK_DATA m_pThunks;
651 | DWORD m_nThunks;
652 | DWORD m_nThunksMax;
653 | DWORD m_nThunkVirtAddr;
654 |
655 | public:
656 | CImageThunks(CImage *pImage, DWORD nThunksMax, DWORD *pnAddr)
657 | {
658 | m_pImage = pImage;
659 | m_nThunks = 0;
660 | m_nThunksMax = nThunksMax;
661 | m_pThunks = (PIMAGE_THUNK_DATA)
662 | m_pImage->AllocateOutput(sizeof(IMAGE_THUNK_DATA) * nThunksMax,
663 | &m_nThunkVirtAddr);
664 | *pnAddr = m_nThunkVirtAddr;
665 | }
666 |
667 | PIMAGE_THUNK_DATA Current(DWORD *pnVirtAddr)
668 | {
669 | if (m_nThunksMax > 1) {
670 | *pnVirtAddr = m_nThunkVirtAddr;
671 | return m_pThunks;
672 | }
673 | *pnVirtAddr = 0;
674 | return NULL;
675 | }
676 |
677 | PIMAGE_THUNK_DATA Allocate(ULONG_PTR nData, DWORD *pnVirtAddr)
678 | {
679 | if (m_nThunks < m_nThunksMax) {
680 | *pnVirtAddr = m_nThunkVirtAddr;
681 |
682 | m_nThunks++;
683 | m_nThunkVirtAddr += sizeof(IMAGE_THUNK_DATA);
684 | m_pThunks->u1.Ordinal = nData;
685 | return m_pThunks++;
686 | }
687 | *pnVirtAddr = 0;
688 | return NULL;
689 | }
690 |
691 | DWORD Size()
692 | {
693 | return m_nThunksMax * sizeof(IMAGE_THUNK_DATA);
694 | }
695 | };
696 |
697 | //////////////////////////////////////////////////////////////////////////////
698 | //
699 | class CImageChars
700 | {
701 | private:
702 | CImage * m_pImage;
703 | PCHAR m_pChars;
704 | DWORD m_nChars;
705 | DWORD m_nCharsMax;
706 | DWORD m_nCharVirtAddr;
707 |
708 | public:
709 | CImageChars(CImage *pImage, _In_ DWORD nCharsMax, _Out_ DWORD *pnAddr)
710 | {
711 | m_pImage = pImage;
712 | m_nChars = 0;
713 | m_nCharsMax = nCharsMax;
714 | m_pChars = (PCHAR)m_pImage->AllocateOutput(nCharsMax, &m_nCharVirtAddr);
715 | *pnAddr = m_nCharVirtAddr;
716 | }
717 |
718 | LPCSTR Allocate(_In_ LPCSTR pszString, _Out_ DWORD *pnVirtAddr)
719 | {
720 | DWORD nLen = (DWORD)strlen(pszString) + 1;
721 | nLen += (nLen & 1);
722 |
723 | if (m_nChars + nLen > m_nCharsMax) {
724 | *pnVirtAddr = 0;
725 | return NULL;
726 | }
727 |
728 | *pnVirtAddr = m_nCharVirtAddr;
729 | HRESULT hrRet = StringCchCopyA(m_pChars, m_nCharsMax, pszString);
730 |
731 | if (FAILED(hrRet)) {
732 | return NULL;
733 | }
734 |
735 | pszString = m_pChars;
736 |
737 | m_pChars += nLen;
738 | m_nChars += nLen;
739 | m_nCharVirtAddr += nLen;
740 |
741 | return pszString;
742 | }
743 |
744 | LPCSTR Allocate(_In_ LPCSTR pszString, _In_ DWORD nHint, _Out_ DWORD *pnVirtAddr)
745 | {
746 | DWORD nLen = (DWORD)strlen(pszString) + 1 + sizeof(USHORT);
747 | nLen += (nLen & 1);
748 |
749 | if (m_nChars + nLen > m_nCharsMax) {
750 | *pnVirtAddr = 0;
751 | return NULL;
752 | }
753 |
754 | *pnVirtAddr = m_nCharVirtAddr;
755 | *(USHORT *)m_pChars = (USHORT)nHint;
756 |
757 | HRESULT hrRet = StringCchCopyA(m_pChars + sizeof(USHORT), m_nCharsMax, pszString);
758 | if (FAILED(hrRet)) {
759 | return NULL;
760 | }
761 |
762 | pszString = m_pChars + sizeof(USHORT);
763 |
764 | m_pChars += nLen;
765 | m_nChars += nLen;
766 | m_nCharVirtAddr += nLen;
767 |
768 | return pszString;
769 | }
770 |
771 | DWORD Size()
772 | {
773 | return m_nChars;
774 | }
775 | };
776 |
777 | //////////////////////////////////////////////////////////////////////////////
778 | //
779 | CImage * CImage::IsValid(PDETOUR_BINARY pBinary)
780 | {
781 | if (pBinary) {
782 | CImage *pImage = (CImage *)pBinary;
783 |
784 | if (pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE) {
785 | return pImage;
786 | }
787 | }
788 | SetLastError(ERROR_INVALID_HANDLE);
789 | return NULL;
790 | }
791 |
792 | CImage::CImage()
793 | {
794 | m_dwValidSignature = (DWORD)DETOUR_IMAGE_VALID_SIGNATURE;
795 |
796 | m_hMap = NULL;
797 | m_pMap = NULL;
798 |
799 | m_nPeOffset = 0;
800 | m_nSectionsOffset = 0;
801 |
802 | m_pbOutputBuffer = NULL;
803 | m_cbOutputBuffer = 0;
804 |
805 | m_pImageData = NULL;
806 |
807 | m_pImportFiles = NULL;
808 | m_nImportFiles = 0;
809 |
810 | m_fHadDetourSection = FALSE;
811 | }
812 |
813 | CImage::~CImage()
814 | {
815 | Close();
816 | m_dwValidSignature = 0;
817 | }
818 |
819 | BOOL CImage::Close()
820 | {
821 | if (m_pImportFiles) {
822 | delete m_pImportFiles;
823 | m_pImportFiles = NULL;
824 | m_nImportFiles = 0;
825 | }
826 |
827 | if (m_pImageData) {
828 | delete m_pImageData;
829 | m_pImageData = NULL;
830 | }
831 |
832 | if (m_pMap != NULL) {
833 | UnmapViewOfFile(m_pMap);
834 | m_pMap = NULL;
835 | }
836 |
837 | if (m_hMap) {
838 | CloseHandle(m_hMap);
839 | m_hMap = NULL;
840 | }
841 |
842 | if (m_pbOutputBuffer) {
843 | delete[] m_pbOutputBuffer;
844 | m_pbOutputBuffer = NULL;
845 | m_cbOutputBuffer = 0;
846 | }
847 | return TRUE;
848 | }
849 |
850 | //////////////////////////////////////////////////////////////////////////////
851 | //
852 | PBYTE CImage::DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
853 | {
854 | if (m_pImageData == NULL) {
855 | return NULL;
856 | }
857 | return m_pImageData->Enumerate(pGuid, pcbData, pnIterator);
858 | }
859 |
860 | PBYTE CImage::DataFind(REFGUID rguid, DWORD *pcbData)
861 | {
862 | if (m_pImageData == NULL) {
863 | return NULL;
864 | }
865 | return m_pImageData->Find(rguid, pcbData);
866 | }
867 |
868 | PBYTE CImage::DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData)
869 | {
870 | if (m_pImageData == NULL) {
871 | return NULL;
872 | }
873 | return m_pImageData->Set(rguid, pbData, cbData);
874 | }
875 |
876 | BOOL CImage::DataDelete(REFGUID rguid)
877 | {
878 | if (m_pImageData == NULL) {
879 | return FALSE;
880 | }
881 | return m_pImageData->Delete(rguid);
882 | }
883 |
884 | BOOL CImage::DataPurge()
885 | {
886 | if (m_pImageData == NULL) {
887 | return TRUE;
888 | }
889 | return m_pImageData->Purge();
890 | }
891 |
892 | //////////////////////////////////////////////////////////////////////////////
893 | //
894 | BOOL CImage::SizeOutputBuffer(DWORD cbData)
895 | {
896 | if (m_cbOutputBuffer < cbData) {
897 | if (cbData < 1024) {//65536
898 | cbData = 1024;
899 | }
900 | cbData = FileAlign(cbData);
901 |
902 | PBYTE pOutput = new NOTHROW BYTE [cbData];
903 | if (pOutput == NULL) {
904 | SetLastError(ERROR_OUTOFMEMORY);
905 | return FALSE;
906 | }
907 |
908 | if (m_pbOutputBuffer) {
909 | CopyMemory(pOutput, m_pbOutputBuffer, m_cbOutputBuffer);
910 |
911 | delete[] m_pbOutputBuffer;
912 | m_pbOutputBuffer = NULL;
913 | }
914 |
915 | ZeroMemory(pOutput + m_cbOutputBuffer, cbData - m_cbOutputBuffer),
916 |
917 | m_pbOutputBuffer = pOutput;
918 | m_cbOutputBuffer = cbData;
919 | }
920 | return TRUE;
921 | }
922 |
923 | PBYTE CImage::AllocateOutput(DWORD cbData, DWORD *pnVirtAddr)
924 | {
925 | cbData = QuadAlign(cbData);
926 |
927 | PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize;
928 |
929 | *pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize;
930 | m_nOutputVirtSize += cbData;
931 |
932 | if (m_nOutputVirtSize > m_cbOutputBuffer) {
933 | SetLastError(ERROR_OUTOFMEMORY);
934 | return NULL;
935 | }
936 |
937 | ZeroMemory(pbData, cbData);
938 |
939 | return pbData;
940 | }
941 |
942 | //////////////////////////////////////////////////////////////////////////////
943 | //
944 | DWORD CImage::FileAlign(DWORD nAddr)
945 | {
946 | return Align(nAddr, m_NtHeader.OptionalHeader.FileAlignment);
947 | }
948 |
949 | DWORD CImage::SectionAlign(DWORD nAddr)
950 | {
951 | return Align(nAddr, m_NtHeader.OptionalHeader.SectionAlignment);
952 | }
953 |
954 | //////////////////////////////////////////////////////////////////////////////
955 | //
956 | PVOID CImage::RvaToVa(ULONG_PTR nRva)
957 | {
958 | if (nRva == 0) {
959 | return NULL;
960 | }
961 |
962 | for (DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
963 | DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
964 | DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
965 |
966 | if (nRva >= vaStart && nRva < vaEnd) {
967 | return (PBYTE)m_pMap
968 | + m_SectionHeaders[n].PointerToRawData
969 | + nRva - m_SectionHeaders[n].VirtualAddress;
970 | }
971 | }
972 | return NULL;
973 | }
974 |
975 | DWORD CImage::RvaToFileOffset(DWORD nRva)
976 | {
977 | DWORD n;
978 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
979 | DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
980 | DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
981 |
982 | if (nRva >= vaStart && nRva < vaEnd) {
983 | return m_SectionHeaders[n].PointerToRawData
984 | + nRva - m_SectionHeaders[n].VirtualAddress;
985 | }
986 | }
987 | return 0;
988 | }
989 |
990 | //////////////////////////////////////////////////////////////////////////////
991 | //
992 | BOOL CImage::WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
993 | LPDWORD lpNumberOfBytesWritten)
994 | {
995 | return ::WriteFile(hFile,
996 | lpBuffer,
997 | nNumberOfBytesToWrite,
998 | lpNumberOfBytesWritten,
999 | NULL);
1000 | }
1001 |
1002 |
1003 | BOOL CImage::CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData)
1004 | {
1005 | DWORD cbDone = 0;
1006 | return WriteFile(hFile, m_pMap + nOldPos, cbData, &cbDone);
1007 | }
1008 |
1009 | BOOL CImage::ZeroFileData(HANDLE hFile, DWORD cbData)
1010 | {
1011 | if (!SizeOutputBuffer(4096)) {
1012 | return FALSE;
1013 | }
1014 |
1015 | ZeroMemory(m_pbOutputBuffer, 4096);
1016 |
1017 | for (DWORD cbLeft = cbData; cbLeft > 0;) {
1018 | DWORD cbStep = cbLeft > sizeof(m_pbOutputBuffer)
1019 | ? sizeof(m_pbOutputBuffer) : cbLeft;
1020 | DWORD cbDone = 0;
1021 |
1022 | if (!WriteFile(hFile, m_pbOutputBuffer, cbStep, &cbDone)) {
1023 | return FALSE;
1024 | }
1025 | if (cbDone == 0) {
1026 | break;
1027 | }
1028 |
1029 | cbLeft -= cbDone;
1030 | }
1031 | return TRUE;
1032 | }
1033 |
1034 | BOOL CImage::AlignFileData(HANDLE hFile)
1035 | {
1036 | DWORD nLastFileAddr = m_nNextFileAddr;
1037 |
1038 | m_nNextFileAddr = FileAlign(m_nNextFileAddr);
1039 | m_nNextVirtAddr = SectionAlign(m_nNextVirtAddr);
1040 |
1041 | if (hFile != INVALID_HANDLE_VALUE) {
1042 | if (m_nNextFileAddr > nLastFileAddr) {
1043 | if (SetFilePointer(hFile, nLastFileAddr, NULL, FILE_BEGIN) == ~0u) {
1044 | return FALSE;
1045 | }
1046 | return ZeroFileData(hFile, m_nNextFileAddr - nLastFileAddr);
1047 | }
1048 | }
1049 | return TRUE;
1050 | }
1051 |
1052 | BOOL CImage::Read(HANDLE hFile)
1053 | {
1054 | DWORD n;
1055 | PBYTE pbData = NULL;
1056 | DWORD cbData = 0;
1057 |
1058 | if (hFile == INVALID_HANDLE_VALUE) {
1059 | SetLastError(ERROR_INVALID_HANDLE);
1060 | return FALSE;
1061 | }
1062 |
1063 | ///////////////////////////////////////////////////////// Create mapping.
1064 | //
1065 | m_nFileSize = GetFileSize(hFile, NULL);
1066 | if (m_nFileSize == (DWORD)-1) {
1067 | return FALSE;
1068 | }
1069 |
1070 | m_hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
1071 | if (m_hMap == NULL) {
1072 | return FALSE;
1073 | }
1074 |
1075 | m_pMap = (PBYTE)MapViewOfFileEx(m_hMap, FILE_MAP_READ, 0, 0, 0, NULL);
1076 | if (m_pMap == NULL) {
1077 | return FALSE;
1078 | }
1079 |
1080 | ////////////////////////////////////////////////////// Process DOS Header.
1081 | //
1082 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)m_pMap;
1083 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
1084 | SetLastError(ERROR_BAD_EXE_FORMAT);
1085 | return FALSE;
1086 | }
1087 | m_nPeOffset = pDosHeader->e_lfanew;
1088 | m_nPrePE = 0;
1089 | m_cbPrePE = QuadAlign(pDosHeader->e_lfanew);
1090 |
1091 | if (m_nPeOffset > m_nFileSize ||
1092 | m_nPeOffset + sizeof(m_NtHeader) > m_nFileSize) {
1093 |
1094 | SetLastError(ERROR_BAD_EXE_FORMAT);
1095 | return FALSE;
1096 | }
1097 |
1098 | CopyMemory(&m_DosHeader, m_pMap + m_nPrePE, sizeof(m_DosHeader));
1099 |
1100 | /////////////////////////////////////////////////////// Process PE Header.
1101 | //
1102 | CopyMemory(&m_NtHeader, m_pMap + m_nPeOffset, sizeof(m_NtHeader));
1103 | if (m_NtHeader.Signature != IMAGE_NT_SIGNATURE) {
1104 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
1105 | return FALSE;
1106 | }
1107 | if (m_NtHeader.FileHeader.SizeOfOptionalHeader == 0) {
1108 | SetLastError(ERROR_EXE_MARKED_INVALID);
1109 | return FALSE;
1110 | }
1111 | m_nSectionsOffset = m_nPeOffset
1112 | + sizeof(m_NtHeader.Signature)
1113 | + sizeof(m_NtHeader.FileHeader)
1114 | + m_NtHeader.FileHeader.SizeOfOptionalHeader;
1115 |
1116 | ///////////////////////////////////////////////// Process Section Headers.
1117 | //
1118 | if (m_NtHeader.FileHeader.NumberOfSections > ARRAYSIZE(m_SectionHeaders)) {
1119 | SetLastError(ERROR_EXE_MARKED_INVALID);
1120 | return FALSE;
1121 | }
1122 | CopyMemory(&m_SectionHeaders,
1123 | m_pMap + m_nSectionsOffset,
1124 | sizeof(m_SectionHeaders[0]) * m_NtHeader.FileHeader.NumberOfSections);
1125 |
1126 | /////////////////////////////////////////////////// Parse .detour Section.
1127 | //
1128 | DWORD rvaOriginalImageDirectory = 0;
1129 | DWORD rvaDetourBeg = 0;
1130 | DWORD rvaDetourEnd = 0;
1131 |
1132 | _Analysis_assume_(m_NtHeader.FileHeader.NumberOfSections <= ARRAYSIZE(m_SectionHeaders));
1133 |
1134 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1135 | if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
1136 | DETOUR_SECTION_HEADER dh;
1137 | CopyMemory(&dh,
1138 | m_pMap + m_SectionHeaders[n].PointerToRawData,
1139 | sizeof(dh));
1140 |
1141 | rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress;
1142 | if (dh.cbPrePE != 0) {
1143 | m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof(dh);
1144 | m_cbPrePE = dh.cbPrePE;
1145 | }
1146 | rvaDetourBeg = m_SectionHeaders[n].VirtualAddress;
1147 | rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData;
1148 | }
1149 | }
1150 |
1151 | //////////////////////////////////////////////////////// Get Import Table.
1152 | //
1153 | DWORD rvaImageDirectory = m_NtHeader.OptionalHeader
1154 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1155 | PIMAGE_IMPORT_DESCRIPTOR iidp
1156 | = (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaImageDirectory);
1157 | PIMAGE_IMPORT_DESCRIPTOR oidp
1158 | = (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaOriginalImageDirectory);
1159 |
1160 | if (oidp == NULL) {
1161 | oidp = iidp;
1162 | }
1163 | if (iidp == NULL || oidp == NULL) {
1164 | SetLastError(ERROR_EXE_MARKED_INVALID);
1165 | return FALSE;
1166 | }
1167 |
1168 | DWORD nFiles = 0;
1169 | for (; iidp[nFiles].OriginalFirstThunk != 0 || iidp[nFiles].FirstThunk != 0; nFiles++) {
1170 | }
1171 |
1172 | CImageImportFile **ppLastFile = &m_pImportFiles;
1173 | m_pImportFiles = NULL;
1174 |
1175 | for (n = 0; n < nFiles; n++, iidp++) {
1176 | ULONG_PTR rvaName = iidp->Name;
1177 | PCHAR pszName = (PCHAR)RvaToVa(rvaName);
1178 | if (pszName == NULL) {
1179 | SetLastError(ERROR_EXE_MARKED_INVALID);
1180 | goto fail;
1181 | }
1182 |
1183 | CImageImportFile *pImportFile = new NOTHROW CImageImportFile;
1184 | if (pImportFile == NULL) {
1185 | SetLastError(ERROR_OUTOFMEMORY);
1186 | goto fail;
1187 | }
1188 |
1189 | *ppLastFile = pImportFile;
1190 | ppLastFile = &pImportFile->m_pNextFile;
1191 | m_nImportFiles++;
1192 |
1193 | pImportFile->m_pszName = DuplicateString(pszName);
1194 | if (pImportFile->m_pszName == NULL) {
1195 | goto fail;
1196 | }
1197 |
1198 | pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk;
1199 | pImportFile->m_rvaFirstThunk = iidp->FirstThunk;
1200 | pImportFile->m_nForwarderChain = iidp->ForwarderChain;
1201 | pImportFile->m_pImportNames = NULL;
1202 | pImportFile->m_nImportNames = 0;
1203 | pImportFile->m_fByway = FALSE;
1204 |
1205 | if ((ULONG)iidp->FirstThunk >= rvaDetourBeg &&
1206 | (ULONG)iidp->FirstThunk < rvaDetourEnd) {
1207 |
1208 | pImportFile->m_pszOrig = NULL;
1209 | pImportFile->m_fByway = TRUE;
1210 | continue;
1211 | }
1212 |
1213 | rvaName = oidp->Name;
1214 | pszName = (PCHAR)RvaToVa(rvaName);
1215 | if (pszName == NULL) {
1216 | SetLastError(ERROR_EXE_MARKED_INVALID);
1217 | goto fail;
1218 | }
1219 | pImportFile->m_pszOrig = DuplicateString(pszName);
1220 | if (pImportFile->m_pszOrig == NULL) {
1221 | goto fail;
1222 | }
1223 |
1224 | DWORD rvaThunk = iidp->OriginalFirstThunk;
1225 | if( !rvaThunk ) {
1226 | rvaThunk = iidp->FirstThunk;
1227 | }
1228 | PIMAGE_THUNK_DATA pAddrThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
1229 | rvaThunk = oidp->OriginalFirstThunk;
1230 | if( !rvaThunk ) {
1231 | rvaThunk = oidp->FirstThunk;
1232 | }
1233 | PIMAGE_THUNK_DATA pLookThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
1234 |
1235 | DWORD nNames = 0;
1236 | if (pAddrThunk) {
1237 | for (; pAddrThunk[nNames].u1.Ordinal; nNames++) {
1238 | }
1239 | }
1240 |
1241 | if (pAddrThunk && nNames) {
1242 | pImportFile->m_nImportNames = nNames;
1243 | pImportFile->m_pImportNames = new NOTHROW CImageImportName [nNames];
1244 | if (pImportFile->m_pImportNames == NULL) {
1245 | SetLastError(ERROR_OUTOFMEMORY);
1246 | goto fail;
1247 | }
1248 |
1249 | CImageImportName *pImportName = &pImportFile->m_pImportNames[0];
1250 |
1251 | for (DWORD f = 0; f < nNames; f++, pImportName++) {
1252 | pImportName->m_nOrig = 0;
1253 | pImportName->m_nOrdinal = 0;
1254 | pImportName->m_nHint = 0;
1255 | pImportName->m_pszName = NULL;
1256 | pImportName->m_pszOrig = NULL;
1257 |
1258 | rvaName = pAddrThunk[f].u1.Ordinal;
1259 | if (rvaName & IMAGE_ORDINAL_FLAG) {
1260 | pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
1261 | pImportName->m_nOrdinal = pImportName->m_nOrig;
1262 | }
1263 | else {
1264 | PIMAGE_IMPORT_BY_NAME pName
1265 | = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
1266 | if (pName) {
1267 | pImportName->m_nHint = pName->Hint;
1268 | pImportName->m_pszName = DuplicateString((PCHAR)pName->Name);
1269 | if (pImportName->m_pszName == NULL) {
1270 | goto fail;
1271 | }
1272 | }
1273 |
1274 | rvaName = pLookThunk[f].u1.Ordinal;
1275 | if (rvaName & IMAGE_ORDINAL_FLAG) {
1276 | pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
1277 | pImportName->m_nOrdinal = (ULONG)IMAGE_ORDINAL(rvaName);
1278 | }
1279 | else {
1280 | pName = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
1281 | if (pName) {
1282 | pImportName->m_pszOrig
1283 | = DuplicateString((PCHAR)pName->Name);
1284 | if (pImportName->m_pszOrig == NULL) {
1285 | goto fail;
1286 | }
1287 | }
1288 | }
1289 | }
1290 | }
1291 | }
1292 | oidp++;
1293 | }
1294 |
1295 | ////////////////////////////////////////////////////////// Parse Sections.
1296 | //
1297 | m_nExtraOffset = 0;
1298 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1299 | m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
1300 | m_SectionHeaders[n].SizeOfRawData,
1301 | m_nExtraOffset);
1302 |
1303 | if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
1304 | DETOUR_SECTION_HEADER dh;
1305 | CopyMemory(&dh,
1306 | m_pMap + m_SectionHeaders[n].PointerToRawData,
1307 | sizeof(dh));
1308 |
1309 | if (dh.nDataOffset == 0) {
1310 | dh.nDataOffset = dh.cbHeaderSize;
1311 | }
1312 |
1313 | cbData = dh.cbDataSize - dh.nDataOffset;
1314 | pbData = (m_pMap +
1315 | m_SectionHeaders[n].PointerToRawData +
1316 | dh.nDataOffset);
1317 |
1318 | m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
1319 | m_SectionHeaders[n].SizeOfRawData,
1320 | m_nExtraOffset);
1321 |
1322 | m_NtHeader.FileHeader.NumberOfSections--;
1323 |
1324 | m_NtHeader.OptionalHeader
1325 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1326 | = dh.nOriginalImportVirtualAddress;
1327 | m_NtHeader.OptionalHeader
1328 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
1329 | = dh.nOriginalImportSize;
1330 |
1331 | m_NtHeader.OptionalHeader
1332 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress
1333 | = dh.nOriginalBoundImportVirtualAddress;
1334 | m_NtHeader.OptionalHeader
1335 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size
1336 | = dh.nOriginalBoundImportSize;
1337 |
1338 | m_NtHeader.OptionalHeader
1339 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress
1340 | = dh.nOriginalIatVirtualAddress;
1341 | m_NtHeader.OptionalHeader
1342 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size
1343 | = dh.nOriginalIatSize;
1344 |
1345 | m_NtHeader.OptionalHeader.CheckSum = 0;
1346 | m_NtHeader.OptionalHeader.SizeOfImage
1347 | = dh.nOriginalSizeOfImage;
1348 |
1349 | m_fHadDetourSection = TRUE;
1350 | }
1351 | }
1352 |
1353 | m_pImageData = new NOTHROW CImageData(pbData, cbData);
1354 | if (m_pImageData == NULL) {
1355 | SetLastError(ERROR_OUTOFMEMORY);
1356 | }
1357 | return TRUE;
1358 |
1359 | fail:
1360 | return FALSE;
1361 | }
1362 |
1363 | static inline BOOL strneq(_In_ LPCSTR pszOne, _In_ LPCSTR pszTwo)
1364 | {
1365 | if (pszOne == pszTwo) {
1366 | return FALSE;
1367 | }
1368 | if (!pszOne || !pszTwo) {
1369 | return TRUE;
1370 | }
1371 | return (strcmp(pszOne, pszTwo) != 0);
1372 | }
1373 |
1374 | BOOL CImage::CheckImportsNeeded(DWORD *pnTables, DWORD *pnThunks, DWORD *pnChars)
1375 | {
1376 | DWORD nTables = 0;
1377 | DWORD nThunks = 0;
1378 | DWORD nChars = 0;
1379 | BOOL fNeedDetourSection = FALSE;
1380 |
1381 | for (CImageImportFile *pImportFile = m_pImportFiles;
1382 | pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {
1383 |
1384 | nChars += (int)strlen(pImportFile->m_pszName) + 1;
1385 | nChars += nChars & 1;
1386 |
1387 | if (pImportFile->m_fByway) {
1388 | fNeedDetourSection = TRUE;
1389 | nThunks++;
1390 | }
1391 | else {
1392 | if (!fNeedDetourSection &&
1393 | strneq(pImportFile->m_pszName, pImportFile->m_pszOrig)) {
1394 |
1395 | fNeedDetourSection = TRUE;
1396 | }
1397 | for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {
1398 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1399 |
1400 | if (!fNeedDetourSection &&
1401 | strneq(pImportName->m_pszName, pImportName->m_pszOrig)) {
1402 |
1403 | fNeedDetourSection = TRUE;
1404 | }
1405 |
1406 | if (pImportName->m_pszName) {
1407 | nChars += sizeof(WORD); // Hint
1408 | nChars += (int)strlen(pImportName->m_pszName) + 1;
1409 | nChars += nChars & 1;
1410 | }
1411 | nThunks++;
1412 | }
1413 | }
1414 | nThunks++;
1415 | nTables++;
1416 | }
1417 | nTables++;
1418 |
1419 | *pnTables = nTables;
1420 | *pnThunks = nThunks;
1421 | *pnChars = nChars;
1422 |
1423 | return fNeedDetourSection;
1424 | }
1425 |
1426 | //////////////////////////////////////////////////////////////////////////////
1427 | //
1428 | CImageImportFile * CImage::NewByway(_In_ LPCSTR pszName)
1429 | {
1430 | CImageImportFile *pImportFile = new NOTHROW CImageImportFile;
1431 | if (pImportFile == NULL) {
1432 | SetLastError(ERROR_OUTOFMEMORY);
1433 | goto fail;
1434 | }
1435 |
1436 | pImportFile->m_pNextFile = NULL;
1437 | pImportFile->m_fByway = TRUE;
1438 |
1439 | pImportFile->m_pszName = DuplicateString(pszName);
1440 | if (pImportFile->m_pszName == NULL) {
1441 | goto fail;
1442 | }
1443 |
1444 | pImportFile->m_rvaOriginalFirstThunk = 0;
1445 | pImportFile->m_rvaFirstThunk = 0;
1446 | pImportFile->m_nForwarderChain = (UINT)0;
1447 | pImportFile->m_pImportNames = NULL;
1448 | pImportFile->m_nImportNames = 0;
1449 |
1450 | m_nImportFiles++;
1451 | return pImportFile;
1452 |
1453 | fail:
1454 | if (pImportFile) {
1455 | delete pImportFile;
1456 | pImportFile = NULL;
1457 | }
1458 | return NULL;
1459 | }
1460 |
1461 | BOOL CImage::EditImports(PVOID pContext,
1462 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
1463 | PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
1464 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
1465 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback)
1466 | {
1467 | CImageImportFile *pImportFile = NULL;
1468 | CImageImportFile **ppLastFile = &m_pImportFiles;
1469 |
1470 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1471 |
1472 | while ((pImportFile = *ppLastFile) != NULL) {
1473 |
1474 | if (pfBywayCallback != NULL) {
1475 | LPCSTR pszFile = NULL;
1476 | if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) {
1477 | goto fail;
1478 | }
1479 |
1480 | if (pszFile != NULL) {
1481 | // Insert a new Byway.
1482 | CImageImportFile *pByway = NewByway(pszFile);
1483 | if (pByway == NULL) {
1484 | return FALSE;
1485 | }
1486 |
1487 | pByway->m_pNextFile = pImportFile;
1488 | *ppLastFile = pByway;
1489 | ppLastFile = &pByway->m_pNextFile;
1490 | continue; // Retry after Byway.
1491 | }
1492 | }
1493 |
1494 | if (pImportFile->m_fByway) {
1495 | if (pfBywayCallback != NULL) {
1496 | LPCSTR pszFile = NULL;
1497 |
1498 | if (!(*pfBywayCallback)(pContext, pImportFile->m_pszName, &pszFile)) {
1499 | goto fail;
1500 | }
1501 |
1502 | if (pszFile != NULL) {
1503 | // Replace? Byway
1504 | if (pszFile != pImportFile->m_pszName) {
1505 | LPCSTR pszLast = pImportFile->m_pszName;
1506 | pImportFile->m_pszName = DuplicateString(pszFile);
1507 | ReleaseString(pszLast);
1508 |
1509 | if (pImportFile->m_pszName == NULL) {
1510 | goto fail;
1511 | }
1512 | }
1513 | }
1514 | else { // Delete Byway
1515 | *ppLastFile = pImportFile->m_pNextFile;
1516 | pImportFile->m_pNextFile = NULL;
1517 | delete pImportFile;
1518 | m_nImportFiles--;
1519 | continue; // Retry after delete.
1520 | }
1521 | }
1522 | }
1523 | else {
1524 | if (pfFileCallback != NULL) {
1525 | LPCSTR pszFile = NULL;
1526 |
1527 | if (!(*pfFileCallback)(pContext,
1528 | pImportFile->m_pszOrig,
1529 | pImportFile->m_pszName,
1530 | &pszFile)) {
1531 | goto fail;
1532 | }
1533 |
1534 | if (pszFile != NULL) {
1535 | if (pszFile != pImportFile->m_pszName) {
1536 | LPCSTR pszLast = pImportFile->m_pszName;
1537 | pImportFile->m_pszName = DuplicateString(pszFile);
1538 | ReleaseString(pszLast);
1539 |
1540 | if (pImportFile->m_pszName == NULL) {
1541 | goto fail;
1542 | }
1543 | }
1544 | }
1545 | }
1546 |
1547 | if (pfSymbolCallback != NULL) {
1548 | for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) {
1549 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1550 |
1551 | LPCSTR pszName = NULL;
1552 | ULONG nOrdinal = 0;
1553 | if (!(*pfSymbolCallback)(pContext,
1554 | pImportName->m_nOrig,
1555 | pImportName->m_nOrdinal,
1556 | &nOrdinal,
1557 | pImportName->m_pszOrig,
1558 | pImportName->m_pszName,
1559 | &pszName)) {
1560 | goto fail;
1561 | }
1562 |
1563 | if (pszName != NULL) {
1564 | if (pszName != pImportName->m_pszName) {
1565 | pImportName->m_nOrdinal = 0;
1566 |
1567 | LPCSTR pszLast = pImportName->m_pszName;
1568 | pImportName->m_pszName = DuplicateString(pszName);
1569 | ReleaseString(pszLast);
1570 |
1571 | if (pImportName->m_pszName == NULL) {
1572 | goto fail;
1573 | }
1574 | }
1575 | }
1576 | else if (nOrdinal != 0) {
1577 | pImportName->m_nOrdinal = nOrdinal;
1578 |
1579 | if (pImportName->m_pszName != NULL) {
1580 | delete[] pImportName->m_pszName;
1581 | pImportName->m_pszName = NULL;
1582 | }
1583 | }
1584 | }
1585 | }
1586 | }
1587 |
1588 | ppLastFile = &pImportFile->m_pNextFile;
1589 | pImportFile = pImportFile->m_pNextFile;
1590 | }
1591 |
1592 | for (;;) {
1593 | if (pfBywayCallback != NULL) {
1594 | LPCSTR pszFile = NULL;
1595 | if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) {
1596 | goto fail;
1597 | }
1598 | if (pszFile != NULL) {
1599 | // Insert a new Byway.
1600 | CImageImportFile *pByway = NewByway(pszFile);
1601 | if (pByway == NULL) {
1602 | return FALSE;
1603 | }
1604 |
1605 | pByway->m_pNextFile = pImportFile;
1606 | *ppLastFile = pByway;
1607 | ppLastFile = &pByway->m_pNextFile;
1608 | continue; // Retry after Byway.
1609 | }
1610 | }
1611 | break;
1612 | }
1613 |
1614 | if (pfCommitCallback != NULL) {
1615 | if (!(*pfCommitCallback)(pContext)) {
1616 | goto fail;
1617 | }
1618 | }
1619 |
1620 | SetLastError(NO_ERROR);
1621 | return TRUE;
1622 |
1623 | fail:
1624 | return FALSE;
1625 | }
1626 |
1627 | BOOL CImage::Write(HANDLE hFile)
1628 | {
1629 | DWORD cbDone;
1630 |
1631 | if (hFile == INVALID_HANDLE_VALUE) {
1632 | SetLastError(ERROR_INVALID_HANDLE);
1633 | return FALSE;
1634 | }
1635 |
1636 | m_nNextFileAddr = 0;
1637 | m_nNextVirtAddr = 0;
1638 |
1639 | DWORD nTables = 0;
1640 | DWORD nThunks = 0;
1641 | DWORD nChars = 0;
1642 | BOOL fNeedDetourSection = CheckImportsNeeded(&nTables, &nThunks, &nChars);
1643 |
1644 | //////////////////////////////////////////////////////////// Copy Headers.
1645 | //
1646 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1647 | return FALSE;
1648 | }
1649 | if (!CopyFileData(hFile, 0, m_NtHeader.OptionalHeader.SizeOfHeaders)) {
1650 | return FALSE;
1651 | }
1652 |
1653 | if (fNeedDetourSection || !m_pImageData->IsEmpty()) {
1654 | // Replace the file's DOS header with our own.
1655 | m_nPeOffset = sizeof(m_DosHeader) + sizeof(s_rbDosCode);
1656 | m_nSectionsOffset = m_nPeOffset
1657 | + sizeof(m_NtHeader.Signature)
1658 | + sizeof(m_NtHeader.FileHeader)
1659 | + m_NtHeader.FileHeader.SizeOfOptionalHeader;
1660 | m_DosHeader.e_lfanew = m_nPeOffset;
1661 |
1662 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1663 | return FALSE;
1664 | }
1665 | if (!WriteFile(hFile, &m_DosHeader, sizeof(m_DosHeader), &cbDone)) {
1666 | return FALSE;
1667 | }
1668 | if (!WriteFile(hFile, &s_rbDosCode, sizeof(s_rbDosCode), &cbDone)) {
1669 | return FALSE;
1670 | }
1671 | }
1672 | else {
1673 | // Restore the file's original DOS header.
1674 | if (m_nPrePE != 0) {
1675 | m_nPeOffset = m_cbPrePE;
1676 | m_nSectionsOffset = m_nPeOffset
1677 | + sizeof(m_NtHeader.Signature)
1678 | + sizeof(m_NtHeader.FileHeader)
1679 | + m_NtHeader.FileHeader.SizeOfOptionalHeader;
1680 | m_DosHeader.e_lfanew = m_nPeOffset;
1681 |
1682 |
1683 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) {
1684 | return FALSE;
1685 | }
1686 | if (!CopyFileData(hFile, m_nPrePE, m_cbPrePE)) {
1687 | return FALSE;
1688 | }
1689 | }
1690 | }
1691 |
1692 | m_nNextFileAddr = m_NtHeader.OptionalHeader.SizeOfHeaders;
1693 | m_nNextVirtAddr = 0;
1694 | if (!AlignFileData(hFile)) {
1695 | return FALSE;
1696 | }
1697 |
1698 | /////////////////////////////////////////////////////////// Copy Sections.
1699 | //
1700 | DWORD n = 0;
1701 | for (; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1702 | if (m_SectionHeaders[n].SizeOfRawData) {
1703 | if (SetFilePointer(hFile,
1704 | m_SectionHeaders[n].PointerToRawData,
1705 | NULL, FILE_BEGIN) == ~0u) {
1706 | return FALSE;
1707 | }
1708 | if (!CopyFileData(hFile,
1709 | m_SectionHeaders[n].PointerToRawData,
1710 | m_SectionHeaders[n].SizeOfRawData)) {
1711 | return FALSE;
1712 | }
1713 | }
1714 | m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData +
1715 | m_SectionHeaders[n].SizeOfRawData,
1716 | m_nNextFileAddr);
1717 | #if 0
1718 | m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress +
1719 | m_SectionHeaders[n].Misc.VirtualSize,
1720 | m_nNextVirtAddr);
1721 | #else
1722 | m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress +
1723 | (m_SectionHeaders[n].Misc.VirtualSize
1724 | ? m_SectionHeaders[n].Misc.VirtualSize
1725 | : SectionAlign(m_SectionHeaders[n].SizeOfRawData)),
1726 | m_nNextVirtAddr);
1727 | #endif
1728 |
1729 | m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset);
1730 |
1731 | if (!AlignFileData(hFile)) {
1732 | return FALSE;
1733 | }
1734 | }
1735 |
1736 | if (fNeedDetourSection || !m_pImageData->IsEmpty()) {
1737 |
1738 | if (m_NtHeader.FileHeader.NumberOfSections >= ARRAYSIZE(m_SectionHeaders)) {
1739 | SetLastError(ERROR_EXE_MARKED_INVALID);
1740 | return FALSE;
1741 | }
1742 |
1743 | ////////////////////////////////////////////// Insert .detour Section.
1744 | //
1745 | DWORD nSection = m_NtHeader.FileHeader.NumberOfSections++;
1746 | DETOUR_SECTION_HEADER dh;
1747 |
1748 | ZeroMemory(&dh, sizeof(dh));
1749 | ZeroMemory(&m_SectionHeaders[nSection], sizeof(m_SectionHeaders[nSection]));
1750 |
1751 | dh.cbHeaderSize = sizeof(DETOUR_SECTION_HEADER);
1752 | dh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE;
1753 |
1754 | dh.nOriginalImportVirtualAddress = m_NtHeader.OptionalHeader
1755 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1756 | dh.nOriginalImportSize = m_NtHeader.OptionalHeader
1757 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
1758 |
1759 | dh.nOriginalBoundImportVirtualAddress
1760 | = m_NtHeader.OptionalHeader
1761 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress;
1762 | dh.nOriginalBoundImportSize = m_NtHeader.OptionalHeader
1763 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size;
1764 |
1765 | dh.nOriginalIatVirtualAddress = m_NtHeader.OptionalHeader
1766 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
1767 | dh.nOriginalIatSize = m_NtHeader.OptionalHeader
1768 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
1769 |
1770 | dh.nOriginalSizeOfImage = m_NtHeader.OptionalHeader.SizeOfImage;
1771 |
1772 | DWORD clrAddr = m_NtHeader.OptionalHeader
1773 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
1774 | DWORD clrSize = m_NtHeader.OptionalHeader
1775 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
1776 | if (clrAddr && clrSize) {
1777 | PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);
1778 | if (pHdr != NULL) {
1779 | DETOUR_CLR_HEADER hdr;
1780 | hdr = *pHdr;
1781 |
1782 | dh.nOriginalClrFlags = hdr.Flags;
1783 | }
1784 | }
1785 |
1786 | HRESULT hrRet = StringCchCopyA((PCHAR)m_SectionHeaders[nSection].Name, IMAGE_SIZEOF_SHORT_NAME , ".detour");
1787 | if (FAILED(hrRet))
1788 | return FALSE;
1789 |
1790 | m_SectionHeaders[nSection].Characteristics
1791 | = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
1792 |
1793 | m_nOutputVirtAddr = m_nNextVirtAddr;
1794 | m_nOutputVirtSize = 0;
1795 | m_nOutputFileAddr = m_nNextFileAddr;
1796 |
1797 | dh.nDataOffset = 0; // pbData
1798 | dh.cbDataSize = m_pImageData->m_cbData;
1799 | dh.cbPrePE = m_cbPrePE;
1800 |
1801 | //////////////////////////////////////////////////////////////////////////
1802 | //
1803 |
1804 | DWORD rvaImportTable = 0;
1805 | DWORD rvaLookupTable = 0;
1806 | DWORD rvaBoundTable = 0;
1807 | DWORD rvaNameTable = 0;
1808 | DWORD nImportTableSize = nTables * sizeof(IMAGE_IMPORT_DESCRIPTOR);
1809 |
1810 | if (!SizeOutputBuffer(QuadAlign(sizeof(dh))
1811 | + m_cbPrePE
1812 | + QuadAlign(m_pImageData->m_cbData)
1813 | + QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)
1814 | + QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks)
1815 | + QuadAlign(nChars)
1816 | + QuadAlign(nImportTableSize))) {
1817 | return FALSE;
1818 | }
1819 |
1820 | DWORD vaHead = 0;
1821 | PBYTE pbHead = NULL;
1822 | DWORD vaPrePE = 0;
1823 | PBYTE pbPrePE = NULL;
1824 | DWORD vaData = 0;
1825 | PBYTE pbData = NULL;
1826 |
1827 | if ((pbHead = AllocateOutput(sizeof(dh), &vaHead)) == NULL) {
1828 | return FALSE;
1829 | }
1830 |
1831 | if ((pbPrePE = AllocateOutput(m_cbPrePE, &vaPrePE)) == NULL) {
1832 | return FALSE;
1833 | }
1834 |
1835 | CImageThunks lookupTable(this, nThunks, &rvaLookupTable);
1836 | CImageThunks boundTable(this, nThunks, &rvaBoundTable);
1837 | CImageChars nameTable(this, nChars, &rvaNameTable);
1838 |
1839 | if ((pbData = AllocateOutput(m_pImageData->m_cbData, &vaData)) == NULL) {
1840 | return FALSE;
1841 | }
1842 |
1843 | dh.nDataOffset = vaData - vaHead;
1844 | dh.cbDataSize = dh.nDataOffset + m_pImageData->m_cbData;
1845 | CopyMemory(pbHead, &dh, sizeof(dh));
1846 | CopyMemory(pbPrePE, m_pMap + m_nPrePE, m_cbPrePE);
1847 | CopyMemory(pbData, m_pImageData->m_pbData, m_pImageData->m_cbData);
1848 |
1849 | PIMAGE_IMPORT_DESCRIPTOR piidDst = (PIMAGE_IMPORT_DESCRIPTOR)
1850 | AllocateOutput(nImportTableSize, &rvaImportTable);
1851 | if (piidDst == NULL) {
1852 | return FALSE;
1853 | }
1854 |
1855 | //////////////////////////////////////////////// Step Through Imports.
1856 | //
1857 | for (CImageImportFile *pImportFile = m_pImportFiles;
1858 | pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) {
1859 |
1860 | ZeroMemory(piidDst, sizeof(piidDst));
1861 | nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name);
1862 | piidDst->TimeDateStamp = 0;
1863 | piidDst->ForwarderChain = pImportFile->m_nForwarderChain;
1864 |
1865 | if (pImportFile->m_fByway) {
1866 | ULONG rvaIgnored;
1867 |
1868 | lookupTable.Allocate(IMAGE_ORDINAL_FLAG+1,
1869 | (DWORD *)&piidDst->OriginalFirstThunk);
1870 | boundTable.Allocate(IMAGE_ORDINAL_FLAG+1,
1871 | (DWORD *)&piidDst->FirstThunk);
1872 |
1873 | lookupTable.Allocate(0, &rvaIgnored);
1874 | boundTable.Allocate(0, &rvaIgnored);
1875 | }
1876 | else {
1877 | ULONG rvaIgnored;
1878 |
1879 | piidDst->FirstThunk = (ULONG)pImportFile->m_rvaFirstThunk;
1880 | lookupTable.Current((DWORD *)&piidDst->OriginalFirstThunk);
1881 |
1882 | for (n = 0; n < pImportFile->m_nImportNames; n++) {
1883 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n];
1884 |
1885 | if (pImportName->m_pszName) {
1886 | ULONG nDstName = 0;
1887 |
1888 | nameTable.Allocate(pImportName->m_pszName,
1889 | pImportName->m_nHint,
1890 | &nDstName);
1891 | lookupTable.Allocate(nDstName, &rvaIgnored);
1892 | }
1893 | else {
1894 | lookupTable.Allocate(IMAGE_ORDINAL_FLAG + pImportName->m_nOrdinal,
1895 | &rvaIgnored);
1896 | }
1897 | }
1898 | lookupTable.Allocate(0, &rvaIgnored);
1899 | }
1900 | piidDst++;
1901 | }
1902 | ZeroMemory(piidDst, sizeof(piidDst));
1903 |
1904 | //////////////////////////////////////////////////////////////////////////
1905 | //
1906 | m_nNextVirtAddr += m_nOutputVirtSize;
1907 | m_nNextFileAddr += FileAlign(m_nOutputVirtSize);
1908 |
1909 | if (!AlignFileData(hFile)) {
1910 | return FALSE;
1911 | }
1912 |
1913 | //////////////////////////////////////////////////////////////////////////
1914 | //
1915 | m_SectionHeaders[nSection].VirtualAddress = m_nOutputVirtAddr;
1916 | m_SectionHeaders[nSection].Misc.VirtualSize = m_nOutputVirtSize;
1917 | m_SectionHeaders[nSection].PointerToRawData = m_nOutputFileAddr;
1918 | m_SectionHeaders[nSection].SizeOfRawData = FileAlign(m_nOutputVirtSize);
1919 |
1920 | m_NtHeader.OptionalHeader
1921 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1922 | = rvaImportTable;
1923 | m_NtHeader.OptionalHeader
1924 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
1925 | = nImportTableSize;
1926 |
1927 | m_NtHeader.OptionalHeader
1928 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
1929 | m_NtHeader.OptionalHeader
1930 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
1931 |
1932 | //////////////////////////////////////////////////////////////////////////
1933 | //
1934 | if (SetFilePointer(hFile, m_SectionHeaders[nSection].PointerToRawData,
1935 | NULL, FILE_BEGIN) == ~0u) {
1936 | return FALSE;
1937 | }
1938 | if (!WriteFile(hFile, m_pbOutputBuffer, m_SectionHeaders[nSection].SizeOfRawData,
1939 | &cbDone)) {
1940 | return FALSE;
1941 | }
1942 | }
1943 |
1944 | ///////////////////////////////////////////////////// Adjust Extra Data.
1945 | //
1946 | LONG nExtraAdjust = m_nNextFileAddr - m_nExtraOffset;
1947 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
1948 | if (m_SectionHeaders[n].PointerToRawData > m_nExtraOffset) {
1949 | m_SectionHeaders[n].PointerToRawData += nExtraAdjust;
1950 | }
1951 | if (m_SectionHeaders[n].PointerToRelocations > m_nExtraOffset) {
1952 | m_SectionHeaders[n].PointerToRelocations += nExtraAdjust;
1953 | }
1954 | if (m_SectionHeaders[n].PointerToLinenumbers > m_nExtraOffset) {
1955 | m_SectionHeaders[n].PointerToLinenumbers += nExtraAdjust;
1956 | }
1957 | }
1958 | if (m_NtHeader.FileHeader.PointerToSymbolTable > m_nExtraOffset) {
1959 | m_NtHeader.FileHeader.PointerToSymbolTable += nExtraAdjust;
1960 | }
1961 |
1962 | m_NtHeader.OptionalHeader.CheckSum = 0;
1963 | m_NtHeader.OptionalHeader.SizeOfImage = m_nNextVirtAddr;
1964 |
1965 | ////////////////////////////////////////////////// Adjust Debug Directory.
1966 | //
1967 | DWORD debugAddr = m_NtHeader.OptionalHeader
1968 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
1969 | DWORD debugSize = m_NtHeader.OptionalHeader
1970 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
1971 | if (debugAddr && debugSize) {
1972 | DWORD nFileOffset = RvaToFileOffset(debugAddr);
1973 | if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {
1974 | return FALSE;
1975 | }
1976 |
1977 | PIMAGE_DEBUG_DIRECTORY pDir = (PIMAGE_DEBUG_DIRECTORY)RvaToVa(debugAddr);
1978 | if (pDir == NULL) {
1979 | return FALSE;
1980 | }
1981 |
1982 | DWORD nEntries = debugSize / sizeof(*pDir);
1983 | for (n = 0; n < nEntries; n++) {
1984 | IMAGE_DEBUG_DIRECTORY dir = pDir[n];
1985 |
1986 | if (dir.PointerToRawData > m_nExtraOffset) {
1987 | dir.PointerToRawData += nExtraAdjust;
1988 | }
1989 | if (!WriteFile(hFile, &dir, sizeof(dir), &cbDone)) {
1990 | return FALSE;
1991 | }
1992 | }
1993 | }
1994 |
1995 | /////////////////////////////////////////////////////// Adjust CLR Header.
1996 | //
1997 | DWORD clrAddr = m_NtHeader.OptionalHeader
1998 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
1999 | DWORD clrSize = m_NtHeader.OptionalHeader
2000 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size;
2001 | if (clrAddr && clrSize && fNeedDetourSection) {
2002 | DWORD nFileOffset = RvaToFileOffset(clrAddr);
2003 | if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) {
2004 | return FALSE;
2005 | }
2006 |
2007 | PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr);
2008 | if (pHdr == NULL) {
2009 | return FALSE;
2010 | }
2011 |
2012 | DETOUR_CLR_HEADER hdr;
2013 | hdr = *pHdr;
2014 | hdr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag.
2015 |
2016 | if (!WriteFile(hFile, &hdr, sizeof(hdr), &cbDone)) {
2017 | return FALSE;
2018 | }
2019 | }
2020 |
2021 | ///////////////////////////////////////////////// Copy Left-over Data.
2022 | //
2023 | if (m_nFileSize > m_nExtraOffset) {
2024 | if (SetFilePointer(hFile, m_nNextFileAddr, NULL, FILE_BEGIN) == ~0u) {
2025 | return FALSE;
2026 | }
2027 | if (!CopyFileData(hFile, m_nExtraOffset, m_nFileSize - m_nExtraOffset)) {
2028 | return FALSE;
2029 | }
2030 | }
2031 |
2032 |
2033 | //////////////////////////////////////////////////// Finalize Headers.
2034 | //
2035 |
2036 | if (SetFilePointer(hFile, m_nPeOffset, NULL, FILE_BEGIN) == ~0u) {
2037 | return FALSE;
2038 | }
2039 | if (!WriteFile(hFile, &m_NtHeader, sizeof(m_NtHeader), &cbDone)) {
2040 | return FALSE;
2041 | }
2042 |
2043 | if (SetFilePointer(hFile, m_nSectionsOffset, NULL, FILE_BEGIN) == ~0u) {
2044 | return FALSE;
2045 | }
2046 | if (!WriteFile(hFile, &m_SectionHeaders,
2047 | sizeof(m_SectionHeaders[0])
2048 | * m_NtHeader.FileHeader.NumberOfSections,
2049 | &cbDone)) {
2050 | return FALSE;
2051 | }
2052 |
2053 | m_cbPostPE = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
2054 | if (m_cbPostPE == ~0u) {
2055 | return FALSE;
2056 | }
2057 | m_cbPostPE = m_NtHeader.OptionalHeader.SizeOfHeaders - m_cbPostPE;
2058 |
2059 | return TRUE;
2060 | }
2061 |
2062 | }; // namespace Detour
2063 |
2064 | //////////////////////////////////////////////////////////////////////////////
2065 | //
2066 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile)
2067 | {
2068 | Detour::CImage *pImage = new NOTHROW
2069 | Detour::CImage;
2070 | if (pImage == NULL) {
2071 | SetLastError(ERROR_OUTOFMEMORY);
2072 | return FALSE;
2073 | }
2074 |
2075 | if (!pImage->Read(hFile)) {
2076 | delete pImage;
2077 | return FALSE;
2078 | }
2079 |
2080 | return (PDETOUR_BINARY)pImage;
2081 | }
2082 |
2083 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pdi,
2084 | _In_ HANDLE hFile)
2085 | {
2086 | Detour::CImage *pImage = Detour::CImage::IsValid(pdi);
2087 | if (pImage == NULL) {
2088 | return FALSE;
2089 | }
2090 |
2091 | return pImage->Write(hFile);
2092 | }
2093 |
2094 | _Writable_bytes_(*pcbData)
2095 | _Readable_bytes_(*pcbData)
2096 | _Success_(return != NULL)
2097 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary,
2098 | _Out_opt_ GUID *pGuid,
2099 | _Out_ DWORD *pcbData,
2100 | _Inout_ DWORD *pnIterator)
2101 | {
2102 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2103 | if (pImage == NULL) {
2104 | return FALSE;
2105 | }
2106 |
2107 | return pImage->DataEnum(pGuid, pcbData, pnIterator);
2108 | }
2109 |
2110 | _Writable_bytes_(*pcbData)
2111 | _Readable_bytes_(*pcbData)
2112 | _Success_(return != NULL)
2113 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary,
2114 | _In_ REFGUID rguid,
2115 | _Out_ DWORD *pcbData)
2116 | {
2117 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2118 | if (pImage == NULL) {
2119 | return FALSE;
2120 | }
2121 |
2122 | return pImage->DataFind(rguid, pcbData);
2123 | }
2124 |
2125 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary,
2126 | _In_ REFGUID rguid,
2127 | _In_reads_opt_(cbData) PVOID pvData,
2128 | _In_ DWORD cbData)
2129 | {
2130 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2131 | if (pImage == NULL) {
2132 | return NULL;
2133 | }
2134 |
2135 | return pImage->DataSet(rguid, (PBYTE)pvData, cbData);
2136 | }
2137 |
2138 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary,
2139 | _In_ REFGUID rguid)
2140 | {
2141 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2142 | if (pImage == NULL) {
2143 | return FALSE;
2144 | }
2145 |
2146 | return pImage->DataDelete(rguid);
2147 | }
2148 |
2149 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary)
2150 | {
2151 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2152 | if (pImage == NULL) {
2153 | return FALSE;
2154 | }
2155 |
2156 | return pImage->DataPurge();
2157 | }
2158 |
2159 | //////////////////////////////////////////////////////////////////////////////
2160 | //
2161 | static BOOL CALLBACK ResetBywayCallback(_In_opt_ PVOID pContext,
2162 | _In_opt_ LPCSTR pszFile,
2163 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile)
2164 | {
2165 | UNREFERENCED_PARAMETER(pContext);
2166 | UNREFERENCED_PARAMETER(pszFile);
2167 |
2168 | *ppszOutFile = NULL;
2169 | return TRUE;
2170 | }
2171 |
2172 | static BOOL CALLBACK ResetFileCallback(_In_opt_ PVOID pContext,
2173 | _In_ LPCSTR pszOrigFile,
2174 | _In_ LPCSTR pszFile,
2175 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile)
2176 | {
2177 | UNREFERENCED_PARAMETER(pContext);
2178 | UNREFERENCED_PARAMETER(pszFile);
2179 |
2180 | *ppszOutFile = pszOrigFile;
2181 | return TRUE;
2182 | }
2183 |
2184 | static BOOL CALLBACK ResetSymbolCallback(_In_opt_ PVOID pContext,
2185 | _In_ ULONG nOrigOrdinal,
2186 | _In_ ULONG nOrdinal,
2187 | _Out_ ULONG *pnOutOrdinal,
2188 | _In_opt_ LPCSTR pszOrigSymbol,
2189 | _In_opt_ LPCSTR pszSymbol,
2190 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol)
2191 | {
2192 | UNREFERENCED_PARAMETER(pContext);
2193 | UNREFERENCED_PARAMETER(nOrdinal);
2194 | UNREFERENCED_PARAMETER(pszSymbol);
2195 |
2196 | *pnOutOrdinal = nOrigOrdinal;
2197 | *ppszOutSymbol = pszOrigSymbol;
2198 | return TRUE;
2199 | }
2200 |
2201 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary)
2202 | {
2203 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2204 | if (pImage == NULL) {
2205 | return FALSE;
2206 | }
2207 |
2208 | return pImage->EditImports(NULL,
2209 | ResetBywayCallback,
2210 | ResetFileCallback,
2211 | ResetSymbolCallback,
2212 | NULL);
2213 | }
2214 |
2215 | //////////////////////////////////////////////////////////////////////////////
2216 | //
2217 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary,
2218 | _In_opt_ PVOID pContext,
2219 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway,
2220 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile,
2221 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol,
2222 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit)
2223 | {
2224 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2225 | if (pImage == NULL) {
2226 | return FALSE;
2227 | }
2228 |
2229 | return pImage->EditImports(pContext,
2230 | pfByway,
2231 | pfFile,
2232 | pfSymbol,
2233 | pfCommit);
2234 | }
2235 |
2236 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary)
2237 | {
2238 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary);
2239 | if (pImage == NULL) {
2240 | return FALSE;
2241 | }
2242 |
2243 | BOOL bSuccess = pImage->Close();
2244 | delete pImage;
2245 | pImage = NULL;
2246 |
2247 | return bSuccess;
2248 | }
2249 |
2250 | //
2251 | ///////////////////////////////////////////////////////////////// End of File.
2252 |
--------------------------------------------------------------------------------
/ShooterGameCheat/detours/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 _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1
13 |
14 | #pragma warning(disable:4068) // unknown pragma (suppress)
15 |
16 | #if _MSC_VER >= 1900
17 | #pragma warning(push)
18 | #pragma warning(disable:4091) // empty typedef
19 | #endif
20 |
21 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
22 | #include
23 | #if (_MSC_VER < 1310)
24 | #else
25 | #pragma warning(push)
26 | #if _MSC_VER > 1400
27 | #pragma warning(disable:6102 6103) // /analyze warnings
28 | #endif
29 | #include
30 | #pragma warning(pop)
31 | #endif
32 |
33 | // #define DETOUR_DEBUG 1
34 | #define DETOURS_INTERNAL
35 | #include "detours.h"
36 |
37 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
38 | #error detours.h version mismatch
39 | #endif
40 |
41 | #if _MSC_VER >= 1900
42 | #pragma warning(pop)
43 | #endif
44 |
45 | #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
46 | #define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
47 |
48 | //////////////////////////////////////////////////////////////////////////////
49 | //
50 | const GUID DETOUR_EXE_RESTORE_GUID = {
51 | 0x2ed7a3ff, 0x3339, 0x4a8d,
52 | { 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }};
53 |
54 | //////////////////////////////////////////////////////////////////////////////
55 | //
56 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
57 | {
58 | static DETOUR_SYM_INFO symInfo;
59 | static PDETOUR_SYM_INFO pSymInfo = NULL;
60 | static BOOL failed = false;
61 |
62 | if (failed) {
63 | return NULL;
64 | }
65 | if (pSymInfo != NULL) {
66 | return pSymInfo;
67 | }
68 |
69 | ZeroMemory(&symInfo, sizeof(symInfo));
70 | // Create a real handle to the process.
71 | #if 0
72 | DuplicateHandle(GetCurrentProcess(),
73 | GetCurrentProcess(),
74 | GetCurrentProcess(),
75 | &symInfo.hProcess,
76 | 0,
77 | FALSE,
78 | DUPLICATE_SAME_ACCESS);
79 | #else
80 | symInfo.hProcess = GetCurrentProcess();
81 | #endif
82 |
83 | symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0);
84 | if (symInfo.hDbgHelp == NULL) {
85 | abort:
86 | failed = true;
87 | if (symInfo.hDbgHelp != NULL) {
88 | FreeLibrary(symInfo.hDbgHelp);
89 | }
90 | symInfo.pfImagehlpApiVersionEx = NULL;
91 | symInfo.pfSymInitialize = NULL;
92 | symInfo.pfSymSetOptions = NULL;
93 | symInfo.pfSymGetOptions = NULL;
94 | symInfo.pfSymLoadModule64 = NULL;
95 | symInfo.pfSymGetModuleInfo64 = NULL;
96 | symInfo.pfSymFromName = NULL;
97 | return NULL;
98 | }
99 |
100 | symInfo.pfImagehlpApiVersionEx
101 | = (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
102 | "ImagehlpApiVersionEx");
103 | symInfo.pfSymInitialize
104 | = (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
105 | symInfo.pfSymSetOptions
106 | = (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
107 | symInfo.pfSymGetOptions
108 | = (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
109 | symInfo.pfSymLoadModule64
110 | = (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
111 | symInfo.pfSymGetModuleInfo64
112 | = (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
113 | symInfo.pfSymFromName
114 | = (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
115 |
116 | API_VERSION av;
117 | ZeroMemory(&av, sizeof(av));
118 | av.MajorVersion = API_VERSION_NUMBER;
119 |
120 | if (symInfo.pfImagehlpApiVersionEx == NULL ||
121 | symInfo.pfSymInitialize == NULL ||
122 | symInfo.pfSymLoadModule64 == NULL ||
123 | symInfo.pfSymGetModuleInfo64 == NULL ||
124 | symInfo.pfSymFromName == NULL) {
125 | goto abort;
126 | }
127 |
128 | symInfo.pfImagehlpApiVersionEx(&av);
129 | if (av.MajorVersion < API_VERSION_NUMBER) {
130 | goto abort;
131 | }
132 |
133 | if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
134 | // We won't retry the initialize if it fails.
135 | goto abort;
136 | }
137 |
138 | if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
139 | DWORD dw = symInfo.pfSymGetOptions();
140 |
141 | dw &= ~(SYMOPT_CASE_INSENSITIVE |
142 | SYMOPT_UNDNAME |
143 | SYMOPT_DEFERRED_LOADS |
144 | 0);
145 | dw |= (
146 | #if defined(SYMOPT_EXACT_SYMBOLS)
147 | SYMOPT_EXACT_SYMBOLS |
148 | #endif
149 | #if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
150 | SYMOPT_NO_UNQUALIFIED_LOADS |
151 | #endif
152 | SYMOPT_DEFERRED_LOADS |
153 | #if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
154 | SYMOPT_FAIL_CRITICAL_ERRORS |
155 | #endif
156 | #if defined(SYMOPT_INCLUDE_32BIT_MODULES)
157 | SYMOPT_INCLUDE_32BIT_MODULES |
158 | #endif
159 | 0);
160 | symInfo.pfSymSetOptions(dw);
161 | }
162 |
163 | pSymInfo = &symInfo;
164 | return pSymInfo;
165 | }
166 |
167 | PVOID WINAPI DetourFindFunction(_In_ PCSTR pszModule,
168 | _In_ PCSTR pszFunction)
169 | {
170 | /////////////////////////////////////////////// First, try GetProcAddress.
171 | //
172 | #pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
173 | HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0);
174 | if (hModule == NULL) {
175 | return NULL;
176 | }
177 |
178 | PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
179 | if (pbCode) {
180 | return pbCode;
181 | }
182 |
183 | ////////////////////////////////////////////////////// Then try ImageHelp.
184 | //
185 | DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
186 | PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
187 | if (pSymInfo == NULL) {
188 | DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n",
189 | GetLastError()));
190 | return NULL;
191 | }
192 |
193 | if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
194 | (PCHAR)pszModule, NULL,
195 | (DWORD64)hModule, 0) == 0) {
196 | if (ERROR_SUCCESS != GetLastError()) {
197 | DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n",
198 | pSymInfo->hProcess, GetLastError()));
199 | return NULL;
200 | }
201 | }
202 |
203 | HRESULT hrRet;
204 | CHAR szFullName[512];
205 | IMAGEHLP_MODULE64 modinfo;
206 | ZeroMemory(&modinfo, sizeof(modinfo));
207 | modinfo.SizeOfStruct = sizeof(modinfo);
208 | if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
209 | DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n",
210 | pSymInfo->hProcess, hModule, GetLastError()));
211 | return NULL;
212 | }
213 |
214 | hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
215 | if (FAILED(hrRet)) {
216 | DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet));
217 | return NULL;
218 | }
219 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
220 | if (FAILED(hrRet)) {
221 | DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
222 | return NULL;
223 | }
224 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
225 | if (FAILED(hrRet)) {
226 | DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet));
227 | return NULL;
228 | }
229 |
230 | struct CFullSymbol : SYMBOL_INFO {
231 | CHAR szRestOfName[512];
232 | } symbol;
233 | ZeroMemory(&symbol, sizeof(symbol));
234 | //symbol.ModBase = (ULONG64)hModule;
235 | symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
236 | #ifdef DBHLPAPI
237 | symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
238 | #else
239 | symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
240 | #endif
241 |
242 | if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
243 | DETOUR_TRACE(("SymFromName(%hs) failed: %d\n", szFullName, GetLastError()));
244 | return NULL;
245 | }
246 |
247 | #if defined(DETOURS_IA64)
248 | // On the IA64, we get a raw code pointer from the symbol engine
249 | // and have to convert it to a wrapped [code pointer, global pointer].
250 | //
251 | PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
252 | PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
253 |
254 | pldSymbol->EntryPoint = symbol.Address;
255 | pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
256 | return (PBYTE)pldSymbol;
257 | #elif defined(DETOURS_ARM)
258 | // On the ARM, we get a raw code pointer, which we must convert into a
259 | // valied Thumb2 function pointer.
260 | return DETOURS_PBYTE_TO_PFUNC(symbol.Address);
261 | #else
262 | return (PBYTE)symbol.Address;
263 | #endif
264 | }
265 |
266 | //////////////////////////////////////////////////// Module Image Functions.
267 | //
268 |
269 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
270 | {
271 | PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
272 |
273 | MEMORY_BASIC_INFORMATION mbi;
274 | ZeroMemory(&mbi, sizeof(mbi));
275 |
276 | // Find the next memory region that contains a mapped PE image.
277 | //
278 | for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
279 | if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) {
280 | break;
281 | }
282 |
283 | // Skip uncommitted regions and guard pages.
284 | //
285 | if ((mbi.State != MEM_COMMIT) ||
286 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
287 | (mbi.Protect & PAGE_GUARD)) {
288 | continue;
289 | }
290 |
291 | __try {
292 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
293 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
294 | (DWORD)pDosHeader->e_lfanew > mbi.RegionSize ||
295 | (DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) {
296 | continue;
297 | }
298 |
299 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
300 | pDosHeader->e_lfanew);
301 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
302 | continue;
303 | }
304 |
305 | return (HMODULE)pDosHeader;
306 | }
307 | #pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
308 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
309 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
310 | continue;
311 | }
312 | }
313 | return NULL;
314 | }
315 |
316 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
317 | {
318 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
319 | if (hModule == NULL) {
320 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
321 | }
322 |
323 | __try {
324 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
325 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
326 | SetLastError(ERROR_BAD_EXE_FORMAT);
327 | return NULL;
328 | }
329 |
330 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
331 | pDosHeader->e_lfanew);
332 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
333 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
334 | return NULL;
335 | }
336 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
337 | SetLastError(ERROR_EXE_MARKED_INVALID);
338 | return NULL;
339 | }
340 |
341 | PDETOUR_CLR_HEADER pClrHeader = NULL;
342 | if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
343 | if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
344 | ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) {
345 | pClrHeader = (PDETOUR_CLR_HEADER)
346 | (((PBYTE)pDosHeader)
347 | + ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
348 | }
349 | }
350 | else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
351 | if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
352 | ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) {
353 | pClrHeader = (PDETOUR_CLR_HEADER)
354 | (((PBYTE)pDosHeader)
355 | + ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
356 | }
357 | }
358 |
359 | if (pClrHeader != NULL) {
360 | // For MSIL assemblies, we want to use the _Cor entry points.
361 |
362 | HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL");
363 | if (hClr == NULL) {
364 | return NULL;
365 | }
366 |
367 | SetLastError(NO_ERROR);
368 | return GetProcAddress(hClr, "_CorExeMain");
369 | }
370 |
371 | SetLastError(NO_ERROR);
372 |
373 | // Pure resource DLLs have neither an entry point nor CLR information
374 | // so handle them by returning NULL (LastError is NO_ERROR)
375 | if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) {
376 | return NULL;
377 | }
378 |
379 | return ((PBYTE)pDosHeader) +
380 | pNtHeader->OptionalHeader.AddressOfEntryPoint;
381 | }
382 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
383 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
384 | SetLastError(ERROR_EXE_MARKED_INVALID);
385 | return NULL;
386 | }
387 | }
388 |
389 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule)
390 | {
391 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
392 | if (hModule == NULL) {
393 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
394 | }
395 |
396 | __try {
397 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
398 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
399 | SetLastError(ERROR_BAD_EXE_FORMAT);
400 | return NULL;
401 | }
402 |
403 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
404 | pDosHeader->e_lfanew);
405 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
406 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
407 | return NULL;
408 | }
409 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
410 | SetLastError(ERROR_EXE_MARKED_INVALID);
411 | return NULL;
412 | }
413 | SetLastError(NO_ERROR);
414 |
415 | return (pNtHeader->OptionalHeader.SizeOfImage);
416 | }
417 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
418 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
419 | SetLastError(ERROR_EXE_MARKED_INVALID);
420 | return NULL;
421 | }
422 | }
423 |
424 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr)
425 | {
426 | MEMORY_BASIC_INFORMATION mbi;
427 | ZeroMemory(&mbi, sizeof(mbi));
428 |
429 | __try {
430 | if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) {
431 | SetLastError(ERROR_BAD_EXE_FORMAT);
432 | return NULL;
433 | }
434 |
435 | // Skip uncommitted regions and guard pages.
436 | //
437 | if ((mbi.State != MEM_COMMIT) ||
438 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
439 | (mbi.Protect & PAGE_GUARD)) {
440 | SetLastError(ERROR_BAD_EXE_FORMAT);
441 | return NULL;
442 | }
443 |
444 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
445 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
446 | SetLastError(ERROR_BAD_EXE_FORMAT);
447 | return NULL;
448 | }
449 |
450 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
451 | pDosHeader->e_lfanew);
452 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
453 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
454 | return NULL;
455 | }
456 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
457 | SetLastError(ERROR_EXE_MARKED_INVALID);
458 | return NULL;
459 | }
460 | SetLastError(NO_ERROR);
461 |
462 | return (HMODULE)pDosHeader;
463 | }
464 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
465 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
466 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
467 | return NULL;
468 | }
469 | }
470 |
471 |
472 | static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr)
473 | {
474 | if (raddr != NULL) {
475 | return ((PBYTE)pDosHeader) + raddr;
476 | }
477 | return NULL;
478 | }
479 |
480 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
481 | _In_opt_ PVOID pContext,
482 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
483 | {
484 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
485 | if (hModule == NULL) {
486 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
487 | }
488 |
489 | __try {
490 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
491 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
492 | SetLastError(ERROR_BAD_EXE_FORMAT);
493 | return NULL;
494 | }
495 |
496 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
497 | pDosHeader->e_lfanew);
498 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
499 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
500 | return FALSE;
501 | }
502 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
503 | SetLastError(ERROR_EXE_MARKED_INVALID);
504 | return FALSE;
505 | }
506 |
507 | PIMAGE_EXPORT_DIRECTORY pExportDir
508 | = (PIMAGE_EXPORT_DIRECTORY)
509 | RvaAdjust(pDosHeader,
510 | pNtHeader->OptionalHeader
511 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
512 |
513 | if (pExportDir == NULL) {
514 | SetLastError(ERROR_EXE_MARKED_INVALID);
515 | return FALSE;
516 | }
517 |
518 | PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader
519 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
520 | PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
521 | PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
522 | PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
523 |
524 | for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
525 | PBYTE pbCode = (pdwFunctions != NULL)
526 | ? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
527 | PCHAR pszName = NULL;
528 |
529 | // if the pointer is in the export region, then it is a forwarder.
530 | if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) {
531 | pbCode = NULL;
532 | }
533 |
534 | for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
535 | if (pwOrdinals[n] == nFunc) {
536 | pszName = (pdwNames != NULL)
537 | ? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
538 | break;
539 | }
540 | }
541 | ULONG nOrdinal = pExportDir->Base + nFunc;
542 |
543 | if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
544 | break;
545 | }
546 | }
547 | SetLastError(NO_ERROR);
548 | return TRUE;
549 | }
550 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
551 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
552 | SetLastError(ERROR_EXE_MARKED_INVALID);
553 | return NULL;
554 | }
555 | }
556 |
557 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
558 | _In_opt_ PVOID pContext,
559 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
560 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc)
561 | {
562 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
563 | if (hModule == NULL) {
564 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
565 | }
566 |
567 | __try {
568 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
569 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
570 | SetLastError(ERROR_BAD_EXE_FORMAT);
571 | return FALSE;
572 | }
573 |
574 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
575 | pDosHeader->e_lfanew);
576 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
577 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
578 | return FALSE;
579 | }
580 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
581 | SetLastError(ERROR_EXE_MARKED_INVALID);
582 | return FALSE;
583 | }
584 |
585 | PIMAGE_IMPORT_DESCRIPTOR iidp
586 | = (PIMAGE_IMPORT_DESCRIPTOR)
587 | RvaAdjust(pDosHeader,
588 | pNtHeader->OptionalHeader
589 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
590 |
591 | if (iidp == NULL) {
592 | SetLastError(ERROR_EXE_MARKED_INVALID);
593 | return FALSE;
594 | }
595 |
596 | for (; iidp->OriginalFirstThunk != 0; iidp++) {
597 |
598 | PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
599 | if (pszName == NULL) {
600 | SetLastError(ERROR_EXE_MARKED_INVALID);
601 | return FALSE;
602 | }
603 |
604 | PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
605 | RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
606 | PVOID * pAddrs = (PVOID *)
607 | RvaAdjust(pDosHeader, iidp->FirstThunk);
608 |
609 | HMODULE hFile = DetourGetContainingModule(pAddrs[0]);
610 |
611 | if (pfImportFile != NULL) {
612 | if (!pfImportFile(pContext, hFile, pszName)) {
613 | break;
614 | }
615 | }
616 |
617 | DWORD nNames = 0;
618 | if (pThunks) {
619 | for (; pThunks[nNames].u1.Ordinal; nNames++) {
620 | DWORD nOrdinal = 0;
621 | PCSTR pszFunc = NULL;
622 |
623 | if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
624 | nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
625 | }
626 | else {
627 | pszFunc = (PCSTR)RvaAdjust(pDosHeader,
628 | (DWORD)pThunks[nNames].u1.AddressOfData + 2);
629 | }
630 |
631 | if (pfImportFunc != NULL) {
632 | if (!pfImportFunc(pContext,
633 | nOrdinal,
634 | pszFunc,
635 | &pAddrs[nNames])) {
636 | break;
637 | }
638 | }
639 | }
640 | if (pfImportFunc != NULL) {
641 | pfImportFunc(pContext, 0, NULL, NULL);
642 | }
643 | }
644 | }
645 | if (pfImportFile != NULL) {
646 | pfImportFile(pContext, NULL, NULL);
647 | }
648 | SetLastError(NO_ERROR);
649 | return TRUE;
650 | }
651 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
652 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
653 | SetLastError(ERROR_EXE_MARKED_INVALID);
654 | return FALSE;
655 | }
656 | }
657 |
658 | // Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex".
659 | struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT
660 | {
661 | PVOID pContext;
662 | PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc;
663 | };
664 |
665 | // Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx
666 | // for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on.
667 |
668 | static
669 | BOOL
670 | CALLBACK
671 | DetourEnumerateImportsThunk(_In_ PVOID VoidContext,
672 | _In_ DWORD nOrdinal,
673 | _In_opt_ PCSTR pszFunc,
674 | _In_opt_ PVOID* ppvFunc)
675 | {
676 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const
677 | pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext;
678 | return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL);
679 | }
680 |
681 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
682 | _In_opt_ PVOID pContext,
683 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
684 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
685 | {
686 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
687 |
688 | return DetourEnumerateImportsEx(hModule,
689 | (PVOID)&context,
690 | pfImportFile,
691 | &DetourEnumerateImportsThunk);
692 | }
693 |
694 | static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
695 | {
696 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
697 | if (hModule == NULL) {
698 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
699 | }
700 |
701 | __try {
702 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
703 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
704 | SetLastError(ERROR_BAD_EXE_FORMAT);
705 | return NULL;
706 | }
707 |
708 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
709 | pDosHeader->e_lfanew);
710 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
711 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
712 | return NULL;
713 | }
714 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
715 | SetLastError(ERROR_EXE_MARKED_INVALID);
716 | return NULL;
717 | }
718 |
719 | PIMAGE_SECTION_HEADER pSectionHeaders
720 | = (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
721 | + sizeof(pNtHeader->Signature)
722 | + sizeof(pNtHeader->FileHeader)
723 | + pNtHeader->FileHeader.SizeOfOptionalHeader);
724 |
725 | for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
726 | if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
727 | if (pSectionHeaders[n].VirtualAddress == 0 ||
728 | pSectionHeaders[n].SizeOfRawData == 0) {
729 |
730 | break;
731 | }
732 |
733 | PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
734 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
735 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
736 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
737 |
738 | break;
739 | }
740 |
741 | if (pHeader->nDataOffset == 0) {
742 | pHeader->nDataOffset = pHeader->cbHeaderSize;
743 | }
744 | SetLastError(NO_ERROR);
745 | return (PBYTE)pHeader;
746 | }
747 | }
748 | SetLastError(ERROR_EXE_MARKED_INVALID);
749 | return NULL;
750 | }
751 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
752 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
753 | SetLastError(ERROR_EXE_MARKED_INVALID);
754 | return NULL;
755 | }
756 | }
757 |
758 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule)
759 | {
760 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
761 | if (pBinary == NULL) {
762 | // Error set by GetPayloadSectionFromModule.
763 | return 0;
764 | }
765 |
766 | __try {
767 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
768 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
769 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
770 |
771 | SetLastError(ERROR_INVALID_HANDLE);
772 | return 0;
773 | }
774 | SetLastError(NO_ERROR);
775 | return pHeader->cbDataSize;
776 | }
777 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
778 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
779 | SetLastError(ERROR_INVALID_HANDLE);
780 | return 0;
781 | }
782 | }
783 |
784 | _Writable_bytes_(*pcbData)
785 | _Readable_bytes_(*pcbData)
786 | _Success_(return != NULL)
787 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
788 | _In_ REFGUID rguid,
789 | _Out_ DWORD *pcbData)
790 | {
791 | PBYTE pbData = NULL;
792 | if (pcbData) {
793 | *pcbData = 0;
794 | }
795 |
796 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
797 | if (pBinary == NULL) {
798 | // Error set by GetPayloadSectionFromModule.
799 | return NULL;
800 | }
801 |
802 | __try {
803 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
804 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
805 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
806 |
807 | SetLastError(ERROR_INVALID_EXE_SIGNATURE);
808 | return NULL;
809 | }
810 |
811 | PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
812 | PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
813 |
814 | for (pbData = pbBeg; pbData < pbEnd;) {
815 | DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
816 |
817 | if (pSection->guid.Data1 == rguid.Data1 &&
818 | pSection->guid.Data2 == rguid.Data2 &&
819 | pSection->guid.Data3 == rguid.Data3 &&
820 | pSection->guid.Data4[0] == rguid.Data4[0] &&
821 | pSection->guid.Data4[1] == rguid.Data4[1] &&
822 | pSection->guid.Data4[2] == rguid.Data4[2] &&
823 | pSection->guid.Data4[3] == rguid.Data4[3] &&
824 | pSection->guid.Data4[4] == rguid.Data4[4] &&
825 | pSection->guid.Data4[5] == rguid.Data4[5] &&
826 | pSection->guid.Data4[6] == rguid.Data4[6] &&
827 | pSection->guid.Data4[7] == rguid.Data4[7]) {
828 |
829 | if (pcbData) {
830 | *pcbData = pSection->cbBytes - sizeof(*pSection);
831 | SetLastError(NO_ERROR);
832 | return (PBYTE)(pSection + 1);
833 | }
834 | }
835 |
836 | pbData = (PBYTE)pSection + pSection->cbBytes;
837 | }
838 | SetLastError(ERROR_INVALID_HANDLE);
839 | return NULL;
840 | }
841 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
842 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
843 | SetLastError(ERROR_INVALID_HANDLE);
844 | return NULL;
845 | }
846 | }
847 |
848 | _Writable_bytes_(*pcbData)
849 | _Readable_bytes_(*pcbData)
850 | _Success_(return != NULL)
851 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
852 | _Out_ DWORD * pcbData)
853 | {
854 | for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
855 | PVOID pvData;
856 |
857 | pvData = DetourFindPayload(hMod, rguid, pcbData);
858 | if (pvData != NULL) {
859 | return pvData;
860 | }
861 | }
862 | SetLastError(ERROR_MOD_NOT_FOUND);
863 | return NULL;
864 | }
865 |
866 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
867 | _In_ DWORD cbData)
868 | {
869 | PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
870 |
871 | if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
872 | SetLastError(ERROR_BAD_EXE_FORMAT);
873 | return FALSE;
874 | }
875 |
876 | DWORD dwPermIdh = ~0u;
877 | DWORD dwPermInh = ~0u;
878 | DWORD dwPermClr = ~0u;
879 | DWORD dwIgnore;
880 | BOOL fSucceeded = FALSE;
881 | BOOL fUpdated32To64 = FALSE;
882 |
883 | if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
884 | // If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
885 | // that.
886 | fUpdated32To64 = TRUE;
887 | }
888 |
889 | if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh,
890 | PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
891 | if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh,
892 | PAGE_EXECUTE_READWRITE, &dwPermInh)) {
893 |
894 | CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
895 | CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
896 |
897 | if (pder->pclr != NULL && !fUpdated32To64) {
898 | if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
899 | PAGE_EXECUTE_READWRITE, &dwPermClr)) {
900 | CopyMemory(pder->pclr, &pder->clr, pder->cbclr);
901 | VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore);
902 | fSucceeded = TRUE;
903 | }
904 | }
905 | else {
906 | fSucceeded = TRUE;
907 | }
908 | VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore);
909 | }
910 | VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
911 | }
912 | return fSucceeded;
913 | }
914 |
915 | BOOL WINAPI DetourRestoreAfterWith()
916 | {
917 | PVOID pvData;
918 | DWORD cbData;
919 |
920 | pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData);
921 |
922 | if (pvData != NULL && cbData != 0) {
923 | return DetourRestoreAfterWithEx(pvData, cbData);
924 | }
925 | SetLastError(ERROR_MOD_NOT_FOUND);
926 | return FALSE;
927 | }
928 |
929 | // End of File
930 |
--------------------------------------------------------------------------------
/ShooterGameCheat/dllmain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/dllmain.cpp
--------------------------------------------------------------------------------
/ShooterGameCheat/game/adapt_data.h:
--------------------------------------------------------------------------------
1 | #ifndef _SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_
2 | #define _SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_
3 |
4 | #define GAME_GWORLD (0x2F70070)
5 | #define GAME_GENGINE (0x2F6D6F8)
6 | #define GAME_NAMES_PTR (0x2E6D0F8)
7 | #define GAME_PERSISTENT_LEVEL_OFFSET (0x30)
8 | #define GAME_GAMEINSTANCE_OFFSET (0x160)
9 | #define GAME_LOCALPLAYER_OFFSET (0x38)
10 | #define GAME_PLAYERCONTROLLER_OFFSET (0x30)
11 | #define GAME_ALL_ACTORS_OFFSET (0x98)
12 | #define GAME_OBJ_NAME_OFFSET (0x18)
13 | #define GAME_MEDIUM_FONT (0x70)
14 | #define GAME_CANVAS_OFFSET (0x380)
15 | #define GAME_ACKNOWLEDEGED_PAWN_OFFSET (0x3B0)
16 | #define GAME_CONTROLROTATION_OFFSET (0x398)
17 | #define GAME_PLAYERCONTROLLER_HUD_OFFSET (0x3C0)
18 | #define GAME_PLAYER_CAMERA_MANAGER (0x3C8)
19 | #define GAME_CAMERACACHEPRIVATE (0x1A20)
20 | #define GAME_CAMERA_POV (0x10)
21 | #define GAME_CAMERA_ROTATION (0xC)
22 | #define GAME_CAMERA_LOCATION (0x0)
23 | #define GAME_CAMERA_FOV (0x18)
24 | #define GAME_PAWN_PLAYERSTATE_OFFSET (0x350)
25 | #define GAME_PAWN_HEALTH_OFFSET (0x92C)
26 | #define GAME_PAWN_NAME (0x438)
27 | #define GAME_PAWN_ROOTCOMMENT (0x158)
28 | #define GAME_PAWN_LOCATION (0x164)
29 | #define GAME_GET_CAMERADAMAGESTARTLOCATION_OFFSET (0x524080)
30 | #define GAME_WORLD_TO_SCREEN_OFFSET (0x1542850)
31 | #define GAME_LINEOFSIGHTTO_OFFSET (0x148B970)
32 | #define GAME_GET_VIEWPORT_SIZE (0x175BD00)
33 | #define GAME_DRAWTEXT_OFFSET (0x155E920)
34 | #define GAME_DRAW_HUD_OFFSET (0x155E280)
35 | #define GAME_DRAW_RECT_OFFSET (0x155E870)
36 | #define GAME_DRAW_LINE_OFFSET (0x155E350)
37 |
38 |
39 | #endif //_SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_
40 |
--------------------------------------------------------------------------------
/ShooterGameCheat/game/base_struct.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #ifdef _MSC_VER
8 | #pragma pack(push, 0x8)
9 | #endif
10 |
11 | struct FVector
12 | {
13 | float X; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
14 | float Y; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
15 | float Z; // 0x0008(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
16 |
17 | FVector(float f_x = 0, float f_y = 0, float f_z = 0)
18 | {
19 | X = f_x;
20 | Y = f_y;
21 | Z = f_z;
22 | }
23 |
24 | float Dot(const FVector& v) const
25 | {
26 | return (X * v.X + Y * v.Y + Z * v.Z);
27 | }
28 |
29 | FVector operator-(FVector v) const
30 | {
31 | return FVector(X - v.X, Y - v.Y, Z - v.Z);
32 | }
33 | };
34 |
35 | struct FVector2D
36 | {
37 | float X; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
38 | float Y; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
39 |
40 | inline FVector2D()
41 | : X(0), Y(0)
42 | { }
43 |
44 | inline FVector2D(float x, float y)
45 | : X(x),
46 | Y(y)
47 | { }
48 |
49 | };
50 |
51 | struct FLinearColor
52 | {
53 | float R; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
54 | float G; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
55 | float B; // 0x0008(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
56 | float A; // 0x000C(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData)
57 |
58 | inline FLinearColor()
59 | : R(0), G(0), B(0), A(0)
60 | { }
61 |
62 | inline FLinearColor(float r, float g, float b, float a)
63 | : R(r),
64 | G(g),
65 | B(b),
66 | A(a)
67 | { }
68 |
69 | };
70 |
71 | //
72 | //struct vector3D
73 | //{
74 | // float x;
75 | // float y;
76 | // float z;
77 | //
78 | // vector3D(float f_x = 0, float f_y = 0, float f_z = 0)
79 | // {
80 | // x = f_x;
81 | // y = f_y;
82 | // z = f_z;
83 | // }
84 | //
85 | //
86 | // float Dot(const vector3D& v) const
87 | // {
88 | // return (x * v.x + y * v.y + z * v.z);
89 | // }
90 | //
91 | // vector3D operator-(vector3D v) const
92 | // {
93 | // return vector3D(x - v.x, y - v.y, z - v.z);
94 | // }
95 | //
96 | // float distance(vector3D v)
97 | // {
98 | // return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2) + pow((v.z - z), 2));
99 | // }
100 | //
101 | // vector3D(float* v)
102 | // {
103 | // x = v[0];
104 | // y = v[1];
105 | // z = v[2];
106 | // }
107 | //};
108 |
109 |
110 |
111 | struct vector2D
112 | {
113 | float x;
114 | float y;
115 |
116 | vector2D(float f_x = 0, float f_y = 0)
117 | {
118 | x = f_x;
119 | y = f_y;
120 | }
121 |
122 | float distance(vector2D v)
123 | {
124 | return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2));
125 | }
126 | };
127 |
128 | struct vMatrix
129 | {
130 | vMatrix() {}
131 | vMatrix(
132 | float m00, float m01, float m02, float m03,
133 | float m10, float m11, float m12, float m13,
134 | float m20, float m21, float m22, float m23)
135 | {
136 | m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03;
137 | m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13;
138 | m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23;
139 | }
140 |
141 | float* operator[](int i)
142 | {
143 | /* Assert((i >= 0) && (i < 3));*/
144 | return m_flMatVal[i];
145 | }
146 | const float* operator[](int i) const
147 | {
148 | /*Assert((i >= 0) && (i < 3)); */
149 | return m_flMatVal[i];
150 | }
151 |
152 | float* Base() { return &m_flMatVal[0][0]; }
153 | const float* Base() const { return &m_flMatVal[0][0]; }
154 |
155 | float m_flMatVal[3][4];
156 | };
157 |
158 | template
159 | class TArray
160 | {
161 | friend class FString;
162 |
163 | public:
164 | inline TArray()
165 | {
166 | Data = nullptr;
167 | Count = Max = 0;
168 | };
169 |
170 | inline int Num() const
171 | {
172 | return Count;
173 | };
174 |
175 | inline T& operator[](int i)
176 | {
177 | return Data[i];
178 | };
179 |
180 | inline const T& operator[](int i) const
181 | {
182 | return Data[i];
183 | };
184 |
185 | inline bool IsValidIndex(int i) const
186 | {
187 | return i < Num();
188 | }
189 |
190 | public:
191 | T* Data;
192 | int32_t Count;
193 | int32_t Max;
194 | };
195 |
196 | class FString : public TArray
197 | {
198 | public:
199 | inline FString()
200 | {
201 | };
202 |
203 | FString(const wchar_t* other)
204 | {
205 | Max = Count = *other ? std::wcslen(other) + 1 : 0;
206 |
207 | if (Count)
208 | {
209 | Data = const_cast(other);
210 | }
211 | };
212 |
213 | inline bool IsValid() const
214 | {
215 | return Data != nullptr;
216 | }
217 |
218 | inline const wchar_t* c_str() const
219 | {
220 | return Data;
221 | }
222 |
223 | std::string ToString() const
224 | {
225 | const auto length = std::wcslen(Data);
226 |
227 | std::string str(length, '\0');
228 |
229 | std::use_facet>(std::locale()).narrow(Data, Data + length, '?', &str[0]);
230 |
231 | return str;
232 | }
233 | };
234 |
235 | class FNameEntry
236 | {
237 | public:
238 | static const auto NAME_WIDE_MASK = 0x1;
239 | static const auto NAME_INDEX_SHIFT = 1;
240 |
241 | int32_t Index;
242 | char UnknownData00[0x04];
243 | FNameEntry* HashNext;
244 | union
245 | {
246 | char AnsiName[1024];
247 | wchar_t WideName[1024];
248 | };
249 |
250 | inline const int32_t GetIndex() const
251 | {
252 | return Index >> NAME_INDEX_SHIFT;
253 | }
254 |
255 | inline bool IsWide() const
256 | {
257 | return Index & NAME_WIDE_MASK;
258 | }
259 |
260 | inline const char* GetAnsiName() const
261 | {
262 | return AnsiName;
263 | }
264 |
265 | inline const wchar_t* GetWideName() const
266 | {
267 | return WideName;
268 | }
269 | };
270 |
271 | template
272 | class TStaticIndirectArrayThreadSafeRead
273 | {
274 | public:
275 | inline size_t Num() const
276 | {
277 | return NumElements;
278 | }
279 |
280 | inline bool IsValidIndex(int32_t index) const
281 | {
282 | return index < Num() && index >= 0;
283 | }
284 |
285 | inline ElementType const* const& operator[](int32_t index) const
286 | {
287 | return *GetItemPtr(index);
288 | }
289 |
290 | private:
291 | inline ElementType const* const* GetItemPtr(int32_t Index) const
292 | {
293 | const auto ChunkIndex = Index / ElementsPerChunk;
294 | const auto WithinChunkIndex = Index % ElementsPerChunk;
295 | const auto Chunk = Chunks[ChunkIndex];
296 | return Chunk + WithinChunkIndex;
297 | }
298 |
299 | enum
300 | {
301 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk
302 | };
303 |
304 | ElementType** Chunks[ChunkTableSize];
305 | int32_t NumElements;
306 | int32_t NumChunks;
307 | };
308 |
309 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead;
310 |
311 |
312 | struct FName
313 | {
314 | union
315 | {
316 | struct
317 | {
318 | int32_t ComparisonIndex;
319 | int32_t Number;
320 | };
321 |
322 | uint64_t CompositeComparisonValue;
323 | };
324 |
325 | inline FName()
326 | : ComparisonIndex(0),
327 | Number(0)
328 | {
329 | };
330 |
331 | inline FName(int32_t i)
332 | : ComparisonIndex(i),
333 | Number(0)
334 | {
335 | };
336 |
337 | FName(const char* nameToFind)
338 | : ComparisonIndex(0),
339 | Number(0)
340 | {
341 | static std::unordered_set cache;
342 |
343 | for (auto i : cache)
344 | {
345 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind))
346 | {
347 | ComparisonIndex = i;
348 |
349 | return;
350 | }
351 | }
352 |
353 | for (auto i = 0; i < GetGlobalNames().Num(); ++i)
354 | {
355 | if (GetGlobalNames()[i] != nullptr)
356 | {
357 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind))
358 | {
359 | cache.insert(i);
360 |
361 | ComparisonIndex = i;
362 |
363 | return;
364 | }
365 | }
366 | }
367 | };
368 |
369 | static TNameEntryArray *GNames;
370 | static inline TNameEntryArray& GetGlobalNames()
371 | {
372 | return *GNames;
373 | };
374 |
375 | inline const char* GetName() const
376 | {
377 | return GetGlobalNames()[ComparisonIndex]->GetAnsiName();
378 | };
379 |
380 | inline bool operator==(const FName &other) const
381 | {
382 | return ComparisonIndex == other.ComparisonIndex;
383 | };
384 | };
385 |
386 | #ifdef _MSC_VER
387 | #pragma pack(pop)
388 | #endif
389 |
--------------------------------------------------------------------------------
/ShooterGameCheat/game/game.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/game/game.cpp
--------------------------------------------------------------------------------
/ShooterGameCheat/game/game.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "base_struct.h"
4 |
5 | namespace Game {
6 |
7 | using DrawHUDType = void(__fastcall*)(void *);
8 | using WorldToScreenType = bool(__fastcall*)(uint8_t*, FVector&, FVector2D&);
9 | using GetCameraDamageStartLocationType = FVector * (__fastcall*) (void*, FVector*, FVector*);
10 | using LineOfSightToType = bool(__fastcall*)(uint8_t*, uint8_t*, FVector, bool);
11 | using GetViewportSizeType = void(__thiscall*)(uint8_t*, int*, int*);
12 | using DrawTextType = float(__fastcall*)(uint8_t*, FString const&, FLinearColor, float, float, uint8_t*, float, bool);
13 | using DrawRectType = void(__fastcall*)(uint8_t*, FLinearColor, float, float, float, float);
14 | using DrawLineType = void(__fastcall*)(uint8_t*, float, float, float, float, FLinearColor, float);
15 |
16 | extern uint8_t** g_engine;
17 | extern uint8_t** g_world;
18 | extern WorldToScreenType g_w2s_func;
19 | extern DrawHUDType g_draw_hud_func;
20 | extern GetCameraDamageStartLocationType g_get_damage_start_location_func;
21 | extern LineOfSightToType g_line_of_sight_to_func;
22 | extern GetViewportSizeType g_get_viewport_size_func;
23 | extern DrawTextType g_draw_text_func;
24 | extern DrawRectType g_draw_rect_func;
25 | extern DrawLineType g_draw_line_func;
26 |
27 | uint8_t *get_local_player_controller(uint8_t **world);
28 | bool is_local_player(uint8_t **world, uint8_t* actor);
29 | uint8_t* get_pawn_state(uint8_t *pawn);
30 | float get_pawn_health(uint8_t *pawn);
31 | FString get_pawn_name(uint8_t *pawn);
32 | bool get_pawn_location(uint8_t *pawn, FVector *location);
33 | void get_local_player_location(uint8_t *controller, FVector *location);
34 | uint8_t *get_all_actors(uint8_t **world);
35 | std::string get_object_name(uint8_t *obj);
36 | void draw_text(uint8_t *hud, const FString& text, float x, float y, const FLinearColor& color);
37 | uint8_t* get_closest_visible_player(uint8_t** world);
38 | void cal_new_rotation(FVector local_pos, FVector target_pos, float &pitch, float &yaw);
39 | void set_local_player_rotation(uint8_t *controller, float &pitch, float &yaw);
40 |
41 | void draw_box(uint8_t *hud, float a, float b, float c, float d, FLinearColor color);
42 |
43 | FVector2D get_box_size(uint8_t *player_controller, FVector target_pos);
44 | bool world_to_screen(uint8_t *player_controller, FVector target_pos, FVector2D* screen_pos);
45 | }
--------------------------------------------------------------------------------
/ShooterGameCheat/shooter_game_cheat.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/shooter_game_cheat.cpp
--------------------------------------------------------------------------------
/ShooterGameCheat/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | namespace Utils {
6 |
7 | _inline void dbg_out(const char *str, ...)
8 | {
9 | char szMsg[1024] = { 0 };
10 |
11 | va_list ap;
12 | va_start(ap, str);
13 | _vsnprintf_s(szMsg, 1024 - 1, str, ap);
14 | va_end(ap);
15 |
16 | OutputDebugStringA(szMsg);
17 | }
18 |
19 | _inline float get_distance_3d(FVector x, FVector y)
20 | {
21 | FVector z;
22 | z.X = x.X - y.X;
23 | z.Y = x.Y - y.Y;
24 | z.Z = x.Z - y.Z;
25 |
26 | return sqrt(z.X * z.X + z.Y * z.Y + z.Z * z.Z);
27 | }
28 |
29 | _inline float get_distance_2d(FVector2D point1, FVector2D point2)
30 | {
31 | FVector2D heading;
32 | heading.X = point1.X - point2.X;
33 | heading.Y = point1.Y - point2.Y;
34 |
35 | float distanceSquared;
36 | float distance;
37 |
38 | distanceSquared = heading.X * heading.X + heading.Y * heading.Y;
39 | distance = sqrt(distanceSquared);
40 |
41 | return distance;
42 | }
43 | }
--------------------------------------------------------------------------------