metasm 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|