metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- 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
|