├── .gitattributes ├── .vscode └── settings.json ├── README.md ├── makefile ├── native.h ├── proxy.c ├── proxy.h └── test.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "windows.h": "c" 4 | } 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proxy Function Calls 2 | 3 | --- 4 | 5 | ### 引用 [BRC4 存储库](https://github.com/paranoidninja/Proxy-Function-Calls-For-ETwTI) 6 | 7 | --- 8 | 9 | ### 可以获取函数返回值的 Proxy Function Calls项目 10 | 11 | --- 12 | 13 | ### 优点 14 | - 代码逻辑清晰 15 | - 代码格式优美 16 | - 功能强大 17 | - 可以直接迁移到您的项目中 18 | 19 | 此项目仅用于学习探讨,本作者不对此代码负任何法律责任。 20 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | PROJECT := example 2 | 3 | SOURCES := $(wildcard *.c) 4 | HEADERS := $(wildcard *.h) 5 | 6 | EXE_x64 := bin/$(PROJECT).x64.exe 7 | EXE_x86 := bin/$(PROJECT).x86.exe 8 | 9 | CCX64 := x86_64-w64-mingw32-gcc 10 | CCX86 := i686-w64-mingw32-gcc 11 | 12 | CFLAGS := -masm=intel -s -w -Wall -I . 13 | 14 | all: x64 x86 15 | 16 | x64: 17 | @ $(CCX64) $(CFLAGS) -o $(EXE_x64) $(SOURCES) 18 | 19 | x86: 20 | @ $(CCX86) $(CFLAGS) -o $(EXE_x86) $(SOURCES) 21 | -------------------------------------------------------------------------------- /native.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _NATIVE_H 4 | #define _NATIVE_H 5 | 6 | #include 7 | 8 | /* Native API Return Value Macros */ 9 | #define NT_SUCCESS( Status ) ( ( ( NTSTATUS )( Status ) ) >= 0 ) 10 | #define NT_INFORMATION( Status ) ( ( ( ( ULONG ) ( Status ) ) >> 30 ) == 1 ) 11 | #define NT_WARNING( Status ) ( ( ( ( ULONG ) ( Status ) ) >> 30 ) == 2 ) 12 | #define NT_ERROR( Status ) ( ( ( ( ULONG ) ( Status ) ) >> 30 ) == 3 ) 13 | 14 | typedef VOID (*PPS_POST_PROCESS_INIT_ROUTINE) ( VOID ); 15 | 16 | typedef struct _UNICODE_STRING 17 | { 18 | USHORT Length; 19 | USHORT MaximumLength; 20 | PWSTR Buffer; 21 | } UNICODE_STRING, *PUNICODE_STRING, **PPUNICODE_STRING; 22 | 23 | typedef struct _PEB_LDR_DATA 24 | { 25 | ULONG Length; 26 | BOOLEAN Initialized; 27 | HANDLE SsHandle; 28 | LIST_ENTRY InLoadOrderModuleList; 29 | LIST_ENTRY InMemoryOrderModuleList; 30 | LIST_ENTRY InInitializationOrderModuleList; 31 | PVOID EntryInProgress; 32 | BOOLEAN ShutdownInProgress; 33 | HANDLE ShutdownThreadId; 34 | } PEB_LDR_DATA, *PPEB_LDR_DATA; 35 | 36 | typedef struct _LDR_DATA_TABLE_ENTRY 37 | { 38 | LIST_ENTRY InLoadOrderLinks; 39 | LIST_ENTRY InMemoryOrderLinks; 40 | LIST_ENTRY InInitializationOrderLinks; 41 | PVOID DllBase; 42 | PVOID EntryPoint; 43 | ULONG SizeOfImage; 44 | UNICODE_STRING FullDllName; 45 | UNICODE_STRING BaseDllName; 46 | ULONG Flags; 47 | USHORT LoadCount; 48 | USHORT TlsIndex; 49 | union 50 | { 51 | LIST_ENTRY HashLinks; 52 | struct 53 | { 54 | PVOID SectionPointer; 55 | ULONG CheckSum; 56 | }; 57 | }; 58 | union 59 | { 60 | ULONG TimeDateStamp; 61 | PVOID LoadedImports; 62 | }; 63 | PVOID EntryPointActivationContext; 64 | PVOID PatchInformation; 65 | LIST_ENTRY ForwarderLinks; 66 | LIST_ENTRY ServiceTagLinks; 67 | LIST_ENTRY StaticLinks; 68 | PVOID ContextInformation; 69 | ULONG_PTR OriginalBase; 70 | LARGE_INTEGER LoadTime; 71 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 72 | 73 | typedef struct _RTL_USER_PROCESS_PARAMETERS 74 | { 75 | BYTE Reserved1[ 16 ]; 76 | PVOID Reserved2[ 10 ]; 77 | UNICODE_STRING ImagePathName; 78 | UNICODE_STRING CommandLine; 79 | } RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS; 80 | 81 | typedef struct _PEB 82 | { 83 | BYTE Reserved1[ 2 ]; 84 | BYTE BeingDebugged; 85 | BYTE Reserved2[ 1 ]; 86 | PVOID Reserved3[ 2 ]; 87 | PPEB_LDR_DATA Ldr; 88 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 89 | BYTE Reserved4[ 104 ]; 90 | PVOID Reserved5[ 52 ]; 91 | PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 92 | BYTE Reserved6[ 128 ]; 93 | PVOID Reserved7[ 1 ]; 94 | ULONG SessionId; 95 | } PEB,*PPEB; 96 | 97 | NTSTATUS 98 | NTAPI 99 | LdrLoadDll( 100 | IN OPTIONAL PWSTR DllPath, 101 | IN OPTIONAL PULONG DllCharacteristics, 102 | IN PUNICODE_STRING DllName, 103 | OUT PVOID *DllHandle 104 | ); 105 | 106 | NTSTATUS 107 | NTAPI 108 | NtAllocateVirtualMemory ( 109 | IN HANDLE ProcessHandle, 110 | IN OUT PVOID *BaseAddress, 111 | IN ULONG_PTR ZeroBits, 112 | IN OUT PSIZE_T RegionSize, 113 | IN ULONG AllocationType, 114 | IN ULONG Protect 115 | ); 116 | 117 | NTSTATUS 118 | NTAPI 119 | NtFreeVirtualMemory ( 120 | IN HANDLE ProcessHandle, 121 | IN OUT PVOID *BaseAddress, 122 | IN OUT PSIZE_T RegionSize, 123 | IN ULONG FreeType 124 | ); 125 | 126 | NTSTATUS 127 | NTAPI 128 | NtProtectVirtualMemory ( 129 | IN HANDLE ProcessHandle, 130 | IN OUT PVOID *BaseAddress, 131 | IN OUT PSIZE_T RegionSize, 132 | IN ULONG NewProtect, 133 | OUT PULONG OldProtect 134 | ); 135 | 136 | NTSTATUS 137 | NTAPI 138 | TpAllocWork( 139 | PVOID WorkObject, 140 | PVOID WorkItem, 141 | PVOID WorkItemData, 142 | PVOID WorkItemRoutine 143 | ); 144 | 145 | NTSTATUS 146 | NTAPI 147 | TpPostWork( 148 | PTP_WORK Work 149 | ); 150 | 151 | NTSTATUS 152 | NTAPI 153 | TpReleaseWork( 154 | PTP_WORK Work 155 | ); 156 | 157 | NTSTATUS 158 | NTAPI 159 | TpWaitForWork( 160 | PTP_WORK Work, 161 | BOOL Data 162 | ); 163 | 164 | PVOID 165 | NTAPI 166 | RtlAddVectoredExceptionHandler ( 167 | LPVOID First, 168 | PVECTORED_EXCEPTION_HANDLER Handler 169 | ); 170 | 171 | ULONG 172 | NTAPI 173 | RtlRemoveVectoredExceptionHandler ( 174 | PVOID Handle 175 | ); 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /proxy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | FUNCTION NAKED VOID CALLBACK PROXY_FUNCTIOND( 4 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ) 4 | { 5 | __asm( 6 | #ifdef _WIN64 7 | "push rbx \n" 8 | "sub rsp, 0x20 \n" 9 | 10 | "mov rbx, rdx \n" 11 | "mov rax, rdx \n" 12 | 13 | "mov rcx, [ rax + 0x10 ] \n" 14 | "mov rdx, [ rax + 0x18 ] \n" 15 | "mov r8, [ rax + 0x20 ] \n" 16 | "mov r9, [ rax + 0x28 ] \n" 17 | 18 | "mov rax, [ rax ] \n" 19 | "mov r10, 0x04 \n" 20 | "push r10 \n" 21 | "jmp rax \n" 22 | 23 | "nop \n" 24 | "nop \n" 25 | "nop \n" 26 | "nop \n" 27 | 28 | "mov [ rbx + 0x08 ], rax \n" 29 | 30 | "add rsp, 0x20 \n" 31 | "pop rbx \n" 32 | 33 | "ret \n" 34 | #else 35 | "mov eax, [ esp + 0x08 ] \n" 36 | 37 | "push ebp \n" 38 | 39 | "mov ebp, esp \n" 40 | "sub esp, 0x38 \n" 41 | 42 | "mov ebx, [ eax + 0x14 ] \n" 43 | "mov [ esp + 0x0C ], ebx \n" 44 | 45 | "mov ebx, [ eax + 0x10 ] \n" 46 | "mov [ esp + 0x08 ], ebx \n" 47 | 48 | "mov ebx, [ eax + 0x0C ] \n" 49 | "mov [ esp + 0x04 ], ebx \n" 50 | 51 | "mov ebx, [ eax + 0x08 ] \n" 52 | "mov [ esp ], ebx \n" 53 | 54 | "mov eax, [ eax ] \n" 55 | "mov ebx, 0x04 \n" 56 | "push ebx \n" 57 | "jmp eax \n" 58 | 59 | "nop \n" 60 | "nop \n" 61 | "nop \n" 62 | "nop \n" 63 | 64 | "sub esp, 0x10 \n" 65 | "leave \n" 66 | 67 | "mov ebx, [ esp + 0x08 ] \n" 68 | "mov [ ebx + 0x04 ], eax \n" 69 | 70 | "ret \n" 71 | #endif 72 | ); 73 | } 74 | 75 | FUNCTION NAKED VOID CALLBACK PROXY_FUNCTIOND( 5 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ) 76 | { 77 | __asm( 78 | #ifdef _WIN64 79 | "push rbx \n" 80 | "sub rsp, 0x30 \n" 81 | 82 | "mov rbx, rdx \n" 83 | "mov rax, rdx \n" 84 | 85 | "mov rcx, [ rax + 0x30 ] \n" 86 | "mov [ rsp + 0x20 ], rcx \n" 87 | 88 | "mov rcx, [ rax + 0x10 ] \n" 89 | "mov rdx, [ rax + 0x18 ] \n" 90 | "mov r8, [ rax + 0x20 ] \n" 91 | "mov r9, [ rax + 0x28 ] \n" 92 | 93 | "mov rax, [ rax ] \n" 94 | "mov r10, 0x05 \n" 95 | "push r10 \n" 96 | "jmp rax \n" 97 | 98 | "nop \n" 99 | "nop \n" 100 | "nop \n" 101 | "nop \n" 102 | 103 | "mov [ rbx + 0x08 ], rax \n" 104 | 105 | "add rsp, 0x30 \n" 106 | "pop rbx \n" 107 | 108 | "ret \n" 109 | #else 110 | "mov eax, [ esp + 0x08 ] \n" 111 | 112 | "push ebp \n" 113 | 114 | "mov ebp, esp \n" 115 | "sub esp, 0x38 \n" 116 | 117 | "mov ebx, [ eax + 0x18 ] \n" 118 | "mov [ esp + 0x10 ], ebx \n" 119 | 120 | "mov ebx, [ eax + 0x14 ] \n" 121 | "mov [ esp + 0x0C ], ebx \n" 122 | 123 | "mov ebx, [ eax + 0x10 ] \n" 124 | "mov [ esp + 0x08 ], ebx \n" 125 | 126 | "mov ebx, [ eax + 0x0C ] \n" 127 | "mov [ esp + 0x04 ], ebx \n" 128 | 129 | "mov ebx, [ eax + 0x08 ] \n" 130 | "mov [ esp ], ebx \n" 131 | 132 | "mov eax, [ eax ] \n" 133 | "mov ebx, 0x05 \n" 134 | "push ebx \n" 135 | "jmp eax \n" 136 | 137 | "nop \n" 138 | "nop \n" 139 | "nop \n" 140 | "nop \n" 141 | 142 | "sub esp, 0x14 \n" 143 | "leave \n" 144 | 145 | "mov ebx, [ esp + 0x08 ] \n" 146 | "mov [ ebx + 0x04 ], eax \n" 147 | 148 | "ret \n" 149 | #endif 150 | ); 151 | } 152 | 153 | FUNCTION NAKED VOID CALLBACK PROXY_FUNCTIOND( 6 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ) 154 | { 155 | __asm( 156 | #ifdef _WIN64 157 | "push rbx \n" 158 | "sub rsp, 0x38 \n" 159 | 160 | "mov rbx, rdx \n" 161 | "mov rax, rdx \n" 162 | 163 | "mov rcx, [ rax + 0x30 ] \n" 164 | "mov [ rsp + 0x20 ], rcx \n" 165 | 166 | "mov rcx, [ rax + 0x38 ] \n" 167 | "mov [ rsp + 0x28 ], rcx \n" 168 | 169 | "mov rcx, [ rax + 0x10 ] \n" 170 | "mov rdx, [ rax + 0x18 ] \n" 171 | "mov r8, [ rax + 0x20 ] \n" 172 | "mov r9, [ rax + 0x28 ] \n" 173 | 174 | "mov rax, [ rax ] \n" 175 | "mov r10, 0x06 \n" 176 | "push r10 \n" 177 | "jmp rax \n" 178 | 179 | "nop \n" 180 | "nop \n" 181 | "nop \n" 182 | "nop \n" 183 | 184 | "mov [ rbx + 0x08 ], rax \n" 185 | 186 | "add rsp, 0x38 \n" 187 | "pop rbx \n" 188 | 189 | "ret \n" 190 | #else 191 | "mov eax, [ esp + 0x08 ] \n" 192 | "push ebp \n" 193 | 194 | "mov ebp, esp \n" 195 | "sub esp, 0x38 \n" 196 | 197 | "mov ebx, [ eax + 0x1C ] \n" 198 | "mov [ esp + 0x14 ], ebx \n" 199 | 200 | "mov ebx, [ eax + 0x18 ] \n" 201 | "mov [ esp + 0x10 ], ebx \n" 202 | 203 | "mov ebx, [ eax + 0x14 ] \n" 204 | "mov [ esp + 0x0C ], ebx \n" 205 | 206 | "mov ebx, [ eax + 0x10 ] \n" 207 | "mov [ esp + 0x08 ], ebx \n" 208 | 209 | "mov ebx, [ eax + 0x0C ] \n" 210 | "mov [ esp + 0x04 ], ebx \n" 211 | 212 | "mov ebx, [ eax + 0x08 ] \n" 213 | "mov [ esp ], ebx \n" 214 | 215 | "mov eax, [ eax ] \n" 216 | "mov ebx, 0x06 \n" 217 | "push ebx \n" 218 | "jmp eax \n" 219 | 220 | "nop \n" 221 | "nop \n" 222 | "nop \n" 223 | "nop \n" 224 | 225 | "sub esp, 0x18 \n" 226 | "leave \n" 227 | 228 | "mov ebx, [ esp + 0x08 ] \n" 229 | "mov [ ebx + 0x04 ], eax \n" 230 | 231 | "ret \n" 232 | #endif 233 | ); 234 | } 235 | 236 | FUNCTION VOID ToWideString( PWSTR Destination, PCHAR Source ) 237 | { 238 | while ( *Source != 0 ) 239 | { 240 | *Destination++ = *Source++; 241 | } 242 | } 243 | 244 | FUNCTION INT StringLengthA( PCHAR String ) 245 | { 246 | INT Length = 0; 247 | 248 | while ( String[ Length ] != 0 ) 249 | { 250 | Length++; 251 | } 252 | 253 | return Length; 254 | } 255 | 256 | FUNCTION PVOID PROXY_FIND_MARKER( PCHAR Ptr ) 257 | { 258 | /* Find our marker */ 259 | while ( TRUE ) 260 | { 261 | /* Check if we found our marker | nop nop nop nop */ 262 | if ( PTR_TO_INT32( Ptr, 0 ) == 0x90909090 ) 263 | { 264 | /* Return our pointer + 0x4, skip our marker */ 265 | return Ptr + 0x4; 266 | } 267 | 268 | /* Increment our pointer */ 269 | Ptr++; 270 | } 271 | 272 | /* We should never get here */ 273 | return NULL; 274 | } 275 | 276 | FUNCTION DWORD PROXY_EXCEPTION_HANDLER( PEXCEPTION_POINTERS ExceptionInfo ) 277 | { 278 | PVOID Type = ExceptionInfo->ExceptionRecord->ExceptionAddress; 279 | DWORD Code = ExceptionInfo->ExceptionRecord->ExceptionCode; 280 | PVOID Call = NULL; 281 | 282 | /* We only care about our marker and access violations */ 283 | if ( Code != EXCEPTION_ACCESS_VIOLATION || ! ( Type == 4 || Type == 5 || Type == 6 ) ) 284 | { 285 | return EXCEPTION_CONTINUE_SEARCH; 286 | } 287 | 288 | /* Handle our marker */ 289 | if ( Type == 4 ) 290 | { 291 | Call = PROXY_FIND_MARKER( QUOTE_SYMBOL( PROXY_FUNCTIOND( 4 ) ) ); 292 | } 293 | else if ( Type == 5 ) 294 | { 295 | Call = PROXY_FIND_MARKER( QUOTE_SYMBOL( PROXY_FUNCTIOND( 5 ) ) ); 296 | } 297 | else if ( Type == 6 ) 298 | { 299 | Call = PROXY_FIND_MARKER( QUOTE_SYMBOL( PROXY_FUNCTIOND( 6 ) ) ); 300 | } 301 | 302 | /* Set our call address */ 303 | #ifdef _WIN64 304 | ExceptionInfo->ContextRecord->Rip = Call; 305 | #else 306 | ExceptionInfo->ContextRecord->Eip = Call; 307 | #endif 308 | 309 | /* Continue execution */ 310 | return EXCEPTION_CONTINUE_EXECUTION; 311 | } 312 | 313 | FUNCTION PVOID InvokeProxy( PINSTANCE Instance, LPVOID Target, LPROXY_ARGS Args ) 314 | { 315 | PTP_WORK Work = NULL; 316 | 317 | /* Add exception handler */ 318 | Instance->RtlAddVectoredExceptionHandler( TRUE, QUOTE_SYMBOL( PROXY_EXCEPTION_HANDLER ) ); 319 | 320 | /* Create work */ 321 | Instance->TpAllocWork( &Work, Target, Args, NULL ); 322 | 323 | /* Post work */ 324 | Instance->TpPostWork( Work ); 325 | 326 | /* Wait work */ 327 | Instance->TpWaitForWork( Work, FALSE ); 328 | 329 | /* Release work */ 330 | Instance->TpReleaseWork( Work ); 331 | 332 | /* Remove exception handler */ 333 | Instance->RtlRemoveVectoredExceptionHandler( QUOTE_SYMBOL( PROXY_EXCEPTION_HANDLER ) ); 334 | 335 | /* Return state */ 336 | return Args->Retu; 337 | } 338 | 339 | FUNCTION PVOID BxLoadLibrary( PINSTANCE Instance, PCHAR String ) 340 | { 341 | UNICODE_STRING Name = { }; 342 | WCHAR Path[ MAX_PATH ] = { }; 343 | LPROXY_ARGS Args = NULL; 344 | INT Size = StringLengthA( String ); 345 | HMODULE Module = NULL; 346 | 347 | /* Allocate proxy args */ 348 | if ( ( Args = alloca( PROXY_ARGS_SIZE( 4 ) ) ) == NULL ) 349 | { 350 | return NULL; 351 | } 352 | 353 | /* Convert string to unicode */ 354 | ToWideString( Path, String ); 355 | 356 | /* Create unicode string */ 357 | Name.Buffer = Path; 358 | Name.Length = Size * sizeof( WCHAR ); 359 | Name.MaximumLength = Name.Length + sizeof( WCHAR ); 360 | 361 | /* Fill proxy args */ 362 | Args->Call = Instance->LdrLoadDll; 363 | Args->Args[ 0 ] = NULL; 364 | Args->Args[ 1 ] = 0; 365 | Args->Args[ 2 ] = &Name; 366 | Args->Args[ 3 ] = &Module; 367 | 368 | /* Call proxy function */ 369 | if ( NT_SUCCESS( InvokeProxy( Instance, QUOTE_SYMBOL( PROXY_FUNCTIOND( 4 ) ), Args ) ) ) 370 | { 371 | /* Return module */ 372 | return Module; 373 | } 374 | 375 | return NULL; 376 | } 377 | 378 | FUNCTION PVOID BxVirtualAlloc( PINSTANCE Instance, LPVOID Address, DWORD Size, DWORD AllocationType, DWORD Protect ) 379 | { 380 | LPVOID Memory = NULL; 381 | LPROXY_ARGS Args = NULL; 382 | SIZE_T Length = Size; 383 | 384 | /* Allocate proxy args */ 385 | if ( ( Args = alloca( PROXY_ARGS_SIZE( 6 ) ) ) == NULL ) 386 | { 387 | return NULL; 388 | } 389 | 390 | /* Fill proxy args */ 391 | Args->Call = Instance->NtAllocateVirtualMemory; 392 | Args->Args[ 0 ] = -1; 393 | Args->Args[ 1 ] = &Memory; 394 | Args->Args[ 2 ] = 0; 395 | Args->Args[ 3 ] = &Length; 396 | Args->Args[ 4 ] = AllocationType; 397 | Args->Args[ 5 ] = Protect; 398 | 399 | /* Call proxy function */ 400 | if ( NT_SUCCESS( InvokeProxy( Instance, QUOTE_SYMBOL( PROXY_FUNCTIOND( 6 ) ), Args ) ) ) 401 | { 402 | /* Return memory */ 403 | return Memory; 404 | } 405 | 406 | return NULL; 407 | } 408 | 409 | FUNCTION BOOL BxVirtualFree( PINSTANCE Instance, PVOID Address, DWORD Size, DWORD FreeType ) 410 | { 411 | LPVOID Memory = Address; 412 | LPROXY_ARGS Args = NULL; 413 | SIZE_T Length = Size; 414 | 415 | /* Allocate proxy args */ 416 | if ( ( Args = alloca( PROXY_ARGS_SIZE( 4 ) ) ) == NULL ) 417 | { 418 | return; 419 | } 420 | 421 | /* Fill proxy args */ 422 | Args->Call = Instance->NtFreeVirtualMemory; 423 | Args->Args[ 0 ] = -1; 424 | Args->Args[ 1 ] = &Memory; 425 | Args->Args[ 2 ] = &Length; 426 | Args->Args[ 3 ] = FreeType; 427 | 428 | /* Call proxy function */ 429 | return NT_SUCCESS( InvokeProxy( Instance, QUOTE_SYMBOL( PROXY_FUNCTIOND( 4 ) ), Args ) ); 430 | } 431 | 432 | FUNCTION BOOL BxVirtualProtect( PINSTANCE Instance, PVOID Address, DWORD Size, DWORD NewProtect, PDWORD OldProtect ) 433 | { 434 | LPVOID Memory = Address; 435 | LPROXY_ARGS Args = NULL; 436 | SIZE_T Length = Size; 437 | 438 | /* Allocate proxy args */ 439 | if ( ( Args = alloca( PROXY_ARGS_SIZE( 5 ) ) ) == NULL ) 440 | { 441 | return; 442 | } 443 | 444 | /* Fill proxy args */ 445 | Args->Call = Instance->NtProtectVirtualMemory; 446 | Args->Args[ 0 ] = -1; 447 | Args->Args[ 1 ] = &Memory; 448 | Args->Args[ 2 ] = &Length; 449 | Args->Args[ 3 ] = NewProtect; 450 | Args->Args[ 4 ] = OldProtect; 451 | 452 | /* Call proxy function */ 453 | return NT_SUCCESS( InvokeProxy( Instance, QUOTE_SYMBOL( PROXY_FUNCTIOND( 5 ) ), Args ) ); 454 | } 455 | -------------------------------------------------------------------------------- /proxy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _PROXY_H 4 | #define _PROXY_H 5 | 6 | #include 7 | #include 8 | 9 | #ifndef FUNCTION 10 | #define FUNCTION 11 | #endif 12 | 13 | #ifdef _WIN64 14 | #define QUOTE_SYMBOL( x ) x 15 | #else 16 | #define QUOTE_SYMBOL( x ) x 17 | #endif 18 | 19 | #define RVA_2_VA(T, B, R) ( T )( ( PVOID ) B + R ) 20 | #define RVA_2_VA_VALUE(T, B, R) *RVA_2_VA( T, B, R ) 21 | #define C_PTR( x ) ( ( PVOID ) x ) 22 | #define U_PTR( x ) ( ( UINT_PTR ) x ) 23 | 24 | #define PTR_TO_INT32( x, o ) RVA_2_VA_VALUE( PDWORD32, x, o ) 25 | #define PTR_TO_INT64( x, o ) RVA_2_VA_VALUE( PDWORD64, x, o ) 26 | #define PTR_TO_INT16( x, o ) RVA_2_VA_VALUE( PWORD, x, o ) 27 | #define PTR_TO_INT08( x, o ) RVA_2_VA_VALUE( PBYTE, x, o ) 28 | 29 | #define NAKED __declspec( naked ) 30 | #define PROXY_ARGS_SIZE( N ) ( sizeof( PROXY_ARGS ) + ( N ) * sizeof( PVOID ) ) 31 | #define PROXY_FUNCTIOND( N ) PROXY_FUNCTION_NAME_##N 32 | 33 | #define DEFINE_FUNC( x ) __typeof__( x ) * x 34 | 35 | typedef struct 36 | { 37 | LPVOID Call; 38 | LPVOID Retu; 39 | LPVOID Args[ 0 ]; 40 | } PROXY_ARGS, *LPROXY_ARGS; 41 | 42 | typedef struct { 43 | DEFINE_FUNC( LdrLoadDll ); 44 | DEFINE_FUNC( NtAllocateVirtualMemory ); 45 | DEFINE_FUNC( NtProtectVirtualMemory ); 46 | DEFINE_FUNC( NtFreeVirtualMemory ); 47 | 48 | DEFINE_FUNC( TpAllocWork ); 49 | DEFINE_FUNC( TpPostWork ); 50 | DEFINE_FUNC( TpReleaseWork ); 51 | DEFINE_FUNC( TpWaitForWork ); 52 | 53 | DEFINE_FUNC( RtlAddVectoredExceptionHandler ); 54 | DEFINE_FUNC( RtlRemoveVectoredExceptionHandler ); 55 | } INSTANCE, *PINSTANCE; 56 | 57 | PVOID InvokeProxy( PINSTANCE Instance, LPVOID Target, LPROXY_ARGS Args ); 58 | PVOID BxLoadLibrary( PINSTANCE Instance, PCHAR String ); 59 | PVOID BxVirtualAlloc( PINSTANCE Instance, LPVOID Address, DWORD Size, DWORD AllocationType, DWORD Protect ); 60 | BOOL BxVirtualFree( PINSTANCE Instance, PVOID Address, DWORD Size, DWORD FreeType ); 61 | BOOL BxVirtualProtect( PINSTANCE Instance, PVOID Address, DWORD Size, DWORD NewProtect, PDWORD OldProtect ); 62 | 63 | VOID CALLBACK PROXY_FUNCTIOND( 4 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ); 64 | VOID CALLBACK PROXY_FUNCTIOND( 5 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ); 65 | VOID CALLBACK PROXY_FUNCTIOND( 6 )( PTP_CALLBACK_INSTANCE Instance, LPROXY_ARGS Args, PTP_WORK Work ); 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main( void ) 5 | { 6 | INSTANCE Instance = { 0 }; 7 | HMODULE Ntdll = NULL; 8 | HMODULE User32 = NULL; 9 | PROXY_ARGS Args = { 0 }; 10 | 11 | /* Load Ntdll */ 12 | Ntdll = GetModuleHandleA( "ntdll" ); 13 | 14 | /* Get Ntdll Functions */ 15 | Instance.LdrLoadDll = GetProcAddress( Ntdll, "LdrLoadDll" ); 16 | Instance.NtAllocateVirtualMemory = GetProcAddress( Ntdll, "NtAllocateVirtualMemory" ); 17 | Instance.NtProtectVirtualMemory = GetProcAddress( Ntdll, "NtProtectVirtualMemory" ); 18 | Instance.NtFreeVirtualMemory = GetProcAddress( Ntdll, "NtFreeVirtualMemory" ); 19 | 20 | Instance.RtlAddVectoredExceptionHandler = GetProcAddress( Ntdll, "RtlAddVectoredExceptionHandler" ); 21 | Instance.RtlRemoveVectoredExceptionHandler = GetProcAddress( Ntdll, "RtlRemoveVectoredExceptionHandler" ); 22 | 23 | Instance.TpAllocWork = GetProcAddress( Ntdll, "TpAllocWork" ); 24 | Instance.TpPostWork = GetProcAddress( Ntdll, "TpPostWork" ); 25 | Instance.TpReleaseWork = GetProcAddress( Ntdll, "TpReleaseWork" ); 26 | Instance.TpWaitForWork = GetProcAddress( Ntdll, "TpWaitForWork" ); 27 | 28 | /* 29 | Demo 30 | */ 31 | if ( ( User32 = BxLoadLibrary( &Instance, "user32" ) ) == NULL ) 32 | { 33 | printf( "[-] Failed to load user32.dll\n" ); return -1; 34 | } 35 | 36 | /* Fill proxy args */ 37 | Args.Call = GetProcAddress( User32, "MessageBoxA" ); 38 | Args.Args[ 0 ] = NULL; 39 | Args.Args[ 1 ] = "Hello World"; 40 | Args.Args[ 2 ] = "Title"; 41 | Args.Args[ 3 ] = MB_OK; 42 | 43 | /* Call proxy function */ 44 | InvokeProxy( &Instance, QUOTE_SYMBOL( PROXY_FUNCTIOND( 4 ) ), &Args ); 45 | 46 | return 0; 47 | } 48 | --------------------------------------------------------------------------------