Skip to content

Instantly share code, notes, and snippets.

@realoriginal
Last active May 6, 2023 13:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save realoriginal/6fcbc17ef29e9e7995a4ec9be6c2ddd8 to your computer and use it in GitHub Desktop.
Save realoriginal/6fcbc17ef29e9e7995a4ec9be6c2ddd8 to your computer and use it in GitHub Desktop.
D_SEC( A ) NTSTATUS NTAPI Entry( _In_ PVOID Parameter )
{
PARSED_BUF Psr;
UINT32 Wrt = 0;
PARG Arg = NULL;
LPWSTR Nps = NULL;
HANDLE Pip = NULL;
/* Zero out stack structures */
RtlZeroMemory( &Psr, sizeof( Psr ) );
/* Is the argument valid? */
if ( Parameter != NULL ) {
/* Extract the named pipe argument */
Arg = C_PTR( Parameter );
ParserInit( Arg->Buffer, Arg->Length, &Psr );
Nps = ParserGetBuffer( &Psr, NULL );
/* Create the post-ex communication pipe for rogue */
if ( NT_SUCCESS( PipeInit( Nps, 60000, 60000 * 30, &Pip ) ) ) {
PipePrintf( Pip, 0, C_PTR( G_PTR( "Would you like to play a game?" ) ) );
/* Close the pipe and flush the buffers */
PipeFree( Pip, TRUE );
}
};
/* Zero out stack structures */
RtlZeroMemory( &Psr, sizeof( Psr ) );
}
/*!
*
* BOOTINFO
*
* GuidePoint Security LLC
*
* Threat and Attack Simulation Team
*
!*/
#include "Common.h"
typedef struct
{
D_API( NtWaitForSingleObject );
D_API( NtCreateNamedPipeFile );
D_API( RtlInitUnicodeString );
D_API( NtFlushBuffersFile );
D_API( NtFsControlFile );
D_API( NtCreateEvent );
D_API( NtWriteFile );
D_API( NtReadFile );
D_API( _vsnprintf );
D_API( NtClose );
} API ;
/* API Hashes */
#define H_API_NTWAITFORSINGLEOBJECT 0xe8ac0c3c /* NtWaitForSingleObject */
#define H_API_NTCREATENAMEDPIPEFILE 0x1da0062e /* NtCreateNamedPipeFile */
#define H_API_RTLINITUNICODESTRING 0xef52b589 /* RtlInitUnicodeString */
#define H_API_NTFLUSHBUFFERSFILE 0xc7654d16 /* NtFlushBuffersFile */
#define H_API_NTFSCONTROLFILE 0xecdfd601 /* NtFsControlFile */
#define H_API_NTCREATEEVENT 0x28d3233d /* NtCreateEvent */
#define H_API_NTWRITEFILE 0xe0d61db2 /* NtWriteFile */
#define H_API_NTREADFILE 0xb2d93203 /* NtReadFile */
#define H_API__VSNPRINTF 0xa59022ce /* _vsnprintf */
#define H_API_NTCLOSE 0x40d6e69d /* NtClose */
/* LIB Hashes */
#define H_LIB_NTDLL 0x1edab0ed /* ntdll.dll */
/* IOCTL */
#define FSCTL_PIPE_DISCONNECT CTL_CODE( FILE_DEVICE_NAMED_PIPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS )
#define FSCTL_PIPE_LISTEN CTL_CODE( FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS )
/*!
*
* Purpose:
*
* Creates a pipe and waits on a connection. IF no
* connection is recieved within the timeout period,
* it will fail and shutdown prematurely.
*
!*/
D_SEC( B ) NTSTATUS PipeInit( _In_ LPWSTR NamedPipe, _In_ UINT32 PipeTimeout, _In_ UINT32 ConnectTimeout, _Out_ PHANDLE PipeHandle )
{
API Api;
LARGE_INTEGER Tim;
UNICODE_STRING Uni;
IO_STATUS_BLOCK Isb;
OBJECT_ATTRIBUTES Att;
NTSTATUS Nst = STATUS_UNSUCCESSFUL;
HANDLE Pip = NULL;
HANDLE Evt = NULL;
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Uni, sizeof( Uni ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
RtlZeroMemory( &Att, sizeof( Att ) );
Api.NtWaitForSingleObject = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTWAITFORSINGLEOBJECT ) );
Api.NtCreateNamedPipeFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCREATENAMEDPIPEFILE ) );
Api.RtlInitUnicodeString = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_RTLINITUNICODESTRING ) );
Api.NtFsControlFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTFSCONTROLFILE ) );
Api.NtCreateEvent = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCREATEEVENT ) );
Api.NtClose = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCLOSE ) );
/* Initialize attributes & string */
Api.RtlInitUnicodeString( &Uni, NamedPipe );
InitializeObjectAttributes( &Att, &Uni, OBJ_CASE_INSENSITIVE, NULL, NULL );
/* Set the pipe operation time out */
Tim.QuadPart = -10000LL * PipeTimeout;
/* Create the named pipe */
Nst = Api.NtCreateNamedPipeFile( &Pip,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&Att,
&Isb,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0, /* FILE_SYCNHRONOUS_IO_NONALERT */
0,
0,
0,
1,
1024 * 1024,
1024 * 1024,
&Tim );
/* Success! Try and block on it */
if ( NT_SUCCESS( Nst ) ) {
/* Create the blocking event */
Nst = Api.NtCreateEvent( &Evt,
EVENT_ALL_ACCESS,
NULL,
NotificationEvent,
FALSE );
if ( NT_SUCCESS( Nst ) ) {
/* Request we start the bloc operation */
Nst = Api.NtFsControlFile( Pip,
Evt,
NULL,
NULL,
&Isb,
FSCTL_PIPE_LISTEN,
NULL,
0,
NULL,
0 );
/* PEnding? */
if ( Nst == STATUS_PENDING ) {
/* Blcok until it connects */
Tim.QuadPart = -10000LL * ConnectTimeout;
/* Blocks until a timeout is reached, is signaled OR waits indefintely if timeout == 0 */
Nst = Api.NtWaitForSingleObject( Evt, FALSE, Tim.QuadPart != 0 ? &Tim : NULL );
/* No errors?! */
if ( NT_SUCCESS( Nst ) ) {
/* SEt the status */
Nst = Isb.Status;
}
}
/* Close the pipe */
Api.NtClose( Evt );
}
}
/* Did we get STATUS_PIPE_CONNECTED? Not really an error */
if ( Nst == STATUS_PIPE_CONNECTED ) {
/* Readjust to a connected status */
Nst = STATUS_SUCCESS;
}
/* We got errors?! */
if ( NT_SUCCESS( Nst ) ) {
/* Set the output handle */
*PipeHandle = C_PTR( Pip );
} else {
/* Failed. Close the pipe */
if ( Pip != NULL ) {
/* Closed the pipe */
Api.NtClose( Pip );
}
}
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Uni, sizeof( Uni ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
RtlZeroMemory( &Att, sizeof( Att ) );
/* Return the status */
return Nst;
}
/*!
*
* Purpose:
*
* Closes the named pipe and flushes the output buffer
* if requested.
*
!*/
D_SEC( B ) NTSTATUS PipeFree( _In_ HANDLE PipeHandle, _In_ BOOLEAN FlushBuffer )
{
API Api;
IO_STATUS_BLOCK Isb;
NTSTATUS Nst = STATUS_UNSUCCESSFUL;
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
Api.NtWaitForSingleObject = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTWAITFORSINGLEOBJECT ) );
Api.NtFlushBuffersFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTFLUSHBUFFERSFILE ) );
Api.NtFsControlFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTFSCONTROLFILE ) );
Api.NtClose = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCLOSE ) );
if ( FlushBuffer ) {
/* Flush the file buffers. Who care about the result */
Api.NtFlushBuffersFile( PipeHandle, &Isb );
}
/* Force a disconnect */
Nst = Api.NtFsControlFile( PipeHandle,
NULL,
NULL,
NULL,
&Isb,
FSCTL_PIPE_DISCONNECT,
NULL,
0,
NULL,
0 );
/* Is this operation pending? */
if ( Nst == STATUS_PENDING ) {
/* Wait until the pending operation completes */
Nst = Api.NtWaitForSingleObject( PipeHandle, FALSE, NULL );
/* Did we succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Set the status */
Nst = Isb.Status;
}
}
/* Did we succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Close the pipe */
Nst = Api.NtClose( PipeHandle );
};
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
/* Return the status */
return Nst;
}
/*!
*
* Purpose:
*
* Reads data from the named pipe. If ReadTimeout is
* set to 0, it is presumed that the function will
* read until an error occurs. If the function has
* succeeded, the LengthRead will be set to the
* output.
*
!*/
D_SEC( B ) NTSTATUS PipeRd( _In_ HANDLE PipeHandle, _In_ PVOID Buffer, _In_ UINT32 Length, _In_ UINT32 ReadTimeout, _Out_ PUINT32 LengthRead )
{
API Api;
LARGE_INTEGER Tim;
IO_STATUS_BLOCK Isb;
NTSTATUS Nst = STATUS_UNSUCCESSFUL;
HANDLE Evt = NULL;
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
Api.NtWaitForSingleObject = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTWAITFORSINGLEOBJECT ) );
Api.NtCreateEvent = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCREATEEVENT ) );
Api.NtReadFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTREADFILE ) );
Api.NtClose = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCLOSE ) );
Nst = Api.NtCreateEvent( &Evt,
EVENT_ALL_ACCESS,
NULL,
NotificationEvent,
FALSE );
if ( NT_SUCCESS( Nst ) ) {
/* Start the read length */
Nst = Api.NtReadFile( PipeHandle,
Evt,
NULL,
NULL,
&Isb,
Buffer,
Length,
NULL,
NULL );
/* Not complete? */
if ( Nst == STATUS_PENDING ) {
/* Wait until timeout or infinite */
Tim.QuadPart = -10000LL * ReadTimeout;
Nst = Api.NtWaitForSingleObject( Evt, FALSE, Tim.QuadPart != 0 ? &Tim : NULL );
/* Did we succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Set the status */
Nst = Isb.Status;
}
}
/* Reached the end of the file */
if ( Nst == STATUS_END_OF_FILE ) {
/* No buffer read */
*LengthRead = 0;
/* Return the length */
return STATUS_SUCCESS;
}
/* Did it succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Set the length read */
*LengthRead = Isb.Information;
};
/* Close the reference */
Api.NtClose( Evt );
};
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
/* Return the status */
return Nst;
}
/*!
*
* Purpose:
*
* Writes to a named pipe. If a timeout is set to 0,
* the function will block indefinetly.
*
!*/
D_SEC( B ) NTSTATUS PipeWr( _In_ HANDLE PipeHandle, _In_ PVOID Buffer, _In_ UINT32 Length, _In_ UINT32 WriteTimeout, _Out_ PUINT32 LengthWritten )
{
API Api;
LARGE_INTEGER Tim;
IO_STATUS_BLOCK Isb;
NTSTATUS Nst = STATUS_UNSUCCESSFUL;
HANDLE Evt = NULL;
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
Api.NtWaitForSingleObject = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTWAITFORSINGLEOBJECT ) );
Api.NtCreateEvent = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCREATEEVENT ) );
Api.NtWriteFile = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTWRITEFILE ) );
Api.NtClose = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API_NTCLOSE ) );
/* Create the event for waiting on */
Nst = Api.NtCreateEvent( &Evt,
EVENT_ALL_ACCESS,
NULL,
NotificationEvent,
FALSE );
/* Did it succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Write to the file */
Nst = Api.NtWriteFile( PipeHandle,
Evt,
NULL,
NULL,
&Isb,
Buffer,
Length,
NULL,
NULL );
/* Is the oepration pending */
if ( Nst == STATUS_PENDING ) {
/* Set the timeout */
Tim.QuadPart = -10000LL * WriteTimeout;
/* Block unti lits ready */
Nst = Api.NtWaitForSingleObject( Evt, FALSE, Tim.QuadPart != 0 ? &Tim : NULL );
/* Did we succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Set the success status */
Nst = Isb.Status;
}
};
/* Did we succeed? */
if ( NT_SUCCESS( Nst ) ) {
/* Set the last read */
*LengthWritten = Isb.Information;
}
/* Close the reference */
Api.NtClose( Evt );
};
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Tim, sizeof( Tim ) );
RtlZeroMemory( &Isb, sizeof( Isb ) );
/* Return status */
return Nst;
}
/*!
*
* Purpose:
*
* Writes a formatted string onto the named pipe.
*
!*/
D_SEC( B ) NTSTATUS PipePrintf( _In_ HANDLE PipeHandle, _In_ UINT32 WriteTimeout, _In_ PCHAR Format, ... )
{
API Api;
va_list Lst;
UINT32 Len = 0;
UINT32 Wrt = 0;
NTSTATUS Nst = STATUS_UNSUCCESSFUL;
PUINT8 Buf = NULL;
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Lst, sizeof( Lst ) );
Api._vsnprintf = PeGetFuncEat( PebGetModule( E_HSH( H_LIB_NTDLL ) ), E_HSH( H_API__VSNPRINTF ) );
/* Get the length of the buffer */
va_start( Lst, Format );
Len = Api._vsnprintf( NULL, 0, Format, Lst );
va_end( Lst );
/* Allocate an output buffer */
if ( ( Buf = MemoryAlloc( Len + 1 ) ) ) {
/* Format the output buffer */
va_start( Lst, Format );
Len = Api._vsnprintf( Buf, Len, Format, Lst );
va_end( Lst );
/* End the line */
Buf[ Len ] = '\n';
/* Write to the buffer */
Nst = PipeWr( PipeHandle, Buf, Len + 1, WriteTimeout, &Wrt );
/* Free the buffer */
MemoryFree( Buf );
};
/* Zero out stack structures */
RtlZeroMemory( &Api, sizeof( Api ) );
RtlZeroMemory( &Lst, sizeof( Lst ) );
/* Return the status */
return Nst;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment