metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,2027 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/os/main'
7
+ require 'metasm/dynldr'
8
+
9
+ module Metasm
10
+ class WinAPI < DynLdr
11
+ def self.api_not_found(lib, func)
12
+ puts "could not find symbol #{func.name.inspect} in #{lib.inspect}" if $VERBOSE and not func.attributes.to_a.include?('optional')
13
+ end
14
+
15
+ new_api_c <<EOS, 'kernel32'
16
+ #line #{__LINE__}
17
+
18
+ typedef char CHAR;
19
+ typedef unsigned char BYTE;
20
+ typedef unsigned short WORD, USHORT;
21
+ typedef unsigned int UINT;
22
+ typedef long LONG;
23
+ typedef unsigned long ULONG, DWORD, *LPDWORD;
24
+ typedef int BOOL;
25
+ typedef unsigned long long DWORD64, ULONGLONG;
26
+
27
+ typedef intptr_t INT_PTR, LONG_PTR;
28
+ typedef uintptr_t UINT_PTR, ULONG_PTR, DWORD_PTR, SIZE_T;
29
+ typedef LONG_PTR LPARAM;
30
+ typedef UINT_PTR WPARAM;
31
+ typedef LONG_PTR LRESULT;
32
+ typedef const CHAR *LPSTR, *LPCSTR;
33
+ typedef void VOID, *PVOID, *LPVOID;
34
+
35
+ typedef void *HANDLE;
36
+ typedef void *HMODULE;
37
+
38
+ #define INVALID_HANDLE_VALUE (HANDLE)-1
39
+ #define DECLSPEC_IMPORT __declspec(dllimport)
40
+ #define WINUSERAPI DECLSPEC_IMPORT
41
+ #define WINBASEAPI DECLSPEC_IMPORT
42
+ #define WINAPI __stdcall
43
+ #define CALLBACK __stdcall
44
+ #define CONST const
45
+ #define ZEROOK __attribute__((zero_not_fail))
46
+ #define __in __attribute__((in))
47
+ #define __out __attribute__((out))
48
+ #define __opt __attribute__((opt))
49
+ #define __inout __in __out
50
+ #define __in_opt __in __opt
51
+ #define __out_opt __out __opt
52
+ #define __inout_opt __inout __opt
53
+
54
+ #define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
55
+ #define INFINITE 0xFFFFFFFF
56
+
57
+ #define PAGE_NOACCESS 0x01
58
+ #define PAGE_READONLY 0x02
59
+ #define PAGE_READWRITE 0x04
60
+ #define PAGE_WRITECOPY 0x08
61
+ #define PAGE_EXECUTE 0x10
62
+ #define PAGE_EXECUTE_READ 0x20
63
+ #define PAGE_EXECUTE_READWRITE 0x40
64
+ #define PAGE_EXECUTE_WRITECOPY 0x80
65
+ #define PAGE_GUARD 0x100
66
+ #define PAGE_NOCACHE 0x200
67
+ #define PAGE_WRITECOMBINE 0x400
68
+ #define MEM_COMMIT 0x1000
69
+ #define MEM_RESERVE 0x2000
70
+ #define MEM_DECOMMIT 0x4000
71
+ #define MEM_RELEASE 0x8000
72
+ #define MEM_FREE 0x10000
73
+ #define MEM_PRIVATE 0x20000
74
+ #define MEM_MAPPED 0x40000
75
+ #define MEM_RESET 0x80000
76
+ #define MEM_TOP_DOWN 0x100000
77
+ #define MEM_WRITE_WATCH 0x200000
78
+ #define MEM_PHYSICAL 0x400000
79
+ #define MEM_LARGE_PAGES 0x20000000
80
+ #define MEM_4MB_PAGES 0x80000000
81
+ #define SEC_FILE 0x800000
82
+ #define SEC_IMAGE 0x1000000
83
+ #define SEC_RESERVE 0x4000000
84
+ #define SEC_COMMIT 0x8000000
85
+ #define SEC_NOCACHE 0x10000000
86
+ #define SEC_LARGE_PAGES 0x80000000
87
+ #define MEM_IMAGE SEC_IMAGE
88
+
89
+ #define DEBUG_PROCESS 0x00000001
90
+ #define DEBUG_ONLY_THIS_PROCESS 0x00000002
91
+ #define CREATE_SUSPENDED 0x00000004
92
+ #define DETACHED_PROCESS 0x00000008
93
+ #define CREATE_NEW_CONSOLE 0x00000010
94
+ #define NORMAL_PRIORITY_CLASS 0x00000020
95
+ #define IDLE_PRIORITY_CLASS 0x00000040
96
+ #define HIGH_PRIORITY_CLASS 0x00000080
97
+ #define REALTIME_PRIORITY_CLASS 0x00000100
98
+ #define CREATE_NEW_PROCESS_GROUP 0x00000200
99
+ #define CREATE_UNICODE_ENVIRONMENT 0x00000400
100
+ #define CREATE_SEPARATE_WOW_VDM 0x00000800
101
+ #define CREATE_SHARED_WOW_VDM 0x00001000
102
+ #define CREATE_FORCEDOS 0x00002000
103
+ #define BELOW_NORMAL_PRIORITY_CLASS 0x00004000
104
+ #define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
105
+ #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
106
+ #define CREATE_BREAKAWAY_FROM_JOB 0x01000000
107
+ #define CREATE_PRESERVE_CODE_AUTHZ_LEVEL 0x02000000
108
+ #define CREATE_DEFAULT_ERROR_MODE 0x04000000
109
+ #define CREATE_NO_WINDOW 0x08000000
110
+ #define PROFILE_USER 0x10000000
111
+ #define PROFILE_KERNEL 0x20000000
112
+ #define PROFILE_SERVER 0x40000000
113
+ #define CREATE_IGNORE_SYSTEM_DEFAULT 0x80000000
114
+
115
+ #define STATUS_WAIT_0 ((DWORD )0x00000000L)
116
+ #define STATUS_ABANDONED_WAIT_0 ((DWORD )0x00000080L)
117
+ #define STATUS_USER_APC ((DWORD )0x000000C0L)
118
+ #define STATUS_TIMEOUT ((DWORD )0x00000102L)
119
+ #define STATUS_PENDING ((DWORD )0x00000103L)
120
+ #define DBG_EXCEPTION_HANDLED ((DWORD )0x00010001L)
121
+ #define DBG_CONTINUE ((DWORD )0x00010002L)
122
+ #define STATUS_SEGMENT_NOTIFICATION ((DWORD )0x40000005L)
123
+ #define DBG_TERMINATE_THREAD ((DWORD )0x40010003L)
124
+ #define DBG_TERMINATE_PROCESS ((DWORD )0x40010004L)
125
+ #define DBG_CONTROL_C ((DWORD )0x40010005L)
126
+ #define DBG_CONTROL_BREAK ((DWORD )0x40010008L)
127
+ #define DBG_COMMAND_EXCEPTION ((DWORD )0x40010009L)
128
+ #define STATUS_GUARD_PAGE_VIOLATION ((DWORD )0x80000001L)
129
+ #define STATUS_DATATYPE_MISALIGNMENT ((DWORD )0x80000002L)
130
+ #define STATUS_BREAKPOINT ((DWORD )0x80000003L)
131
+ #define STATUS_SINGLE_STEP ((DWORD )0x80000004L)
132
+ #define DBG_EXCEPTION_NOT_HANDLED ((DWORD )0x80010001L)
133
+ #define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L)
134
+ #define STATUS_IN_PAGE_ERROR ((DWORD )0xC0000006L)
135
+ #define STATUS_INVALID_HANDLE ((DWORD )0xC0000008L)
136
+ #define STATUS_NO_MEMORY ((DWORD )0xC0000017L)
137
+ #define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL)
138
+ #define STATUS_NONCONTINUABLE_EXCEPTION ((DWORD )0xC0000025L)
139
+ #define STATUS_INVALID_DISPOSITION ((DWORD )0xC0000026L)
140
+ #define STATUS_ARRAY_BOUNDS_EXCEEDED ((DWORD )0xC000008CL)
141
+ #define STATUS_FLOAT_DENORMAL_OPERAND ((DWORD )0xC000008DL)
142
+ #define STATUS_FLOAT_DIVIDE_BY_ZERO ((DWORD )0xC000008EL)
143
+ #define STATUS_FLOAT_INEXACT_RESULT ((DWORD )0xC000008FL)
144
+ #define STATUS_FLOAT_INVALID_OPERATION ((DWORD )0xC0000090L)
145
+ #define STATUS_FLOAT_OVERFLOW ((DWORD )0xC0000091L)
146
+ #define STATUS_FLOAT_STACK_CHECK ((DWORD )0xC0000092L)
147
+ #define STATUS_FLOAT_UNDERFLOW ((DWORD )0xC0000093L)
148
+ #define STATUS_INTEGER_DIVIDE_BY_ZERO ((DWORD )0xC0000094L)
149
+ #define STATUS_INTEGER_OVERFLOW ((DWORD )0xC0000095L)
150
+ #define STATUS_PRIVILEGED_INSTRUCTION ((DWORD )0xC0000096L)
151
+ #define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL)
152
+ #define STATUS_CONTROL_C_EXIT ((DWORD )0xC000013AL)
153
+ #define STATUS_FLOAT_MULTIPLE_FAULTS ((DWORD )0xC00002B4L)
154
+ #define STATUS_FLOAT_MULTIPLE_TRAPS ((DWORD )0xC00002B5L)
155
+ #define STATUS_REG_NAT_CONSUMPTION ((DWORD )0xC00002C9L)
156
+
157
+ #define EXCEPTION_DEBUG_EVENT 1
158
+ #define CREATE_THREAD_DEBUG_EVENT 2
159
+ #define CREATE_PROCESS_DEBUG_EVENT 3
160
+ #define EXIT_THREAD_DEBUG_EVENT 4
161
+ #define EXIT_PROCESS_DEBUG_EVENT 5
162
+ #define LOAD_DLL_DEBUG_EVENT 6
163
+ #define UNLOAD_DLL_DEBUG_EVENT 7
164
+ #define OUTPUT_DEBUG_STRING_EVENT 8
165
+ #define RIP_EVENT 9
166
+
167
+ #define MAX_PATH 260
168
+
169
+ #define EXCEPTION_NONCONTINUABLE 0x1 // Noncontinuable exception
170
+ #define EXCEPTION_MAXIMUM_PARAMETERS 15 // maximum number of exception parameters
171
+
172
+ typedef struct _EXCEPTION_RECORD {
173
+ DWORD ExceptionCode;
174
+ DWORD ExceptionFlags; // noncontinuable
175
+ struct _EXCEPTION_RECORD *ExceptionRecord;
176
+ PVOID ExceptionAddress;
177
+ DWORD NumberParameters;
178
+ ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
179
+ } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
180
+
181
+ typedef struct _EXCEPTION_RECORD32 {
182
+ DWORD ExceptionCode;
183
+ DWORD ExceptionFlags;
184
+ DWORD ExceptionRecord;
185
+ DWORD ExceptionAddress;
186
+ DWORD NumberParameters;
187
+ DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
188
+ } EXCEPTION_RECORD32, *PEXCEPTION_RECORD32;
189
+
190
+ typedef struct _EXCEPTION_RECORD64 {
191
+ DWORD ExceptionCode;
192
+ DWORD ExceptionFlags;
193
+ DWORD64 ExceptionRecord;
194
+ DWORD64 ExceptionAddress;
195
+ DWORD NumberParameters;
196
+ DWORD __unusedAlignment;
197
+ DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
198
+ } EXCEPTION_RECORD64, *PEXCEPTION_RECORD64;
199
+
200
+ typedef struct _EXCEPTION_DEBUG_INFO {
201
+ EXCEPTION_RECORD ExceptionRecord;
202
+ DWORD dwFirstChance;
203
+ } EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO;
204
+
205
+ typedef struct _EXCEPTION_DEBUG_INFO32 {
206
+ EXCEPTION_RECORD32 ExceptionRecord;
207
+ DWORD dwFirstChance;
208
+ } EXCEPTION_DEBUG_INFO32;
209
+
210
+ typedef struct _EXCEPTION_DEBUG_INFO64 {
211
+ EXCEPTION_RECORD64 ExceptionRecord;
212
+ DWORD dwFirstChance;
213
+ } EXCEPTION_DEBUG_INFO64;
214
+
215
+ typedef struct _CREATE_THREAD_DEBUG_INFO {
216
+ HANDLE hThread;
217
+ LPVOID lpThreadLocalBase;
218
+ LPVOID lpStartAddress;
219
+ } CREATE_THREAD_DEBUG_INFO, *LPCREATE_THREAD_DEBUG_INFO;
220
+
221
+ typedef struct _CREATE_PROCESS_DEBUG_INFO {
222
+ HANDLE hFile;
223
+ HANDLE hProcess;
224
+ HANDLE hThread;
225
+ LPVOID lpBaseOfImage;
226
+ DWORD dwDebugInfoFileOffset;
227
+ DWORD nDebugInfoSize;
228
+ LPVOID lpThreadLocalBase;
229
+ LPVOID lpStartAddress;
230
+ LPVOID lpImageName;
231
+ WORD fUnicode;
232
+ } CREATE_PROCESS_DEBUG_INFO, *LPCREATE_PROCESS_DEBUG_INFO;
233
+
234
+ typedef struct _EXIT_THREAD_DEBUG_INFO {
235
+ DWORD dwExitCode;
236
+ } EXIT_THREAD_DEBUG_INFO, *LPEXIT_THREAD_DEBUG_INFO;
237
+
238
+ typedef struct _EXIT_PROCESS_DEBUG_INFO {
239
+ DWORD dwExitCode;
240
+ } EXIT_PROCESS_DEBUG_INFO, *LPEXIT_PROCESS_DEBUG_INFO;
241
+
242
+ typedef struct _LOAD_DLL_DEBUG_INFO {
243
+ HANDLE hFile;
244
+ LPVOID lpBaseOfDll;
245
+ DWORD dwDebugInfoFileOffset;
246
+ DWORD nDebugInfoSize;
247
+ LPVOID lpImageName;
248
+ WORD fUnicode;
249
+ } LOAD_DLL_DEBUG_INFO, *LPLOAD_DLL_DEBUG_INFO;
250
+
251
+ typedef struct _UNLOAD_DLL_DEBUG_INFO {
252
+ LPVOID lpBaseOfDll;
253
+ } UNLOAD_DLL_DEBUG_INFO, *LPUNLOAD_DLL_DEBUG_INFO;
254
+
255
+ typedef struct _OUTPUT_DEBUG_STRING_INFO {
256
+ LPSTR lpDebugStringData;
257
+ WORD fUnicode;
258
+ WORD nDebugStringLength;
259
+ } OUTPUT_DEBUG_STRING_INFO, *LPOUTPUT_DEBUG_STRING_INFO;
260
+
261
+ typedef struct _RIP_INFO {
262
+ DWORD dwError;
263
+ DWORD dwType;
264
+ } RIP_INFO, *LPRIP_INFO;
265
+
266
+ typedef struct _DEBUG_EVENT {
267
+ DWORD dwDebugEventCode;
268
+ DWORD dwProcessId;
269
+ DWORD dwThreadId;
270
+ // DWORD pad64; (implicit)
271
+ union {
272
+ EXCEPTION_DEBUG_INFO Exception;
273
+ EXCEPTION_DEBUG_INFO32 Exception32;
274
+ CREATE_THREAD_DEBUG_INFO CreateThread;
275
+ CREATE_PROCESS_DEBUG_INFO CreateProcess;
276
+ EXIT_THREAD_DEBUG_INFO ExitThread;
277
+ EXIT_PROCESS_DEBUG_INFO ExitProcess;
278
+ LOAD_DLL_DEBUG_INFO LoadDll;
279
+ UNLOAD_DLL_DEBUG_INFO UnloadDll;
280
+ OUTPUT_DEBUG_STRING_INFO DebugString;
281
+ RIP_INFO RipInfo;
282
+ } u;
283
+ } DEBUG_EVENT, *LPDEBUG_EVENT;
284
+
285
+ // XXX conflict with structure name..
286
+ #define CONTEXT_I386 0x00010000
287
+ #define CONTEXT_AMD64 0x00100000
288
+
289
+ #define CONTEXT_CONTROL 0x00000001L // SS:SP, CS:IP, FLAGS, BP
290
+ #define CONTEXT_INTEGER 0x00000002L // AX, BX, CX, DX, SI, DI
291
+ #define CONTEXT_SEGMENTS 0x00000004L // DS, ES, FS, GS
292
+ #define CONTEXT_FLOATING_POINT 0x00000008L // 387 state
293
+ #define CONTEXT_DEBUG_REGISTERS 0x00000010L // DB 0-3,6,7
294
+ #define CONTEXT_EXTENDED_REGISTERS 0x00000020L // cpu specific extensions
295
+ #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
296
+ #define CONTEXT_ALL (CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS)
297
+
298
+ #define CONTEXT_I386_FULL CONTEXT_I386 | CONTEXT_FULL
299
+ #define CONTEXT_I386_ALL CONTEXT_I386 | CONTEXT_ALL
300
+ #define CONTEXT_AMD64_FULL CONTEXT_AMD64 | CONTEXT_FULL
301
+ #define CONTEXT_AMD64_ALL CONTEXT_AMD64 | CONTEXT_ALL
302
+
303
+ #define MAXIMUM_SUPPORTED_EXTENSION 512
304
+ #define SIZE_OF_80387_REGISTERS 80
305
+
306
+ typedef struct _FPREG { BYTE b[10]; } FPREG;
307
+ typedef struct _XMMREG { ULONGLONG lo, hi; } XMMREG;
308
+
309
+ typedef struct _FLOATING_SAVE_AREA {
310
+ WORD ControlWord;
311
+ WORD res0;
312
+ WORD StatusWord;
313
+ WORD res1;
314
+ WORD TagWord;
315
+ WORD res2;
316
+ DWORD ErrorOffset;
317
+ WORD ErrorSelector;
318
+ WORD ErrorOpcode;
319
+ DWORD DataOffset;
320
+ WORD DataSelector;
321
+ WORD res3;
322
+ FPREG St[8];
323
+ DWORD Cr0NpxState;
324
+ } FLOATING_SAVE_AREA, *PFLOATING_SAVE_AREA;
325
+
326
+ typedef struct _CONTEXT_I386 {
327
+ DWORD ContextFlags;
328
+ DWORD Dr0;
329
+ DWORD Dr1;
330
+ DWORD Dr2;
331
+ DWORD Dr3;
332
+ DWORD Dr6;
333
+ DWORD Dr7;
334
+ FLOATING_SAVE_AREA FloatSave;
335
+ DWORD SegGs;
336
+ DWORD SegFs;
337
+ DWORD SegEs;
338
+ DWORD SegDs;
339
+ DWORD Edi;
340
+ DWORD Esi;
341
+ DWORD Ebx;
342
+ DWORD Edx;
343
+ DWORD Ecx;
344
+ DWORD Eax;
345
+ DWORD Ebp;
346
+ DWORD Eip;
347
+ DWORD SegCs;
348
+ DWORD EFlags;
349
+ DWORD Esp;
350
+ DWORD SegSs;
351
+
352
+ XMMREG Xmm[8];
353
+
354
+ BYTE ExtendedRegisters[24*16];
355
+ } *LPCONTEXT_I386, *LPCONTEXT;
356
+
357
+ typedef struct _CONTEXT_AMD64 {
358
+ DWORD64 P1Home; // Register parameter home addresses.
359
+ DWORD64 P2Home;
360
+ DWORD64 P3Home;
361
+ DWORD64 P4Home;
362
+ DWORD64 P5Home;
363
+ DWORD64 P6Home;
364
+
365
+ DWORD ContextFlags;
366
+ DWORD MxCsr;
367
+
368
+ WORD SegCs;
369
+ WORD SegDs;
370
+ WORD SegEs;
371
+ WORD SegFs;
372
+ WORD SegGs;
373
+ WORD SegSs;
374
+ DWORD RFlags;
375
+
376
+ DWORD64 Dr0;
377
+ DWORD64 Dr1;
378
+ DWORD64 Dr2;
379
+ DWORD64 Dr3;
380
+ DWORD64 Dr6;
381
+ DWORD64 Dr7;
382
+
383
+ DWORD64 Rax;
384
+ DWORD64 Rcx;
385
+ DWORD64 Rdx;
386
+ DWORD64 Rbx;
387
+ DWORD64 Rsp;
388
+ DWORD64 Rbp;
389
+ DWORD64 Rsi;
390
+ DWORD64 Rdi;
391
+ DWORD64 R8;
392
+ DWORD64 R9;
393
+ DWORD64 R10;
394
+ DWORD64 R11;
395
+ DWORD64 R12;
396
+ DWORD64 R13;
397
+ DWORD64 R14;
398
+ DWORD64 R15;
399
+ DWORD64 Rip;
400
+
401
+ WORD ControlWord;
402
+ WORD StatusWord;
403
+ BYTE TagWord;
404
+ BYTE resv1;
405
+ WORD ErrorOpcode;
406
+ DWORD ErrorOffset;
407
+ WORD ErrorSelector;
408
+ WORD resv2;
409
+ DWORD DataAtOffset;
410
+ WORD DataSelector;
411
+ WORD resv3;
412
+ DWORD MxCsr_f;
413
+ DWORD MxCsrMask;
414
+ XMMREG ST[8];
415
+ XMMREG Xmm[16];
416
+
417
+ XMMREG Vector[26];
418
+ DWORD64 VectorControl;
419
+
420
+ DWORD64 DebugControl;
421
+ DWORD64 LastBranchToRip;
422
+ DWORD64 LastBranchFromRip;
423
+ DWORD64 LastExceptionToRip;
424
+ DWORD64 LastExceptionFromRip;
425
+ } *LPCONTEXT_AMD64;
426
+
427
+ typedef struct _EXCEPTION_POINTERS {
428
+ PEXCEPTION_RECORD ExceptionRecord;
429
+ LPCONTEXT ContextRecord;
430
+ } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
431
+
432
+ #define STANDARD_RIGHTS_REQUIRED (0x000F0000L)
433
+ #define SYNCHRONIZE (0x00100000L)
434
+
435
+ #define PROCESS_TERMINATE (0x0001)
436
+ #define PROCESS_CREATE_THREAD (0x0002)
437
+ #define PROCESS_SET_SESSIONID (0x0004)
438
+ #define PROCESS_VM_OPERATION (0x0008)
439
+ #define PROCESS_VM_READ (0x0010)
440
+ #define PROCESS_VM_WRITE (0x0020)
441
+ #define PROCESS_DUP_HANDLE (0x0040)
442
+ #define PROCESS_CREATE_PROCESS (0x0080)
443
+ #define PROCESS_SET_QUOTA (0x0100)
444
+ #define PROCESS_SET_INFORMATION (0x0200)
445
+ #define PROCESS_QUERY_INFORMATION (0x0400)
446
+ #define PROCESS_SUSPEND_RESUME (0x0800)
447
+ #define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
448
+ #define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
449
+
450
+ #define THREAD_TERMINATE (0x0001)
451
+ #define THREAD_SUSPEND_RESUME (0x0002)
452
+ #define THREAD_GET_CONTEXT (0x0008)
453
+ #define THREAD_SET_CONTEXT (0x0010)
454
+ #define THREAD_SET_INFORMATION (0x0020)
455
+ #define THREAD_QUERY_INFORMATION (0x0040)
456
+ #define THREAD_SET_THREAD_TOKEN (0x0080)
457
+ #define THREAD_IMPERSONATE (0x0100)
458
+ #define THREAD_DIRECT_IMPERSONATION (0x0200)
459
+ #define THREAD_SET_LIMITED_INFORMATION (0x0400)
460
+ #define THREAD_QUERY_LIMITED_INFORMATION (0x0800)
461
+ #define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
462
+
463
+
464
+ typedef struct _STARTUPINFOA {
465
+ DWORD cb;
466
+ LPSTR lpReserved;
467
+ LPSTR lpDesktop;
468
+ LPSTR lpTitle;
469
+ DWORD dwX;
470
+ DWORD dwY;
471
+ DWORD dwXSize;
472
+ DWORD dwYSize;
473
+ DWORD dwXCountChars;
474
+ DWORD dwYCountChars;
475
+ DWORD dwFillAttribute;
476
+ DWORD dwFlags;
477
+ WORD wShowWindow;
478
+ WORD cbReserved2;
479
+ LPVOID lpReserved2;
480
+ HANDLE hStdInput;
481
+ HANDLE hStdOutput;
482
+ HANDLE hStdError;
483
+ } STARTUPINFOA, *LPSTARTUPINFOA;
484
+
485
+ typedef struct _PROCESS_INFORMATION {
486
+ HANDLE hProcess;
487
+ HANDLE hThread;
488
+ DWORD dwProcessId;
489
+ DWORD dwThreadId;
490
+ } PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
491
+
492
+
493
+ WINBASEAPI
494
+ HANDLE
495
+ WINAPI
496
+ OpenProcess(
497
+ __in DWORD dwDesiredAccess,
498
+ __in BOOL bInheritHandle,
499
+ __in DWORD dwProcessId
500
+ );
501
+
502
+ WINBASEAPI
503
+ HANDLE
504
+ WINAPI
505
+ GetCurrentProcess(VOID);
506
+
507
+ WINBASEAPI
508
+ DWORD
509
+ WINAPI
510
+ GetCurrentProcessId(VOID);
511
+
512
+ WINBASEAPI
513
+ BOOL
514
+ WINAPI
515
+ TerminateProcess(
516
+ __in HANDLE hProcess,
517
+ __in UINT uExitCode);
518
+
519
+ WINBASEAPI
520
+ BOOL
521
+ WINAPI
522
+ GetExitCodeProcess(
523
+ __in HANDLE hProcess,
524
+ __out LPDWORD lpExitCode);
525
+
526
+ WINBASEAPI
527
+ HANDLE
528
+ WINAPI
529
+ CreateRemoteThread(
530
+ __in HANDLE hProcess,
531
+ __in_opt LPVOID lpThreadAttributes,
532
+ __in DWORD dwStackSize,
533
+ __in LPVOID lpStartAddress,
534
+ __in_opt LPVOID lpParameter,
535
+ __in DWORD dwCreationFlags,
536
+ __out_opt LPDWORD lpThreadId);
537
+
538
+ /* Vista onwards only..
539
+ WINBASEAPI
540
+ DWORD
541
+ WINAPI
542
+ GetThreadId(
543
+ __in HANDLE Thread);
544
+ */
545
+
546
+ WINBASEAPI
547
+ DWORD
548
+ WINAPI
549
+ GetProcessId(
550
+ __in HANDLE Process);
551
+
552
+ WINBASEAPI
553
+ HANDLE
554
+ WINAPI
555
+ OpenThread(
556
+ __in DWORD dwDesiredAccess,
557
+ __in BOOL bInheritHandle,
558
+ __in DWORD dwThreadId);
559
+
560
+ WINBASEAPI
561
+ BOOL
562
+ WINAPI
563
+ TerminateThread(
564
+ __in HANDLE hThread,
565
+ __in DWORD dwExitCode);
566
+
567
+ WINBASEAPI
568
+ BOOL
569
+ WINAPI
570
+ GetExitCodeThread(
571
+ __in HANDLE hThread,
572
+ __out LPDWORD lpExitCode);
573
+
574
+ ZEROOK
575
+ WINBASEAPI
576
+ DWORD
577
+ WINAPI
578
+ GetLastError(VOID);
579
+
580
+ ZEROOK
581
+ WINBASEAPI
582
+ BOOL
583
+ WINAPI
584
+ ReadProcessMemory(
585
+ __in HANDLE hProcess,
586
+ __in LPVOID lpBaseAddress,
587
+ __out LPVOID lpBuffer,
588
+ __in DWORD nSize,
589
+ __out_opt DWORD *lpNumberOfBytesRead);
590
+
591
+ WINBASEAPI
592
+ BOOL
593
+ WINAPI
594
+ WriteProcessMemory(
595
+ __in HANDLE hProcess,
596
+ __in LPVOID lpBaseAddress,
597
+ __in LPVOID lpBuffer,
598
+ __in DWORD nSize,
599
+ __out_opt DWORD *lpNumberOfBytesWritten);
600
+
601
+ WINBASEAPI
602
+ BOOL
603
+ WINAPI
604
+ GetThreadContext(
605
+ __in HANDLE hThread,
606
+ __inout LPCONTEXT lpContext);
607
+
608
+ WINBASEAPI
609
+ BOOL
610
+ WINAPI
611
+ SetThreadContext(
612
+ __in HANDLE hThread,
613
+ __in LPCONTEXT lpContext);
614
+
615
+ WINBASEAPI
616
+ BOOL
617
+ WINAPI
618
+ __attribute__((optional))
619
+ Wow64GetThreadContext(
620
+ __in HANDLE hThread,
621
+ __inout LPCONTEXT_I386 lpContext);
622
+
623
+ WINBASEAPI
624
+ BOOL
625
+ WINAPI
626
+ __attribute__((optional))
627
+ Wow64SetThreadContext(
628
+ __in HANDLE hThread,
629
+ __inout LPCONTEXT_I386 lpContext);
630
+
631
+ ZEROOK
632
+ WINBASEAPI
633
+ DWORD
634
+ WINAPI
635
+ SuspendThread(
636
+ __in HANDLE hThread);
637
+
638
+ ZEROOK
639
+ WINBASEAPI
640
+ DWORD
641
+ WINAPI
642
+ __attribute__((optional))
643
+ Wow64SuspendThread(
644
+ __in HANDLE hThread);
645
+
646
+ ZEROOK
647
+ WINBASEAPI
648
+ DWORD
649
+ WINAPI
650
+ ResumeThread(
651
+ __in HANDLE hThread);
652
+
653
+ WINBASEAPI
654
+ VOID
655
+ WINAPI
656
+ DebugBreak(VOID);
657
+
658
+ ZEROOK
659
+ WINBASEAPI
660
+ BOOL
661
+ WINAPI
662
+ WaitForDebugEvent(
663
+ __in LPDEBUG_EVENT lpDebugEvent,
664
+ __in DWORD dwMilliseconds);
665
+
666
+ WINBASEAPI
667
+ BOOL
668
+ WINAPI
669
+ ContinueDebugEvent(
670
+ __in DWORD dwProcessId,
671
+ __in DWORD dwThreadId,
672
+ __in DWORD dwContinueStatus);
673
+
674
+ WINBASEAPI
675
+ BOOL
676
+ WINAPI
677
+ DebugActiveProcess(
678
+ __in DWORD dwProcessId);
679
+
680
+ WINBASEAPI
681
+ BOOL
682
+ WINAPI
683
+ DebugActiveProcessStop(
684
+ __in DWORD dwProcessId);
685
+
686
+ WINBASEAPI
687
+ BOOL
688
+ WINAPI
689
+ DebugSetProcessKillOnExit(
690
+ __in BOOL KillOnExit);
691
+
692
+ WINBASEAPI
693
+ BOOL
694
+ WINAPI
695
+ DebugBreakProcess (
696
+ __in HANDLE Process);
697
+
698
+ ZEROOK
699
+ WINBASEAPI
700
+ DWORD
701
+ WINAPI
702
+ FormatMessageA(
703
+ DWORD dwFlags,
704
+ LPVOID lpSource,
705
+ DWORD dwMessageId,
706
+ DWORD dwLanguageId,
707
+ LPSTR lpBuffer,
708
+ DWORD nSize,
709
+ LPVOID Arguments);
710
+
711
+ WINBASEAPI
712
+ BOOL
713
+ WINAPI
714
+ CreateProcessA(
715
+ __in_opt LPCSTR lpApplicationName,
716
+ __inout_opt LPSTR lpCommandLine,
717
+ __in_opt LPVOID lpProcessAttributes,
718
+ __in_opt LPVOID lpThreadAttributes,
719
+ __in BOOL bInheritHandles,
720
+ __in DWORD dwCreationFlags,
721
+ __in_opt LPVOID lpEnvironment,
722
+ __in_opt LPCSTR lpCurrentDirectory,
723
+ __in LPSTARTUPINFOA lpStartupInfo,
724
+ __out LPPROCESS_INFORMATION lpProcessInformation);
725
+
726
+ WINBASEAPI
727
+ BOOL
728
+ WINAPI
729
+ CloseHandle(
730
+ __in HANDLE hObject);
731
+
732
+ WINBASEAPI
733
+ LPVOID
734
+ WINAPI
735
+ VirtualAllocEx(
736
+ __in HANDLE hProcess,
737
+ __in_opt LPVOID lpAddress,
738
+ __in SIZE_T dwSize,
739
+ __in DWORD flAllocationType,
740
+ __in DWORD flProtect);
741
+
742
+ WINBASEAPI
743
+ BOOL
744
+ WINAPI
745
+ VirtualFreeEx(
746
+ __in HANDLE hProcess,
747
+ __in LPVOID lpAddress,
748
+ __in SIZE_T dwSize,
749
+ __in DWORD dwFreeType);
750
+
751
+ WINBASEAPI
752
+ BOOL
753
+ WINAPI
754
+ VirtualProtectEx(
755
+ __in HANDLE hProcess,
756
+ __in LPVOID lpAddress,
757
+ __in SIZE_T dwSize,
758
+ __in DWORD flNewProtect,
759
+ __out LPDWORD lpflOldProtect);
760
+
761
+ #define TH32CS_SNAPHEAPLIST 0x00000001
762
+ #define TH32CS_SNAPPROCESS 0x00000002
763
+ #define TH32CS_SNAPTHREAD 0x00000004
764
+ #define TH32CS_SNAPMODULE 0x00000008
765
+ #define TH32CS_SNAPMODULE32 0x00000010
766
+ #define TH32CS_INHERIT 0x80000000
767
+
768
+ HANDLE
769
+ WINAPI
770
+ CreateToolhelp32Snapshot(
771
+ DWORD dwFlags,
772
+ DWORD th32ProcessID
773
+ );
774
+
775
+ typedef struct tagPROCESSENTRY32
776
+ {
777
+ DWORD dwSize;
778
+ DWORD cntUsage;
779
+ DWORD th32ProcessID;
780
+ ULONG_PTR th32DefaultHeapID;
781
+ DWORD th32ModuleID;
782
+ DWORD cntThreads;
783
+ DWORD th32ParentProcessID;
784
+ LONG pcPriClassBase;
785
+ DWORD dwFlags;
786
+ CHAR szExeFile[MAX_PATH];
787
+ } PROCESSENTRY32;
788
+
789
+ BOOL
790
+ WINAPI
791
+ Process32First(
792
+ HANDLE hSnapshot,
793
+ PROCESSENTRY32 *lppe
794
+ );
795
+ BOOL
796
+ WINAPI
797
+ ZEROOK
798
+ Process32Next(
799
+ HANDLE hSnapshot,
800
+ PROCESSENTRY32 *lppe
801
+ );
802
+
803
+
804
+ typedef struct tagTHREADENTRY32
805
+ {
806
+ DWORD dwSize;
807
+ DWORD cntUsage;
808
+ DWORD th32ThreadID; // this thread
809
+ DWORD th32OwnerProcessID; // Process this thread is associated with
810
+ LONG tpBasePri;
811
+ LONG tpDeltaPri;
812
+ DWORD dwFlags;
813
+ } THREADENTRY32, * LPTHREADENTRY32;
814
+
815
+ BOOL
816
+ WINAPI
817
+ Thread32First(
818
+ HANDLE hSnapshot,
819
+ LPTHREADENTRY32 lpte
820
+ );
821
+ BOOL
822
+ WINAPI
823
+ ZEROOK
824
+ Thread32Next(
825
+ HANDLE hSnapshot,
826
+ LPTHREADENTRY32 lpte
827
+ );
828
+
829
+
830
+ typedef struct tagHEAPLIST32
831
+ {
832
+ SIZE_T dwSize;
833
+ DWORD th32ProcessID; // owning process
834
+ ULONG_PTR th32HeapID; // heap (in owning process context!)
835
+ DWORD dwFlags;
836
+ } HEAPLIST32, LPHEAPLIST32;
837
+
838
+ #define HF32_DEFAULT 1 // process default heap
839
+ #define HF32_SHARED 2 // is shared heap
840
+
841
+ BOOL
842
+ WINAPI
843
+ Heap32ListFirst(
844
+ HANDLE hSnapshot,
845
+ LPHEAPLIST32 lphl
846
+ );
847
+ BOOL
848
+ WINAPI
849
+ ZEROOK
850
+ Heap32ListNext(
851
+ HANDLE hSnapshot,
852
+ LPHEAPLIST32 lphl
853
+ );
854
+
855
+
856
+ typedef struct tagMODULEENTRY32
857
+ {
858
+ DWORD dwSize;
859
+ DWORD th32ModuleID;
860
+ DWORD th32ProcessID;
861
+ DWORD GlblcntUsage;
862
+ DWORD ProccntUsage;
863
+ ULONG_PTR modBaseAddr;
864
+ DWORD modBaseSize;
865
+ HMODULE hModule;
866
+ char szModule[256];
867
+ char szExePath[MAX_PATH];
868
+ } MODULEENTRY32;
869
+
870
+ BOOL
871
+ WINAPI
872
+ Module32First(
873
+ HANDLE hSnapshot,
874
+ MODULEENTRY32 *lpme
875
+ );
876
+ BOOL
877
+ WINAPI
878
+ ZEROOK
879
+ Module32Next(
880
+ HANDLE hSnapshot,
881
+ MODULEENTRY32 *lpme
882
+ );
883
+
884
+
885
+ typedef struct _MEMORY_BASIC_INFORMATION32 {
886
+ DWORD BaseAddress;
887
+ DWORD AllocationBase;
888
+ DWORD AllocationProtect; // initial (alloc time) prot
889
+ DWORD RegionSize;
890
+ DWORD State; // MEM_FREE/COMMIT/RESERVE
891
+ DWORD Protect; // PAGE_EXECUTE_READWRITE etc
892
+ DWORD Type; // MEM_IMAGE/MAPPED/PRIVATE
893
+ } MEMORY_BASIC_INFORMATION32, *PMEMORY_BASIC_INFORMATION32;
894
+
895
+ typedef struct _MEMORY_BASIC_INFORMATION64 {
896
+ ULONGLONG BaseAddress;
897
+ ULONGLONG AllocationBase;
898
+ DWORD AllocationProtect;
899
+ DWORD __alignment1;
900
+ ULONGLONG RegionSize;
901
+ DWORD State;
902
+ DWORD Protect;
903
+ DWORD Type;
904
+ DWORD __alignment2;
905
+ } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;
906
+
907
+ SIZE_T
908
+ WINAPI
909
+ ZEROOK
910
+ VirtualQueryEx(
911
+ HANDLE hProcess,
912
+ LPVOID lpAddress,
913
+ PMEMORY_BASIC_INFORMATION32 lpBuffer,
914
+ SIZE_T dwLength // sizeof lpBuffer
915
+ );
916
+
917
+ typedef struct _LDT_ENTRY {
918
+ WORD LimitLow;
919
+ WORD BaseLow;
920
+ union {
921
+ struct {
922
+ BYTE BaseMid;
923
+ BYTE Flags1;
924
+ BYTE Flags2;
925
+ BYTE BaseHi;
926
+ } Bytes;
927
+ struct {
928
+ DWORD BaseMid :8;
929
+ DWORD Type :5;
930
+ DWORD Dpl :2;
931
+ DWORD Pres :1;
932
+ DWORD LimitHi :4;
933
+ DWORD Sys :1;
934
+ DWORD Reserved_0 :1;
935
+ DWORD Default_Big :1;
936
+ DWORD Granularity :1;
937
+ DWORD BaseHi :8;
938
+ } Bits;
939
+ } HighWord;
940
+ } LDT_ENTRY;
941
+
942
+ BOOL
943
+ WINAPI
944
+ GetThreadSelectorEntry(
945
+ HANDLE hThread,
946
+ DWORD dwSelector,
947
+ LDT_ENTRY *lpSelectorEntry
948
+ );
949
+
950
+ BOOL
951
+ WINAPI
952
+ __attribute__((optional))
953
+ IsWow64Process(
954
+ HANDLE hProcess,
955
+ BOOL *wow64
956
+ );
957
+
958
+ EOS
959
+
960
+ new_api_c <<EOS, 'advapi32'
961
+ #line #{__LINE__}
962
+
963
+ #define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L)
964
+ #define SE_PRIVILEGE_ENABLED (0x00000002L)
965
+ #define SE_PRIVILEGE_REMOVED (0X00000004L)
966
+ #define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L)
967
+
968
+ #define TOKEN_ASSIGN_PRIMARY (0x0001)
969
+ #define TOKEN_DUPLICATE (0x0002)
970
+ #define TOKEN_IMPERSONATE (0x0004)
971
+ #define TOKEN_QUERY (0x0008)
972
+ #define TOKEN_QUERY_SOURCE (0x0010)
973
+ #define TOKEN_ADJUST_PRIVILEGES (0x0020)
974
+ #define TOKEN_ADJUST_GROUPS (0x0040)
975
+ #define TOKEN_ADJUST_DEFAULT (0x0080)
976
+ #define TOKEN_ADJUST_SESSIONID (0x0100)
977
+
978
+ typedef struct _LUID {
979
+ DWORD LowPart;
980
+ LONG HighPart;
981
+ } LUID, *PLUID;
982
+
983
+ typedef struct _LUID_AND_ATTRIBUTES {
984
+ LUID Luid;
985
+ DWORD Attributes;
986
+ } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES;
987
+
988
+ typedef struct _TOKEN_PRIVILEGES {
989
+ DWORD PrivilegeCount;
990
+ LUID_AND_ATTRIBUTES Privileges[1];
991
+ } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
992
+
993
+
994
+ BOOL
995
+ WINAPI
996
+ LookupPrivilegeNameA(
997
+ __in_opt LPCSTR lpSystemName,
998
+ __in PLUID lpLuid,
999
+ __out LPSTR lpName,
1000
+ __inout LPDWORD cchName);
1001
+
1002
+ BOOL
1003
+ WINAPI
1004
+ LookupPrivilegeValueA(
1005
+ __in_opt LPCSTR lpSystemName,
1006
+ __in LPCSTR lpName,
1007
+ __out PLUID lpLuid);
1008
+
1009
+ BOOL
1010
+ WINAPI
1011
+ AdjustTokenPrivileges (
1012
+ __in HANDLE TokenHandle,
1013
+ __in BOOL DisableAllPrivileges,
1014
+ __in_opt PTOKEN_PRIVILEGES NewState,
1015
+ __in DWORD BufferLength,
1016
+ __out PTOKEN_PRIVILEGES PreviousState,
1017
+ __out_opt DWORD *ReturnLength);
1018
+
1019
+ BOOL
1020
+ WINAPI
1021
+ OpenProcessToken (
1022
+ __in HANDLE ProcessHandle,
1023
+ __in DWORD DesiredAccess,
1024
+ __out HANDLE *TokenHandle);
1025
+
1026
+
1027
+ BOOL
1028
+ WINAPI
1029
+ OpenThreadToken (
1030
+ __in HANDLE ThreadHandle,
1031
+ __in DWORD DesiredAccess,
1032
+ __in BOOL OpenAsSelf,
1033
+ __out HANDLE *TokenHandle);
1034
+ EOS
1035
+ SE_DEBUG_NAME = 'SeDebugPrivilege'
1036
+
1037
+ new_api_c <<EOS, 'ntdll'
1038
+ #line #{__LINE__}
1039
+
1040
+ typedef LONG NTSTATUS;
1041
+
1042
+ typedef enum _PROCESSINFOCLASS {
1043
+ ProcessBasicInformation,
1044
+ ProcessQuotaLimits,
1045
+ ProcessIoCounters,
1046
+ ProcessVmCounters,
1047
+ ProcessTimes,
1048
+ ProcessBasePriority,
1049
+ ProcessRaisePriority,
1050
+ ProcessDebugPort,
1051
+ ProcessExceptionPort,
1052
+ ProcessAccessToken,
1053
+ ProcessLdtInformation,
1054
+ ProcessLdtSize,
1055
+ ProcessDefaultHardErrorMode,
1056
+ ProcessIoPortHandlers,
1057
+ ProcessPooledUsageAndLimits,
1058
+ ProcessWorkingSetWatch,
1059
+ ProcessUserModeIOPL,
1060
+ ProcessEnableAlignmentFaultFixup,
1061
+ ProcessPriorityClass,
1062
+ ProcessWx86Information,
1063
+ ProcessHandleCount,
1064
+ ProcessAffinityMask,
1065
+ ProcessPriorityBoost,
1066
+ ProcessDeviceMap,
1067
+ ProcessSessionInformation,
1068
+ ProcessForegroundInformation,
1069
+ ProcessWow64Information,
1070
+ ProcessImageFileName,
1071
+ ProcessLUIDDeviceMapsEnabled,
1072
+ ProcessBreakOnTermination,
1073
+ ProcessDebugObjectHandle,
1074
+ ProcessDebugFlags,
1075
+ ProcessHandleTracing
1076
+ } PROCESSINFOCLASS;
1077
+
1078
+ typedef enum _THREADINFOCLASS {
1079
+ ThreadBasicInformation,
1080
+ ThreadTimes,
1081
+ ThreadPriority,
1082
+ ThreadBasePriority,
1083
+ ThreadAffinityMask,
1084
+ ThreadImpersonationToken,
1085
+ ThreadDescriptorTableEntry,
1086
+ ThreadEnableAlignmentFaultFixup,
1087
+ ThreadEventPair_Reusable,
1088
+ ThreadQuerySetWin32StartAddress,
1089
+ ThreadZeroTlsCell,
1090
+ ThreadPerformanceCount,
1091
+ ThreadAmILastThread,
1092
+ ThreadIdealProcessor,
1093
+ ThreadPriorityBoost,
1094
+ ThreadSetTlsArrayAddress,
1095
+ ThreadIsIoPending,
1096
+ ThreadHideFromDebugger,
1097
+ ThreadBreakOnTermination
1098
+ } THREADINFOCLASS;
1099
+
1100
+ typedef enum _MEMORYINFOCLASS {
1101
+ MemoryBasicInformation,
1102
+ MemoryDunnoLol,
1103
+ MemoryMapFileName
1104
+ } MEMORYINFOCLASS;
1105
+
1106
+ typedef struct _CLIENT_ID {
1107
+ HANDLE UniqueProcess;
1108
+ HANDLE UniqueThread;
1109
+ } CLIENT_ID;
1110
+
1111
+ typedef struct _PROCESS_BASIC_INFORMATION {
1112
+ PVOID Reserved1;
1113
+ PVOID PebBaseAddress;
1114
+ PVOID Reserved2[2];
1115
+ ULONG_PTR UniqueProcessId;
1116
+ PVOID Reserved3;
1117
+ } PROCESS_BASIC_INFORMATION;
1118
+
1119
+ typedef struct _THREAD_BASIC_INFORMATION {
1120
+ NTSTATUS ExitStatus;
1121
+ PVOID TebBaseAddress;
1122
+ CLIENT_ID ClientId;
1123
+ ULONG_PTR AffinityMask;
1124
+ LONG Priority;
1125
+ LONG BasePriority;
1126
+ } THREAD_BASIC_INFORMATION;
1127
+
1128
+ typedef struct _UNICODE_STRING {
1129
+ USHORT Length;
1130
+ USHORT MaximumLength;
1131
+ USHORT *Buffer;
1132
+ } UNICODE_STRING;
1133
+
1134
+ ZEROOK
1135
+ NTSTATUS
1136
+ WINAPI
1137
+ NtQueryInformationProcess(
1138
+ HANDLE ProcessHandle,
1139
+ PROCESSINFOCLASS ProcessInformationClass,
1140
+ PVOID ProcessInformation,
1141
+ ULONG ProcessInformationLength,
1142
+ ULONG *ReturnLength
1143
+ );
1144
+
1145
+ ZEROOK
1146
+ NTSTATUS
1147
+ WINAPI
1148
+ NtQueryInformationThread (
1149
+ HANDLE ThreadHandle,
1150
+ THREADINFOCLASS ThreadInformationClass,
1151
+ PVOID ThreadInformation,
1152
+ ULONG ThreadInformationLength,
1153
+ ULONG *ReturnLength
1154
+ );
1155
+
1156
+ ZEROOK
1157
+ NTSTATUS
1158
+ WINAPI
1159
+ NtQueryVirtualMemory (
1160
+ HANDLE ProcessHandle,
1161
+ PVOID BaseAddress,
1162
+ MEMORYINFOCLASS MemoryInformationClass,
1163
+ PVOID MemoryInformation,
1164
+ ULONG MemoryInformationLength,
1165
+ ULONG *ReturnLength
1166
+ );
1167
+
1168
+ EOS
1169
+
1170
+ # convert a native function return value
1171
+ # if the native does not have the zero_not_fail attribute, convert 0
1172
+ # to nil, and print a message on stdout
1173
+ def self.convert_ret_c2rb(fproto, ret)
1174
+ @last_err_msg = nil
1175
+ if ret == 0 and not fproto.has_attribute 'zero_not_fail'
1176
+ # save error msg so that last_error_msg returns the same thing if called again
1177
+ puts "WinAPI: error in #{fproto.name}: #{@last_err_msg = last_error_msg}" if $VERBOSE
1178
+ nil
1179
+ else super(fproto, ret)
1180
+ end
1181
+ end
1182
+
1183
+ # retrieve the textual error message relative to GetLastError
1184
+ def self.last_error_msg(errno = nil)
1185
+ return @last_err_msg if @last_err_msg
1186
+ errno ||= getlasterror
1187
+ message = ' '*512
1188
+ if formatmessagea(FORMAT_MESSAGE_FROM_SYSTEM, nil, errno, 0, message, message.length, nil) == 0
1189
+ message = 'unknown error %x' % errno
1190
+ else
1191
+ message = message[0, message.index(?\0)] if message.index(?\0)
1192
+ message.chomp!
1193
+ end
1194
+ message
1195
+ end
1196
+ end
1197
+
1198
+ class WinOS < OS
1199
+ class Process < OS::Process
1200
+ attr_accessor :ppid
1201
+ def initialize(pid, handle=nil)
1202
+ @pid = pid
1203
+ @handle = handle
1204
+ end
1205
+
1206
+ # on-demand cached openprocess(ALL_ACCESS) handle
1207
+ def handle
1208
+ @handle ||= WinAPI.openprocess(WinAPI::PROCESS_ALL_ACCESS, 0, @pid)
1209
+ end
1210
+ attr_writer :handle
1211
+
1212
+ # return/create a WindowsRemoteString
1213
+ def memory
1214
+ @memory ||= WindowsRemoteString.new(handle)
1215
+ end
1216
+ attr_writer :memory
1217
+
1218
+ def debugger
1219
+ @debugger ||= WinDebugger.new(@pid)
1220
+ end
1221
+ attr_writer :debugger
1222
+
1223
+ # returns the memory address size of the target process
1224
+ def addrsz
1225
+ @addrsz ||= if WinAPI.respond_to?(:iswow64process)
1226
+ byte = 0.chr*8
1227
+ if WinAPI.iswow64process(handle, byte)
1228
+ if byte != 0.chr*8
1229
+ 32 # target = wow64
1230
+ elsif WinAPI.iswow64process(WinAPI.getcurrentprocess, byte) and byte != 0.chr*8
1231
+ 64 # us = wow64, target is not
1232
+ else
1233
+ WinAPI.host_cpu.size
1234
+ end
1235
+ else
1236
+ WinAPI.host_cpu.size
1237
+ end
1238
+ end
1239
+ end
1240
+
1241
+ def modules
1242
+ WinOS.list_modules(@pid)
1243
+ end
1244
+
1245
+ def threads
1246
+ WinOS.list_threads(@pid)
1247
+ end
1248
+
1249
+ def heaps
1250
+ WinOS.list_heaps(@pid)
1251
+ end
1252
+
1253
+ # return a list of [addr_start, length, perms]
1254
+ def mappings
1255
+ addr = 0
1256
+ list = []
1257
+ info = WinAPI.alloc_c_struct("MEMORY_BASIC_INFORMATION#{addrsz}")
1258
+ path = [0xff].pack('C') * 512
1259
+
1260
+ hcache = heaps
1261
+
1262
+ while WinAPI.virtualqueryex(handle, addr, info, info.length) != 0
1263
+ addr += info.regionsize
1264
+ next unless info.state & WinAPI::MEM_COMMIT > 0
1265
+
1266
+ prot = {
1267
+ WinAPI::PAGE_NOACCESS => '---',
1268
+ WinAPI::PAGE_READONLY => 'r--',
1269
+ WinAPI::PAGE_READWRITE => 'rw-',
1270
+ WinAPI::PAGE_WRITECOPY => 'rw-',
1271
+ WinAPI::PAGE_EXECUTE => '--x',
1272
+ WinAPI::PAGE_EXECUTE_READ => 'r-x',
1273
+ WinAPI::PAGE_EXECUTE_READWRITE => 'rwx',
1274
+ WinAPI::PAGE_EXECUTE_WRITECOPY => 'rwx'
1275
+ }[info[:protect] & 0xff]
1276
+ prot << 'g' if info[:protect] & WinAPI::PAGE_GUARD > 0
1277
+ prot << 'p' if info[:type] & WinAPI::MEM_PRIVATE > 0
1278
+
1279
+ if h = hcache[info.baseaddress]
1280
+ a = []
1281
+ a << 'default' if h[:default]
1282
+ a << 'shared' if h[:shared]
1283
+ a << 'heap'
1284
+ #a << h[:flags].to_s(16)
1285
+ cmt = '[' + a.join(' ') + ']'
1286
+ elsif WinAPI.ntqueryvirtualmemory(handle, info.baseaddress, WinAPI::MEMORYMAPFILENAME, path, path.length, 0) == 0
1287
+ us = WinAPI.decode_c_struct('UNICODE_STRING', path)
1288
+ s = WinAPI.decode_c_ary('USHORT', us['Length']/2, WinAPI.memory_read(us['Buffer'], us['MaximumLength']))
1289
+ cmt = s.to_strz
1290
+ else
1291
+ cmt = ''
1292
+ end
1293
+
1294
+ list << [info.baseaddress, info.regionsize, prot, cmt]
1295
+ end
1296
+
1297
+ list
1298
+ end
1299
+
1300
+ def peb_base
1301
+ @peb_base ||=
1302
+ if WinAPI.respond_to?(:ntqueryinformationprocess)
1303
+ pinfo = WinAPI.alloc_c_struct('PROCESS_BASIC_INFORMATION')
1304
+ if WinAPI.ntqueryinformationprocess(handle, WinAPI::PROCESSBASICINFORMATION, pinfo, pinfo.length, 0) == 0
1305
+ pinfo.pebbaseaddress
1306
+ end
1307
+ else
1308
+ # pre-NT: all pebs should have the same addr
1309
+ WinAPI.new_func_asm('unsigned get_peb(void)', 'mov eax, fs:[30h] ret') { WinAPI.get_peb }
1310
+ end
1311
+ end
1312
+ attr_writer :peb_base
1313
+
1314
+ def terminate(exitcode=0)
1315
+ WinAPI.terminateprocess(handle, exitcode)
1316
+ end
1317
+ end
1318
+
1319
+ class Thread
1320
+ attr_accessor :tid
1321
+ attr_accessor :process
1322
+
1323
+ def initialize(tid, handle=nil, process=nil)
1324
+ @tid = tid
1325
+ @handle = handle
1326
+ @process = process
1327
+ end
1328
+
1329
+ def handle
1330
+ @handle ||= WinAPI.openthread(WinAPI::THREAD_ALL_ACCESS, 0, @tid)
1331
+ end
1332
+ attr_writer :handle
1333
+
1334
+ # return the address of the TEB for the target thread
1335
+ def teb_base
1336
+ @teb_base ||=
1337
+ if WinAPI.respond_to?(:ntqueryinformationthread)
1338
+ tinfo = WinAPI.alloc_c_struct('THREAD_BASIC_INFORMATION')
1339
+ if WinAPI.ntqueryinformationthread(handle, WinAPI::THREADBASICINFORMATION, tinfo, tinfo.length, 0) == 0
1340
+ tinfo.tebbaseaddress
1341
+ end
1342
+ else
1343
+ fs = context { |c| c[:fs] }
1344
+ ldte = WinAPI.alloc_c_struct('LDT_ENTRY')
1345
+ if WinAPI.getthreadselectorentry(handle, fs, ldte)
1346
+ ldte.baselow | (ldte.basemid << 16) | (ldte.basehi << 24)
1347
+ end
1348
+ end
1349
+ end
1350
+ attr_writer :teb_base
1351
+
1352
+ # increment the suspend count of the target thread - stop at >0
1353
+ def suspend
1354
+ if WinAPI.host_cpu.size == 64 and process and process.addrsz == 32
1355
+ WinAPI.wow64suspendthread(handle)
1356
+ else
1357
+ WinAPI.suspendthread(handle)
1358
+ end
1359
+ end
1360
+
1361
+ # decrease the suspend count of the target thread - runs at 0
1362
+ def resume
1363
+ WinAPI.resumethread(handle)
1364
+ end
1365
+
1366
+ def terminate(exitcode=0)
1367
+ WinAPI.terminatethread(handle, exitcode)
1368
+ end
1369
+
1370
+ # returns a Context object. Can be reused, refresh the values with #update (target thread must be suspended)
1371
+ # if a block is given, suspend the thread, update the context, yield it, and resume the thread
1372
+ def context
1373
+ @context ||= Context.new(self, :all)
1374
+ if block_given?
1375
+ suspend
1376
+ @context.update
1377
+ ret = yield @context
1378
+ resume
1379
+ ret
1380
+ else
1381
+ @context
1382
+ end
1383
+ end
1384
+ attr_writer :context
1385
+
1386
+ class Context
1387
+ def initialize(thread, kind=:all)
1388
+ @handle = thread.handle
1389
+ tg = thread.process ? thread.process.addrsz : 32
1390
+ case WinAPI.host_cpu.shortname
1391
+ when 'ia32', 'x64'; tg = ((tg == 32) ? 'ia32' : 'x64')
1392
+ else raise "unsupported architecture #{tg}"
1393
+ end
1394
+
1395
+ @getcontext = :getthreadcontext
1396
+ @setcontext = :setthreadcontext
1397
+ case tg
1398
+ when 'ia32'
1399
+ @context = WinAPI.alloc_c_struct('_CONTEXT_I386')
1400
+ @context.contextflags = WinAPI::CONTEXT_I386_ALL
1401
+ if WinAPI.host_cpu.shortname == 'x64'
1402
+ @getcontext = :wow64getthreadcontext
1403
+ @setcontext = :wow64setthreadcontext
1404
+ end
1405
+ when 'x64'
1406
+ @context = WinAPI.alloc_c_struct('_CONTEXT_AMD64')
1407
+ @context.contextflags = WinAPI::CONTEXT_AMD64_ALL
1408
+ end
1409
+ end
1410
+
1411
+ # update the context to reflect the current thread reg values
1412
+ # call only when the thread is suspended
1413
+ def update
1414
+ WinAPI.send(@getcontext, @handle, @context)
1415
+ end
1416
+
1417
+ def [](k)
1418
+ case k.to_s
1419
+ when /^[cdefgs]s$/i
1420
+ @context["seg#{k}"]
1421
+ when /^st(\d*)/i
1422
+ v = @context['st'][$1.to_i]
1423
+ buf = v.str[v.str_off, 10]
1424
+ # TODO check this, 'D' is 8byte wide
1425
+ buf.unpack('D')[0]
1426
+ when /^xmm(\d+)/i
1427
+ v = @context['xmm'][$1.to_i]
1428
+ (v.hi << 64) | v.lo
1429
+ when /^mmx?(\d+)/i
1430
+ @context['xmm'][$1.to_i].lo
1431
+ else
1432
+ @context[k]
1433
+ end
1434
+ end
1435
+
1436
+ def []=(k, v)
1437
+ case k.to_s
1438
+ when /^[cdefgs]s$/i
1439
+ @context["seg#{k}"] = v
1440
+ when /^st(\d*)/i
1441
+ # TODO check this, 'D' is 8byte wide
1442
+ buf = [v, 0, 0].pack('DCC')
1443
+ @context['st'][$1.to_i][0, 10] = buf
1444
+ when /^xmm(\d+)/i
1445
+ kk = @context['xmm'][$1.to_i]
1446
+ kk.lo = v & ((1<<64)-1)
1447
+ kk.hi = (v>>64) & ((1<<64)-1)
1448
+ when /^mmx?(\d+)/i
1449
+ @context['xmm'][$1.to_i].lo = v
1450
+ else
1451
+ @context[k] = v
1452
+ end
1453
+ WinAPI.send(@setcontext, @handle, @context)
1454
+ end
1455
+
1456
+ def method_missing(m, *a)
1457
+ if m.to_s[-1] == ?=
1458
+ super(m, *a) if a.length != 1
1459
+ send '[]=', m.to_s[0...-1], a[0]
1460
+ else
1461
+ super(m, *a) if a.length != 0
1462
+ send '[]', m
1463
+ end
1464
+ end
1465
+ end
1466
+ end
1467
+
1468
+ class << self
1469
+ # try to enable debug privilege in current process
1470
+ def get_debug_privilege
1471
+ # TODO use real structs / new_func_c
1472
+ htok = [0].pack('L')
1473
+ return if not WinAPI.openprocesstoken(WinAPI.getcurrentprocess(), WinAPI::TOKEN_ADJUST_PRIVILEGES | WinAPI::TOKEN_QUERY, htok)
1474
+ luid = [0, 0].pack('LL')
1475
+ return if not WinAPI.lookupprivilegevaluea(nil, WinAPI::SE_DEBUG_NAME, luid)
1476
+
1477
+ # priv.PrivilegeCount = 1;
1478
+ # priv.Privileges[0].Luid = luid;
1479
+ # priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1480
+ priv = luid.unpack('LL').unshift(1).push(WinAPI::SE_PRIVILEGE_ENABLED).pack('LLLL')
1481
+ return if not WinAPI.adjusttokenprivileges(htok.unpack('L').first, 0, priv, 0, nil, nil)
1482
+
1483
+ true
1484
+ end
1485
+
1486
+ # returns an array of Processes with pid/ppid/path filled
1487
+ def list_processes
1488
+ h = WinAPI.createtoolhelp32snapshot(WinAPI::TH32CS_SNAPPROCESS, 0)
1489
+ list = []
1490
+ pe = WinAPI.alloc_c_struct('PROCESSENTRY32', :dwsize => :size)
1491
+ return if not WinAPI.process32first(h, pe)
1492
+ loop do
1493
+ p = Process.new(pe.th32processid)
1494
+ p.ppid = pe.th32parentprocessid
1495
+ p.path = pe.szexefile.to_strz
1496
+ list << p if p.pid != 0
1497
+ break if WinAPI.process32next(h, pe) == 0
1498
+ end
1499
+ WinAPI.closehandle(h)
1500
+ list
1501
+ end
1502
+
1503
+ # retrieve the list of Modules for a process with addr/size/path filled
1504
+ def list_modules(pid)
1505
+ h = WinAPI.createtoolhelp32snapshot(WinAPI::TH32CS_SNAPMODULE, pid)
1506
+ return [] if h == WinAPI::INVALID_HANDLE_VALUE
1507
+ list = []
1508
+ me = WinAPI.alloc_c_struct('MODULEENTRY32', :dwsize => :size)
1509
+ return [] if not WinAPI.module32first(h, me)
1510
+ loop do
1511
+ m = Process::Module.new
1512
+ m.addr = me.modbaseaddr
1513
+ m.size = me.modbasesize
1514
+ m.path = me.szexepath.to_strz
1515
+ list << m
1516
+ break if WinAPI.module32next(h, me) == 0
1517
+ end
1518
+ WinAPI.closehandle(h)
1519
+ list
1520
+ end
1521
+
1522
+ # returns the list of thread ids of the system, optionally filtering by pid
1523
+ def list_threads(pid=nil)
1524
+ h = WinAPI.createtoolhelp32snapshot(WinAPI::TH32CS_SNAPTHREAD, 0)
1525
+ list = []
1526
+ te = WinAPI.alloc_c_struct('THREADENTRY32', :dwsize => :size)
1527
+ return [] if not WinAPI.thread32first(h, te)
1528
+ loop do
1529
+ list << te.th32threadid if not pid or te.th32ownerprocessid == pid
1530
+ break if WinAPI.thread32next(h, te) == 0
1531
+ end
1532
+ WinAPI.closehandle(h)
1533
+ list
1534
+ end
1535
+
1536
+ # returns the heaps of the process, from a toolhelp snapshot SNAPHEAPLIST
1537
+ # this is a hash
1538
+ # heap_addr => { :flags => integer (heap flags)
1539
+ # :shared => bool (from flags)
1540
+ # :default => bool (from flags) }
1541
+ def list_heaps(pid)
1542
+ h = WinAPI.createtoolhelp32snapshot(WinAPI::TH32CS_SNAPHEAPLIST, pid)
1543
+ return [] if h == WinAPI::INVALID_HANDLE_VALUE
1544
+ ret = {}
1545
+ he = WinAPI.alloc_c_struct('HEAPLIST32', :dwsize => :size)
1546
+ return [] if not WinAPI.heap32listfirst(h, he)
1547
+ loop do
1548
+ hash = ret[he.th32heapid] = { :flags => he.dwflags }
1549
+ hash[:default] = true if hash[:flags] & WinAPI::HF32_DEFAULT == WinAPI::HF32_DEFAULT
1550
+ hash[:shared] = true if hash[:flags] & WinAPI::HF32_SHARED == WinAPI::HF32_SHARED
1551
+ # TODO there are lots of other flags in there ! like 0x1000 / 0x8000
1552
+ break if WinAPI.heap32listnext(h, he) == 0
1553
+ end
1554
+ WinAPI.closehandle(h)
1555
+ ret
1556
+ end
1557
+
1558
+
1559
+ # create a debugger for the target pid/path
1560
+ def create_debugger(path)
1561
+ WinDebugger.new(path)
1562
+ end
1563
+
1564
+ # Injects a shellcode into the memory space of targetproc
1565
+ # target is a WinOS::Process
1566
+ # shellcode may be a String (raw shellcode) or an EncodedData
1567
+ # With an EncodedData, unresolved relocations are solved using
1568
+ # exports of modules from the target address space ; also the
1569
+ # shellcode need not be position-independant.
1570
+ def inject_shellcode(target, shellcode)
1571
+ raise 'cannot open target memory' if not remote_mem = target.memory
1572
+ return if not injectaddr = WinAPI.virtualallocex(target.handle, 0, shellcode.length,
1573
+ WinAPI::MEM_COMMIT | WinAPI::MEM_RESERVE, WinAPI::PAGE_EXECUTE_READWRITE)
1574
+ puts 'remote buffer at %x' % injectaddr if $VERBOSE
1575
+
1576
+ if shellcode.kind_of? EncodedData
1577
+ fixup_shellcode_relocs(shellcode, target, remote_mem)
1578
+ shellcode.fixup! shellcode.binding(injectaddr)
1579
+ r = shellcode.reloc.values.map { |r_| r_.target }
1580
+ raise "unresolved shellcode relocs #{r.join(', ')}" if not r.empty?
1581
+ shellcode = shellcode.data
1582
+ end
1583
+
1584
+ # inject the shellcode
1585
+ remote_mem[injectaddr, shellcode.length] = shellcode
1586
+
1587
+ injectaddr
1588
+ end
1589
+
1590
+ def fixup_shellcode_relocs(shellcode, target, remote_mem)
1591
+ ext = shellcode.reloc_externals
1592
+ binding = {}
1593
+ while e = ext.pop
1594
+ next if binding[e]
1595
+ next if not lib = WindowsExports::EXPORT[e] # XXX could scan all exports... LoadLibrary ftw
1596
+ next if not m = target.modules.find { |m_| m_.path.downcase.include? lib.downcase }
1597
+ lib = LoadedPE.load(remote_mem[m.addr, 0x1000_0000])
1598
+ lib.decode_header
1599
+ lib.decode_exports
1600
+ lib.export.exports.each { |e_|
1601
+ next if not e_.name or not e_.target
1602
+ binding[e_.name] = m.addr + lib.label_rva(e_.target)
1603
+ }
1604
+ shellcode.fixup! binding
1605
+ end
1606
+ end
1607
+
1608
+ # creates a new thread in the target process, with the specified start address
1609
+ def createthread(target, startaddr)
1610
+ WinAPI.createremotethread(target.handle, 0, 0, startaddr, 0, 0, 0)
1611
+ end
1612
+
1613
+ # calls inject_shellcode and createthread
1614
+ def inject_run_shellcode(target, shellcode)
1615
+ raise "failed to inject shellcode" if not addr = inject_shellcode(target, shellcode)
1616
+ createthread(target, addr)
1617
+ end
1618
+
1619
+ # returns a Process associated to the process handle
1620
+ def open_process_handle(h)
1621
+ pid = WinAPI.getprocessid(h) rescue 0
1622
+ Process.new(pid, h)
1623
+ end
1624
+
1625
+ # returns the Process associated to pid if it is alive
1626
+ def open_process(pid)
1627
+ Process.new(pid) if check_process(pid)
1628
+ end
1629
+
1630
+ # returns true if the process pid exists and we can open it with QUERY_INFORMATION
1631
+ def check_process(pid)
1632
+ if h = WinAPI.openprocess(WinAPI::PROCESS_QUERY_INFORMATION, 0, pid)
1633
+ WinAPI.closehandle(h)
1634
+ true
1635
+ end
1636
+ end
1637
+
1638
+ # returns the Thread associated to a tid if it is alive
1639
+ def open_thread(tid)
1640
+ Thread.new(tid) if check_tid(tid)
1641
+ end
1642
+
1643
+ # check if the thread is alive and can be read with QUERY_INFO
1644
+ # and optionally if it belongs to pid
1645
+ def check_tid(tid, pid=nil)
1646
+ if h = WinAPI.openthread(WinAPI::THREAD_QUERY_INFORMATION, 0, tid)
1647
+ WinAPI.closehandle(h)
1648
+ not pid or list_threads(pid).include?(tid)
1649
+ end
1650
+ end
1651
+
1652
+ end # class << self
1653
+ end
1654
+
1655
+ class WindowsRemoteString < VirtualString
1656
+ def self.open_pid(pid, access = nil)
1657
+ if access
1658
+ handle = WinAPI.openprocess(access, 0, pid)
1659
+ else
1660
+ handle = WinAPI.openprocess(WinAPI::PROCESS_ALL_ACCESS, 0, pid)
1661
+ if not handle
1662
+ puts "cannot openprocess ALL_ACCESS pid #{pid}, try ro" if $VERBOSE
1663
+ handle = WinAPI.openprocess(WinAPI::PROCESS_VM_READ, 0, pid)
1664
+ end
1665
+ end
1666
+ raise "OpenProcess(#{pid}): #{WinAPI.last_error_msg}" if not handle
1667
+
1668
+ new(handle)
1669
+ end
1670
+
1671
+ attr_accessor :handle
1672
+
1673
+ # returns a virtual string proxying the specified process memory range
1674
+ # reads are cached (4096 aligned bytes read at once)
1675
+ # writes are done directly (if handle has appropriate privileges)
1676
+ def initialize(handle, addr_start=0, length=nil)
1677
+ @handle = handle
1678
+ length ||= 1 << (WinOS.open_process_handle(@handle).addrsz rescue 32)
1679
+ super(addr_start, length)
1680
+ end
1681
+
1682
+ def dup(addr = @addr_start, len = @length)
1683
+ self.class.new(@handle, addr, len)
1684
+ end
1685
+
1686
+ def rewrite_at(addr, data)
1687
+ WinAPI.writeprocessmemory(@handle, addr, data, data.length, nil)
1688
+ end
1689
+
1690
+ def get_page(addr, len=@pagelength)
1691
+ page = [0].pack('C')*len
1692
+ return if WinAPI.readprocessmemory(@handle, addr, page, len, 0) == 0
1693
+ page
1694
+ end
1695
+ end
1696
+
1697
+ # this class implements a high-level API over the Windows debugging primitives
1698
+ class WinDebugger < Debugger
1699
+ attr_accessor :os_process, :os_thread,
1700
+ :auto_fix_fs_bug,
1701
+ # is current exception handled? (arg to pass to continuedbgevt)
1702
+ :continuecode
1703
+
1704
+ attr_accessor :callback_unloadlibrary, :callback_debugstring, :callback_ripevent
1705
+
1706
+ def initialize(pidpath=nil)
1707
+ super()
1708
+ @pid_stuff_list << :os_process
1709
+ @tid_stuff_list << :os_thread << :ctx << :continuecode
1710
+
1711
+ @auto_fix_fs_bug = false
1712
+
1713
+ return if not pidpath
1714
+
1715
+ begin
1716
+ npid = Integer(pidpath)
1717
+ attach(npid)
1718
+ rescue ArgumentError
1719
+ create_process(pidpath)
1720
+ end
1721
+
1722
+ check_target until pid
1723
+ end
1724
+
1725
+ def shortname; 'windbg'; end
1726
+
1727
+ def attach(npid)
1728
+ WinAPI.debugactiveprocess(npid)
1729
+ WinAPI.debugsetprocesskillonexit(0) if WinAPI.respond_to?(:debugsetprocesskillonexit)
1730
+ 100.times {
1731
+ check_target
1732
+ break if pid
1733
+ }
1734
+ raise "attach failed" if not pid
1735
+ end
1736
+
1737
+ def create_process(target)
1738
+ startupinfo = WinAPI.alloc_c_struct('STARTUPINFOA', :cb => :size)
1739
+ processinfo = WinAPI.alloc_c_struct('PROCESS_INFORMATION')
1740
+ flags = WinAPI::DEBUG_PROCESS
1741
+ flags |= WinAPI::DEBUG_ONLY_THIS_PROCESS if not trace_children
1742
+ target = target.dup if target.frozen? # eg ARGV
1743
+ h = WinAPI.createprocessa(nil, target, nil, nil, 0, flags, nil, nil, startupinfo, processinfo)
1744
+ raise "CreateProcess: #{WinAPI.last_error_msg}" if not h
1745
+
1746
+ set_context(processinfo.dwprocessid, processinfo.dwthreadid)
1747
+ @os_process = WinOS::Process.new(processinfo.dwprocessid, processinfo.hprocess)
1748
+ @os_thread = WinOS::Thread.new(processinfo.dwthreadid, processinfo.hthread, @os_process)
1749
+ initialize_osprocess
1750
+ end
1751
+
1752
+ # called whenever we receive a handle to a new process being debugged, after initialisation of @os_process
1753
+ def initialize_osprocess
1754
+ initialize_cpu
1755
+ initialize_memory
1756
+ initialize_disassembler
1757
+ end
1758
+
1759
+ def initialize_newpid
1760
+ raise "non-existing pid #@pid" if pid and not WinOS.check_process(@pid)
1761
+ super()
1762
+ # os_process etc wait for CREATE_THREAD_DBGEVT
1763
+ end
1764
+
1765
+ def initialize_newtid
1766
+ super()
1767
+ # os_thread etc wait for CREATE_THREAD_DBGEVT
1768
+ @continuecode = WinAPI::DBG_CONTINUE #WinAPI::DBG_EXCEPTION_NOT_HANDLED
1769
+ end
1770
+
1771
+ def initialize_cpu
1772
+ # wait until we receive the CREATE_PROCESS_DBGEVT message
1773
+ return if not @os_process
1774
+ case WinAPI.host_cpu.shortname
1775
+ when 'ia32', 'x64'
1776
+ @cpu = Ia32.new(os_process.addrsz)
1777
+ else
1778
+ raise 'unsupported architecture'
1779
+ end
1780
+ end
1781
+
1782
+ def initialize_memory
1783
+ return if not @os_process
1784
+ @memory = os_process.memory
1785
+ end
1786
+
1787
+ def mappings
1788
+ os_process.mappings
1789
+ end
1790
+
1791
+ def modules
1792
+ os_process.modules
1793
+ end
1794
+
1795
+ def list_processes
1796
+ WinOS.list_processes
1797
+ end
1798
+
1799
+ def list_threads
1800
+ os_process.threads
1801
+ end
1802
+
1803
+ def check_pid(pid)
1804
+ WinOS.check_process(pid)
1805
+ end
1806
+
1807
+ def check_tid(tid)
1808
+ # dont raise() on the first set_context when os_proc is not set yet
1809
+ return true if not os_process
1810
+ super(tid)
1811
+ end
1812
+
1813
+ def ctx
1814
+ if not @ctx
1815
+ # swapin_tid => gui.swapin_tid => getreg before we init os_thread in EventCreateThread
1816
+ return Hash.new(0) if not os_thread
1817
+ @ctx = os_thread.context
1818
+ @ctx.update
1819
+ end
1820
+ @ctx
1821
+ end
1822
+
1823
+ def invalidate
1824
+ @ctx = nil
1825
+ super()
1826
+ end
1827
+
1828
+ def get_reg_value(r)
1829
+ ctx[r]
1830
+ end
1831
+
1832
+ def set_reg_value(r, v)
1833
+ ctx[r] = v
1834
+ end
1835
+
1836
+ def do_continue(*a)
1837
+ @cpu.dbg_disable_singlestep(self)
1838
+ WinAPI.continuedebugevent(@pid, @tid, @continuecode)
1839
+ end
1840
+
1841
+ def do_singlestep(*a)
1842
+ @cpu.dbg_enable_singlestep(self)
1843
+ WinAPI.continuedebugevent(@pid, @tid, @continuecode)
1844
+ end
1845
+
1846
+ def update_dbgev(ev)
1847
+ # XXX ev is static, copy all necessary values before yielding to something that may call check_target
1848
+ set_context ev.dwprocessid, ev.dwthreadid
1849
+ invalidate
1850
+ @continuecode = WinAPI::DBG_CONTINUE
1851
+
1852
+ # XXX reinterpret ev as struct32/64 depending on os_process.addrsz ?
1853
+ case ev.dwdebugeventcode
1854
+ when WinAPI::EXCEPTION_DEBUG_EVENT
1855
+ st = ev.exception
1856
+ str = st.exceptionrecord
1857
+ stf = st.dwfirstchance # non-zero = first chance
1858
+
1859
+ @state = :stopped
1860
+ @info = "exception"
1861
+
1862
+ # DWORD ExceptionCode;
1863
+ # DWORD ExceptionFlags;
1864
+ # struct _EXCEPTION_RECORD *ExceptionRecord;
1865
+ # PVOID ExceptionAddress;
1866
+ # DWORD NumberParameters;
1867
+ # ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
1868
+ case str.exceptioncode
1869
+ when WinAPI::STATUS_ACCESS_VIOLATION
1870
+ if @auto_fix_fs_bug and ctx.fs != 0x3b
1871
+ # fix bug in xpsp1 where fs would get a random value in a debugee
1872
+ log "wdbg: #{pid}:#{tid} fix fs bug" if $DEBUG
1873
+ ctx.fs = 0x3b
1874
+ resume_badbreak
1875
+ return
1876
+ end
1877
+ mode = case str.exceptioninformation[0]
1878
+ when 0; :r
1879
+ when 1; :w
1880
+ when 8; :x
1881
+ end
1882
+ addr = str.exceptioninformation[1]
1883
+ evt_exception(:type => 'access violation', :st => str, :firstchance => stf,
1884
+ :fault_addr => addr, :fault_access => mode)
1885
+ when WinAPI::STATUS_BREAKPOINT
1886
+ # we must ack ntdll interrupts on process start
1887
+ # but we should not mask process-generated exceptions by default..
1888
+ evt_bpx
1889
+ when WinAPI::STATUS_SINGLE_STEP
1890
+ evt_hwbp_singlestep
1891
+ else
1892
+ @status_name ||= WinAPI.cp.lexer.definition.keys.grep(/^STATUS_/).
1893
+ sort.inject({}) { |h, c| h.update WinAPI.const_get(c) => c }
1894
+ type = @status_name[str.exceptioncode] || str.exceptioncode.to_s(16)
1895
+ evt_exception(:type => type, :st => str, :firstchance => stf)
1896
+ end
1897
+
1898
+ when WinAPI::CREATE_THREAD_DEBUG_EVENT
1899
+ st = ev.createthread
1900
+ @os_thread ||= WinOS::Thread.new(@tid, st.hthread, os_process)
1901
+ @os_thread.teb_base = st.lpthreadlocalbase if st.lpthreadlocalbase.to_i != 0
1902
+ evt_newthread(:st => st)
1903
+
1904
+ when WinAPI::CREATE_PROCESS_DEBUG_EVENT
1905
+ # XXX 32 vs 64 struct undecidable before we get hprocess..
1906
+ st = ev.createprocess
1907
+ if not @os_process
1908
+ @os_process = WinOS::Process.new(@pid, st.hprocess)
1909
+ @os_thread ||= WinOS::Thread.new(@tid, st.hthread, os_process)
1910
+ initialize_osprocess
1911
+ else
1912
+ @os_thread ||= WinOS::Thread.new(@tid, st.hthread, os_process)
1913
+ end
1914
+ @os_thread.teb_base = st.lpthreadlocalbase if st.lpthreadlocalbase.to_i != 0
1915
+ hfile = st.hfile
1916
+ evt_newprocess(:st => st)
1917
+ WinAPI.closehandle(hfile)
1918
+
1919
+ when WinAPI::EXIT_THREAD_DEBUG_EVENT
1920
+ st = ev.exitthread
1921
+ evt_endthread(:exitcode => st.dwexitcode)
1922
+
1923
+ when WinAPI::EXIT_PROCESS_DEBUG_EVENT
1924
+ st = ev.exitprocess
1925
+ evt_endprocess(:exitcode => st.dwexitcode)
1926
+
1927
+ when WinAPI::LOAD_DLL_DEBUG_EVENT
1928
+ st = ev.loaddll
1929
+ hfile = st.hfile
1930
+ evt_loadlibrary(:address => st.lpbaseofdll, :st => st)
1931
+ WinAPI.closehandle(hfile)
1932
+
1933
+ when WinAPI::UNLOAD_DLL_DEBUG_EVENT
1934
+ st = ev.unloaddll
1935
+ evt_unloadlibrary(:address => st.lpbaseofdll)
1936
+
1937
+ when WinAPI::OUTPUT_DEBUG_STRING_EVENT
1938
+ st = ev.debugstring
1939
+ str = WinAPI.decode_c_ary("__int#{st.funicode != 0 ? 16 : 8}", st.ndebugstringlength, @memory, st.lpdebugstringdata) if st.lpdebugstringdata
1940
+ str = str.to_array.pack('C*') rescue str.to_array.pack('v*')
1941
+ evt_debugstring(:string => str, :st => str)
1942
+
1943
+ when WinAPI::RIP_EVENT
1944
+ st = ev.ripinfo
1945
+ evt_ripevent(:st => st)
1946
+ end
1947
+ end
1948
+
1949
+ def evt_debugstring(info={})
1950
+ @state = :stopped
1951
+ @info = "debugstring"
1952
+
1953
+ log "Debugstring: #{info[:string].inspect}"
1954
+
1955
+ callback_debugstring[info] if callback_debugstring
1956
+
1957
+ # allow callback to skip this call to continue() by setting info[:nocontinue] = true
1958
+ continue unless info[:nocontinue]
1959
+ end
1960
+
1961
+ def evt_unloadlibrary(info={})
1962
+ @state = :stopped
1963
+ @info = "unload library"
1964
+
1965
+ callback_unloadlibrary[info] if callback_unloadlibrary
1966
+
1967
+ continue unless info[:nocontinue]
1968
+ end
1969
+
1970
+ def evt_ripevent(info={})
1971
+ @state = :stopped
1972
+ @info = "rip_event" # wtf?
1973
+
1974
+ callback_ripevent[info] if callback_ripevent
1975
+
1976
+ continue unless info[:nocontinue]
1977
+ end
1978
+
1979
+ def do_check_target
1980
+ do_waitfordebug(0)
1981
+ end
1982
+
1983
+ def do_wait_target
1984
+ do_waitfordebug(WinAPI::INFINITE)
1985
+ end
1986
+
1987
+ def do_waitfordebug(timeout)
1988
+ @dbg_eventstruct ||= WinAPI.alloc_c_struct('_DEBUG_EVENT')
1989
+ if WinAPI.waitfordebugevent(@dbg_eventstruct, timeout) != 0
1990
+ update_dbgev(@dbg_eventstruct)
1991
+ end
1992
+ end
1993
+
1994
+ def break
1995
+ return if @state != :running
1996
+ if WinAPI.respond_to? :debugbreakprocess
1997
+ WinAPI.debugbreakprocess(os_process.handle)
1998
+ else
1999
+ suspend
2000
+ end
2001
+ end
2002
+
2003
+ def suspend
2004
+ os_thread.suspend
2005
+ @state = :stopped
2006
+ @info = 'thread suspended'
2007
+ end
2008
+
2009
+ def detach
2010
+ del_all_breakpoints
2011
+ if WinAPI.respond_to? :debugactiveprocessstop
2012
+ WinAPI.debugactiveprocessstop(@pid)
2013
+ else
2014
+ raise 'detach not supported'
2015
+ end
2016
+ del_pid
2017
+ end
2018
+
2019
+ def kill(exitcode=0)
2020
+ os_process.terminate(exitcode)
2021
+ end
2022
+
2023
+ def pass_current_exception(doit = true)
2024
+ @continuecode = (doit ? WinAPI::DBG_EXCEPTION_NOT_HANDLED : WinAPI::DBG_CONTINUE)
2025
+ end
2026
+ end
2027
+ end