参考:
1,Offensive Windows IPC Internals 3: ALPC · csandker.io
***
下面出现的代码都来自参考链接中,非本人编写
***
常见的进程间通信有管道,共享内存等。下面代码演示一种交少见的机制,alpc (advanced local procedure call) 。
文件ALPC.h
#pragma once
#include <Windows.h>
#include <winternl.h>
//
// CONSTANTS
//
// PORT ATTRIBUTE FLAGS
#define ALPC_PORTFLG_NONE 0x0
#define ALPC_PORTFLG_LPCPORT 0x1000 // Only usable in kernel
#define ALPC_PORTFLG_ALLOWIMPERSONATION 0x10000 // Can be set by client to allow server to impersonation this client
#define ALPC_PORTFLG_ALLOW_LPC_REQUESTS 0x20000
#define ALPC_PORTFLG_WAITABLE_PORT 0x40000 // Allow port to be used with synchronization mechanisms like Semaphores
#define ALPC_PORTFLG_SYSTEM_PROCESS 0x100000 // Only usable in kernel
#define ALPC_PORTFLG_ALLOW_DUP_OBJECT 0x80000
#define ALPC_PORTFLG_LRPC_WAKE_POLICY1 0x200000
#define ALPC_PORTFLG_LRPC_WAKE_POLICY2 0x400000
#define ALPC_PORTFLG_LRPC_WAKE_POLICY3 0x800000
#define ALPC_PORTFLG_DIRECT_MESSAGE 0x1000000 // There are 5 queues, Main queue, Direct message queue, Large message queue, Pending queue, Canceled queue... guess this attribute specifies to use the direct message queue instead of main queue
// Uncertain
//#define ALPC_PORTFLG_ACCEPT_INDIRECT_HANDLES (from https://github.com/microsoft/terminal/blob/059f2031583fd22fb7b5f498e4a30196cf3150d4/src/interactivity/onecore/ConIoSrvComm.cpp)
//#define ALPC_PORTFLG_ALLOW_MULTI_HANDLE_ATTRIBUTE 0x2000000
// ERROS
/// just the ones i need to integrate into my code flow
const NTSTATUS STATUS_BUFFER_TOO_SMALL = 0xC0000023;
const NTSTATUS STATUS_PORT_CONNECTION_REFUSED = 0xC0000041;
const NTSTATUS STATUS_ACCESS_DENIED = 0xC0000022;
const NTSTATUS STATUS_SERVER_SID_MISMATCH = 0xC00002A0;
// ALPC Message Attributes
#define ALPC_MESSAGE_SECURITY_ATTRIBUTE 0x80000000
#define ALPC_MESSAGE_VIEW_ATTRIBUTE 0x40000000
#define ALPC_MESSAGE_CONTEXT_ATTRIBUTE 0x20000000
#define ALPC_MESSAGE_HANDLE_ATTRIBUTE 0x10000000
#define ALPC_MESSAGE_TOKEN_ATTRIBUTE 0x8000000
#define ALPC_MESSAGE_DIRECT_ATTRIBUTE 0x4000000
#define ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE 0x2000000
#define ALPC_MESSAGE_ATTRIBUTE_ALL ALPC_MESSAGE_SECURITY_ATTRIBUTE | ALPC_MESSAGE_VIEW_ATTRIBUTE | ALPC_MESSAGE_CONTEXT_ATTRIBUTE | ALPC_MESSAGE_HANDLE_ATTRIBUTE | ALPC_MESSAGE_TOKEN_ATTRIBUTE | ALPC_MESSAGE_DIRECT_ATTRIBUTE | ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE
// ALPC Message Flags
#define ALPC_MSGFLG_NONE 0x0
#define ALPC_MSGFLG_REPLY_MESSAGE 0x1
#define ALPC_MSGFLG_LPC_MODE 0x2
#define ALPC_MSGFLG_RELEASE_MESSAGE 0x10000
#define ALPC_MSGFLG_SYNC_REQUEST 0x20000 // synchronous message, needs a receive buffer or else error 0xC0000705 is returned
#define ALPC_MSGFLG_WAIT_USER_MODE 0x100000
#define ALPC_MSGFLG_WAIT_ALERTABLE 0x200000
#define ALPC_MSGFLG_WOW64_CALL 0x80000000
// ALPC Connection FLAGS
/// From: https://recon.cx/2008/a/thomas_garnier/LPC-ALPC-paper.pdf
#define ALPC_SYNC_CONNECTION 0x20000 // Synchronous connection request
#define ALPC_USER_WAIT_MODE 0x100000 // Wait in user mode
#define ALPC_WAIT_IS_ALERTABLE 0x200000 // Wait in alertable mode
// 0xc0020000 connection flag causing SF flag to be "1" in nt!AlpcpExposeViewAttribute and therefore calling nt!AlpcpExposeViewAttribute
//
// STRUCTS
//
// Based on https://github.com/googleprojectzero/sandbox-attacksurface-analysis-tools/blob/main/NtApiDotNet/NtAlpcNative.cs#L82-L97
enum ALPC_MESSAGE_TYPE
{
None = 0,
Request = 1,
Reply = 2,
Datagram = 3,
LostReply = 4,
PortClosed = 5,
ClientDied = 6,
Exception = 7,
DebugEvent = 8,
ErrorEvent = 9,
ConnectionRequest = 10,
ConnectionReply = 11,
UNKNOWN12 = 12, // Seems to be something like an empty reply, PID and TID pointing to own thread
PortDisconnected = 13 // Used by the kernel when disconnecting an exception port.
};
// End Based ON
typedef struct _ALPC_PORT_ATTRIBUTES
{
unsigned long Flags;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
unsigned __int64 MaxMessageLength;
unsigned __int64 MemoryBandwidth;
unsigned __int64 MaxPoolUsage;
unsigned __int64 MaxSectionSize;
unsigned __int64 MaxViewSize;
unsigned __int64 MaxTotalSectionSize;
ULONG DupObjectTypes;
#ifdef _WIN64
ULONG Reserved;
#endif
} ALPC_PORT_ATTRIBUTES, * PALPC_PORT_ATTRIBUTES;
typedef struct _ALPC_MESSAGE_ATTRIBUTES
{
ULONG AllocatedAttributes;
ULONG ValidAttributes;
} ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES;
typedef struct _PORT_MESSAGE
{
union
{
struct
{
USHORT DataLength;
USHORT TotalLength;
} s1;
ULONG Length;
} u1;
union
{
struct
{
USHORT Type;
USHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union
{
CLIENT_ID ClientId;
double DoNotUseThisField;
};
ULONG MessageId;
union
{
SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages
ULONG CallbackId; // only valid for LPC_REQUEST messages
};
} PORT_MESSAGE, * PPORT_MESSAGE;
// FROM https://docs.rs/ntapi/0.3.6/ntapi/ntlpcapi/struct.ALPC_HANDLE_ATTR.html
typedef struct _ALPC_DATA_VIEW_ATTR {
ULONG Flags;
HANDLE SectionHandle;
PVOID ViewBase;
SIZE_T ViewSize;
} ALPC_DATA_VIEW_ATTR, * PALPC_DATA_VIEW_ATTR;
typedef struct _ALPC_TOKEN_ATTR
{
ULONGLONG TokenId;
ULONGLONG AuthenticationId;
ULONGLONG ModifiedId;
} ALPC_TOKEN_ATTR, * PALPC_TOKEN_ATTR;
typedef struct _AlpcPortContext {
HANDLE Handle;
} AlpcPortContext, * PAlpcPortContext;
typedef struct _ALPC_CONTEXT_ATTR {
PVOID PortContext;
PVOID MessageContext;
ULONG Sequence;
ULONG MessageId;
ULONG CallbackId;
} ALPC_CONTEXT_ATTR, * PALPC_CONTEXT_ATTR;
typedef struct _ALPC_SECURITY_ATTR {
ULONG Flags;
PSECURITY_QUALITY_OF_SERVICE pQOS;
HANDLE ContextHandle;
} ALPC_SECURITY_ATTR, * PALPC_SECURITY_ATTR;
typedef struct _SECURITY_CLIENT_CONTEXT
{
SECURITY_QUALITY_OF_SERVICE SecurityQos; //_KALPC_SECURITY_DATA
LPVOID ClientToken;
UCHAR DirectlyAccessClientToken;
UCHAR DirectAccessEffectiveOnly;
UCHAR ServerIsRemote;
_TOKEN_CONTROL ClientTokenControl;
} SECURITY_CLIENT_CONTEXT, * PSECURITY_CLIENT_CONTEXT;
// From https://github.com/hakril/PythonForWindows/blob/3149961634cda0029a288e6ffa7779e4492adb13/ctypes_generation/definitions/structures/alpc.txt
typedef struct _ALPC_DIRECT_ATTR
{
HANDLE Event;
} ALPC_DIRECT_ATTR, * PALPC_DIRECT_ATTR;
typedef struct _ALPC_WORK_ON_BEHALF_ATTR
{
ULONGLONG Ticket;
} ALPC_WORK_ON_BEHALF_ATTR, * PALPC_WORK_ON_BEHALF_ATTR;
typedef struct _ALPC_HANDLE_ATTR
{
ULONG Flags;
HANDLE Handle;
ULONG ObjectType;
ACCESS_MASK DesiredAccess;
} ALPC_HANDLE_ATTR, * PALPC_HANDLE_ATTR;
typedef struct _ALPC_HANDLE_ENTRY {
LPVOID Object;
};
typedef struct _PORT_VIEW
{
ULONG Length;
HANDLE SectionHandle;
ULONG SectionOffset;
SIZE_T ViewSize;
PVOID ViewBase;
PVOID ViewRemoteBase;
} PORT_VIEW, * PPORT_VIEW;
typedef enum _ALPC_PORT_INFORMATION_CLASS
{
AlpcBasicInformation, // q: out ALPC_BASIC_INFORMATION
AlpcPortInformation, // s: in ALPC_PORT_ATTRIBUTES
AlpcAssociateCompletionPortInformation, // s: in ALPC_PORT_ASSOCIATE_COMPLETION_PORT
AlpcConnectedSIDInformation, // q: in SID
AlpcServerInformation, // q: inout ALPC_SERVER_INFORMATION
AlpcMessageZoneInformation, // s: in ALPC_PORT_MESSAGE_ZONE_INFORMATION
AlpcRegisterCompletionListInformation, // s: in ALPC_PORT_COMPLETION_LIST_INFORMATION
AlpcUnregisterCompletionListInformation, // s: VOID
AlpcAdjustCompletionListConcurrencyCountInformation, // s: in ULONG
AlpcRegisterCallbackInformation, // kernel-mode only
AlpcCompletionListRundownInformation, // s: VOID
AlpcWaitForPortReferences
} ALPC_PORT_INFORMATION_CLASS;
typedef struct _ALPC_SERVER_INFORMATION
{
union
{
struct
{
HANDLE ThreadHandle;
} In;
struct
{
BOOLEAN ThreadBlocked;
HANDLE ConnectedProcessId;
UNICODE_STRING ConnectionPortName;
} Out;
};
} ALPC_SERVER_INFORMATION, * PALPC_SERVER_INFORMATION;
typedef struct _ALPC_BASIC_INFORMATION
{
ULONG Flags;
ULONG SequenceNo;
PVOID PortContext;
} ALPC_BASIC_INFORMATION, * PALPC_BASIC_INFORMATION;
typedef enum _ALPC_MESSAGE_INFORMATION_CLASS {
AlpcMessageSidInformation, // out PSID
AlpcMessageTokenModifiedIdInformation, // q: out LUID
AlpcMessageDirectStatusInformation,
AlpcMessageHandleInformation, // ALPC_MESSAGE_HANDLE_INFORMATION
MaxAlpcMessageInfoClass
} ALPC_MESSAGE_INFORMATION_CLASS, * PALPC_MESSAGE_INFORMATION_CLASS;
typedef struct _ALPC_MESSAGE_HANDLE_INFORMATION {
ULONG Index;
ULONG Flags;
ULONG Handle;
ULONG ObjectType;
ACCESS_MASK GrantedAccess;
} ALPC_MESSAGE_HANDLE_INFORMATION, * PALPC_MESSAGE_HANDLE_INFORMATION;
//
// FUNCTIONS
//
EXTERN_C
LPVOID NTAPI AlpcGetMessageAttribute(
_In_ PALPC_MESSAGE_ATTRIBUTES Buffer,
_In_ ULONG AttributeFlag
);
EXTERN_C
NTSTATUS NTAPI AlpcInitializeMessageAttribute(
_In_ ULONG AttributeFlags,
_Out_opt_ PALPC_MESSAGE_ATTRIBUTES Buffer,
_In_ SIZE_T BufferSize,
_Out_ PSIZE_T RequiredBufferSize
);
EXTERN_C
NTSTATUS NTAPI NtAlpcCreatePort(
_Out_ PHANDLE PortHandle,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes
);
EXTERN_C
NTSTATUS NTAPI NtAlpcConnectPort(
_Out_ PHANDLE PortHandle,
_In_ PUNICODE_STRING PortName,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
_In_ DWORD ConnectionFlags,
_In_opt_ PSID RequiredServerSid,
_In_opt_ PPORT_MESSAGE ConnectionMessage,
_Inout_opt_ PSIZE_T ConnectMessageSize,
_In_opt_ PALPC_MESSAGE_ATTRIBUTES OutMessageAttributes,
_In_opt_ PALPC_MESSAGE_ATTRIBUTES InMessageAttributes,
_In_opt_ PLARGE_INTEGER Timeout
);
EXTERN_C
NTSTATUS NTAPI NtAlpcSendWaitReceivePort(
_In_ HANDLE PortHandle,
_In_ DWORD Flags,
_In_opt_ PPORT_MESSAGE SendMessage_,
_In_opt_ PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes,
_Inout_opt_ PPORT_MESSAGE ReceiveMessage,
_Inout_opt_ PSIZE_T BufferLength,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,
_In_opt_ PLARGE_INTEGER Timeout
);
EXTERN_C
NTSTATUS NTAPI NtAlpcAcceptConnectPort(
_Out_ PHANDLE PortHandle,
_In_ HANDLE ConnectionPortHandle,
_In_ DWORD Flags,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes,
_In_opt_ PVOID PortContext,
_In_ PPORT_MESSAGE ConnectionRequest,
_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES ConnectionMessageAttributes,
_In_ BOOLEAN AcceptConnection
);
EXTERN_C
SIZE_T NTAPI AlpcGetHeaderSize(
ULONG TypeFlag
);
EXTERN_C
NTSTATUS NTAPI NtAlpcImpersonateClientOfPort(
_In_ HANDLE PortHandle,
_In_ PPORT_MESSAGE PortMessage,
_Reserved_ PVOID Reserved
);
EXTERN_C
NTSTATUS NTAPI NtAlpcImpersonateClientContainerOfPort(
_In_ HANDLE PortHandle,
_In_ PPORT_MESSAGE Message,
_In_ ULONG Flags
);
EXTERN_C
NTSTATUS NTAPI NtAlpcDisconnectPort(
_In_ HANDLE PortHandle,
_In_ ULONG Flags
);
EXTERN_C
NTSTATUS NTAPI NtAlpcCreatePortSection(
_In_ HANDLE PortHandle,
_In_ ULONG Flags,
_In_opt_ HANDLE SectionHandle,
_In_ SIZE_T SectionSize,
_Out_ PHANDLE AlpcSectionHandle,
_Out_ PSIZE_T ActualSectionSize
);
EXTERN_C
NTSTATUS NTAPI NtAlpcCreateSectionView(
_In_ HANDLE PortHandle,
_Reserved_ ULONG Flags,
_Inout_ PALPC_DATA_VIEW_ATTR ViewAttributes
);
EXTERN_C
ULONG NTAPI AlpcMaxAllowedMessageLength();
EXTERN_C
NTSTATUS NTAPI NtAlpcQueryInformationMessage(
_In_ HANDLE PortHandle,
_In_ PPORT_MESSAGE PortMessage,
_In_ ALPC_MESSAGE_INFORMATION_CLASS MessageInformationClass,
__out_bcount(Length) PVOID MessageInformation,
_In_ SIZE_T Length,
_Out_opt_ PSIZE_T ReturnLength
);
// From https://processhacker.sourceforge.io/doc/ntlpcapi_8h.html#a1c4ea76677db393f9bb13baabdcb242a
EXTERN_C
NTSTATUS NTAPI NtAlpcCreateSecurityContext(
_In_ HANDLE PortHandle,
_Reserved_ ULONG Flags,
_Inout_ PALPC_SECURITY_ATTR SecurityAttribute
);
//EXTERN_C
//NTSTATUS NTAPI NtAlpcOpenSenderThread(
// _Out_ PHANDLE ThreadHandle,
// _In_ HANDLE PortHandle,
// _In_ PPORT_MESSAGE PortMessage,
// _In_ ULONG Flags,
// _In_ ACCESS_MASK DesiredAccess,
// _In_ POBJECT_ATTRIBUTES ObjectAttributes
//);
//
// CUSTOM Additions for my specific ALPC serer
//
typedef struct _CS_PORT_CONTEXT {
ULONG PID;
ULONG TID;
ULONG ID;
} CS_PORT_CONTEXT, * PCS_PORT_CONTEXT;
typedef struct _ALPC_MESSAGE {
PORT_MESSAGE PortHeader;
BYTE PortMessage[1000]; // Hard limit for this is 65488. An Error is thrown if AlpcMaxAllowedMessageLength() is exceeded
} ALPC_MESSAGE, * PALPC_MESSAGE;
//
// OTHER Stuff
//
//typedef struct _PH_TOKEN_ATTRIBUTES
//{
// HANDLE TokenHandle;
// struct
// {
// ULONG Elevated : 1;
// ULONG ElevationType : 2;
// ULONG ReservedBits : 29;
// };
// ULONG Reserved;
// PSID TokenSid;
//} PH_TOKEN_ATTRIBUTES, * PPH_TOKEN_ATTRIBUTES;
//0x4 bytes (sizeof)
struct _EX_PUSH_LOCK
{
union
{
struct
{
ULONG Locked : 1; //0x0
ULONG Waiting : 1; //0x0
ULONG Waking : 1; //0x0
ULONG MultipleShared : 1; //0x0
ULONG Shared : 28; //0x0
};
ULONG Value; //0x0
PVOID Ptr; //0x0
};
};
typedef struct _ALPC_HANDLE_TABLE{
_ALPC_HANDLE_ENTRY Handles;
UINT TotalHandles;
UINT Flags;
_EX_PUSH_LOCK Lock;
} ALPC_HANDLE_TABLE, * PALPC_HANDLE_TABLE;
//typedef struct _EPROCESS* PEPROCESS;
typedef struct _KALPC_SECURITY_DATA
{
PALPC_HANDLE_TABLE HandleTable; //_KALPC_SECURITY_DATA
LPVOID ContextHandle;
LPVOID OwningProcess;
LPVOID OwnerPort;
_SECURITY_CLIENT_CONTEXT DynamicSecurity;
} KALPC_SECURITY_DATA, * PKALPC_SECURITY_DATA;
文件CommandALPC.cpp
//#include<iostream>
#include<stdio.h>
#include<windows.h>
#include <sddl.h>
#include <AclAPI.h>
#include"ALPC.h"
// This could also be defined in the project properties, but i wanted to ensure everyone spots that you need to link against those libs
#pragma comment( lib, "ntdll" )
#pragma comment( lib, "User32" )
typedef struct _csTOKEN {
LPWSTR pwsUSERSID;
TOKEN_TYPE TokenType;
LPWSTR pwsTokenType;
LPWSTR pwsTokenImpersonationLevel;
} CSTOKEN, * PCSTOKEN;
BOOL EnablePriv(HANDLE hToken, LPCTSTR priv)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(NULL, priv, &luid))
{
printf("Priv Lookup FALSE\n");
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("Priv Adjust FALSE\n");
return FALSE;
}
return TRUE;
}
BOOL printTokenType(HANDLE hToken, PCSTOKEN pCSToken) {
PTOKEN_TYPE ptt = NULL;
DWORD dwSize = 0;
pCSToken->pwsTokenType = (LPWSTR)L"";
if (!GetTokenInformation(hToken, TokenType, NULL, 0, &dwSize)
&& ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
return FALSE;
}
if (NULL != (ptt = (PTOKEN_TYPE)LocalAlloc(LPTR, dwSize)))
{
if (!GetTokenInformation(hToken, TokenType, ptt, dwSize, &dwSize))
{
LocalFree((HLOCAL)ptt);
return FALSE;
}
pCSToken->TokenType = (TOKEN_TYPE)*ptt;
switch (pCSToken->TokenType)
{
case TokenImpersonation:
pCSToken->pwsTokenType = (LPWSTR)L"ImpersonationToken";
return TRUE;
case TokenPrimary:
pCSToken->pwsTokenType = (LPWSTR)L"PrimaryToken";
return TRUE;
default:
wprintf(L"[-] Undefined Token Type. \n");
return FALSE;
}
LocalFree((HLOCAL)ptt);
}
return FALSE;
}
BOOL printTokenImpersonationLeven(HANDLE hToken, PCSTOKEN pCSToken) {
PSECURITY_IMPERSONATION_LEVEL psil = NULL;
DWORD dwSize = 0;
pCSToken->pwsTokenImpersonationLevel = (LPWSTR)L"";
if (!GetTokenInformation(hToken, TokenImpersonationLevel, NULL, 0, &dwSize)
&& ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
return FALSE;
}
if (NULL != (psil = (PSECURITY_IMPERSONATION_LEVEL)LocalAlloc(LPTR, dwSize)))
{
if (!GetTokenInformation(hToken, TokenImpersonationLevel, psil, dwSize, &dwSize))
{
LocalFree((HLOCAL)psil);
return FALSE;
}
switch (*psil)
{
case SecurityAnonymous:
pCSToken->pwsTokenImpersonationLevel = (LPWSTR)L"SecurityAnonymous";
return TRUE;
case SecurityIdentification:
pCSToken->pwsTokenImpersonationLevel = (LPWSTR)L"SecurityIdentification";
return TRUE;
case SecurityImpersonation:
pCSToken->pwsTokenImpersonationLevel = (LPWSTR)L"SecurityImpersonation";
return TRUE;
case SecurityDelegation:
pCSToken->pwsTokenImpersonationLevel = (LPWSTR)L"SecurityDelegation";
return TRUE;
default:
wprintf(L"[-] Undefined Impersonation Level. \n");
return FALSE;
}
LocalFree((HLOCAL)psil);
}
return FALSE;
}
BOOL printTokenUserSid(HANDLE hToken, PCSTOKEN pCSToken)
{
PTOKEN_USER ptu = NULL;
DWORD dwSize = 0;
pCSToken->pwsUSERSID = (LPWSTR)L"";
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize)
&& ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
return FALSE;
}
if (NULL != (ptu = (PTOKEN_USER)LocalAlloc(LPTR, dwSize)))
{
LPWSTR StringSid = NULL;
if (!GetTokenInformation(hToken, TokenUser, ptu, dwSize, &dwSize))
{
LocalFree((HLOCAL)ptu);
return FALSE;
}
if (ConvertSidToStringSidW(ptu->User.Sid, &StringSid))
{
pCSToken->pwsUSERSID = StringSid;
//LocalFree((HLOCAL)StringSid);
LocalFree((HLOCAL)ptu);
return TRUE;
}
else {
wprintf(L"[-] Failed to resolve SID to string.\n");
return FALSE;
}
LocalFree((HLOCAL)ptu);
}
return FALSE;
}
void ExtractTokenInformation(HANDLE hToken) {
BOOL result;
PCSTOKEN pCSToken = new CSTOKEN;
// Get UserSID
result = printTokenUserSid(hToken, pCSToken);
if (!result) wprintf(L" [-]... failed to get Token SID\n");
else wprintf(L" [+] UserSID: %s\n", pCSToken->pwsUSERSID);
// GET TokenType
result = printTokenType(hToken, pCSToken);
if (!result) wprintf(L" [-]... failed to get Token Type\n");
else wprintf(L" [+] TokenType: %s\n", pCSToken->pwsTokenType);
if (pCSToken->TokenType == TokenImpersonation) {
// GET TokenImpersonationLevel
result = printTokenImpersonationLeven(hToken, pCSToken);
if (!result) wprintf(L" [-]... failed to get Token Type\n");
else wprintf(L" [+] ImpersonationLevel: %s\n", pCSToken->pwsTokenImpersonationLevel);
}
if (pCSToken->pwsUSERSID)
{
LocalFree((HLOCAL)pCSToken->pwsUSERSID);
}
}
void setWindowAccess() {
DWORD error;
wprintf(L"[*] Gettinng current process Window...");
HWINSTA hWinSta = GetProcessWindowStation();
if (hWinSta) {
wprintf(L"Success.\n");
wprintf(L"[*] Setting Security of current Proccess Window...");
error = SetSecurityInfo(hWinSta,
SE_WINDOW_OBJECT,
DACL_SECURITY_INFORMATION,
NULL, // don't set the ownerSID
NULL, // don't set the primary GROUP
NULL, // DACL pointer, NULL=> full access to everyone
NULL // no setting SACL
);
if (error == ERROR_SUCCESS) wprintf(L"Success.\n");
else wprintf(L"Error: %d.\n", error);
}
else wprintf(L"Error: %d.\n", GetLastError());
}
void setDesktopAccess() {
DWORD error;
wprintf(L"[*] Getting current Desktop..");
HDESK hDesk = GetThreadDesktop(GetCurrentThreadId());
if (hDesk) {
wprintf(L"Success\n");
wprintf(L"[*] Setting Security of current Desktop...");
error = SetSecurityInfo(
hDesk,
SE_WINDOW_OBJECT,
DACL_SECURITY_INFORMATION,
NULL, // don't set the ownerSID
NULL, // don't set the primary GROUP
NULL, // DACL pointer, NULL=> full access to everyone
NULL // no setting SACL
);
if (error == ERROR_SUCCESS) wprintf(L"Success\n");
else wprintf(L"Error: %d\n", error);
}
else wprintf(L"Error: %d\n", GetLastError());
}
BOOL execCommand(HANDLE hDuppedToken, LPCWSTR command) {
// -- Execute Process
BOOL bSuccess;
PROCESS_INFORMATION pi;
STARTUPINFOW si;
//SECURITY_ATTRIBUTES sa;
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
//memset(&pi, 0x00, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
wprintf(L"[*] Trying to launch '%s' with CreateProcessWithTokenW ... ", command);
/*
创建新进程及其主线程。 新进程在指定令牌的安全上下文中运行。 它可以选择性地加载指定用户的用户配置文件。
调用 CreateProcessWithTokenW 的进程必须具有SE_IMPERSONATE_NAME特权。
如果此函数失败并出现 ERROR_PRIVILEGE_NOT_HELD (1314) ,请改用 CreateProcessAsUser 或 CreateProcessWithLogonW 函数。
通常,调用的进程CreateProcessAsUser 必须具有SE_INCREASE_QUOTA_NAME特权,并且如果令牌不可分配,
则可能需要SE_ASSIGNPRIMARYTOKEN_NAME特权。 CreateProcessWithLogonW 不需要特殊权限,但必须允许指定的用户帐户以交互方式登录。
通常,最好使用 CreateProcessWithLogonW 创建具有备用凭据的进程。
*/
bSuccess = CreateProcessWithTokenW(
hDuppedToken,
0,
command,
NULL,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
);
if (!bSuccess) {
wprintf(L"failed (Error: %d).\n", GetLastError());
}
else wprintf(L"Success.\n");
return bSuccess;
}
BOOL execImpersonatedWindowCommand(HANDLE hPort, ALPC_MESSAGE pmReceived, LPCWSTR command) {
BOOL bSuccess;
HANDLE hToken, hDuppedToken;
//HANDLE hDuppedToken = INVALID_HANDLE_VALUE;
wprintf(L"[*] Trying to impersonate client...");
NTSTATUS lSuccess = NtAlpcImpersonateClientOfPort(
hPort, // client connection port
(PPORT_MESSAGE)&pmReceived,//&PortMessage, // the port messages
NULL // reserved
);
if (NT_SUCCESS(lSuccess)) {
wprintf(L"Success.\n");
wprintf(L"[*] Trying to open Thread token...");
bSuccess = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken);
if (bSuccess) {
wprintf(L"Success.\n");
ExtractTokenInformation(hToken);
// Duplicate Token
wprintf(L"[*] Trying to duplicate impersonated token...");
bSuccess = DuplicateTokenEx(hToken,
TOKEN_ALL_ACCESS,
NULL,
SecurityImpersonation,
TokenPrimary,
&hDuppedToken);
if (bSuccess) wprintf(L"Success!\n");
else wprintf(L"Error: %d.\n", GetLastError());
ExtractTokenInformation(hDuppedToken);
// -- Revert back to original thread identity
wprintf(L"Reverting back to self...");
bSuccess = RevertToSelf();
if (!bSuccess)
{
wprintf(L"Failed to revert back from RPC client impersonation to server identity. Error 0x%x.\n", GetLastError());
}
else printf("Success.\n");
bSuccess = execCommand(hDuppedToken, command);
// Close Handles
CloseHandle(hToken);
CloseHandle(hDuppedToken);
}
else {
wprintf(L"Error: %d\n", GetLastError());
bSuccess = false;
}
}
else if (lSuccess == STATUS_ACCESS_DENIED) {
wprintf(L"Access Denied! (Error: 0x%X) Maybe the ALPC_PORTFLG_AllowImpersonation was not set?\n", lSuccess);
bSuccess = false;
}
else {
wprintf(L"Error: 0x%X\n", lSuccess);
bSuccess = false;
}
return bSuccess;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALPC_MESSAGE_TYPE get_message_type(ULONG ulType) {
ULONG ulConverted = ulType & 0xFF;
return ALPC_MESSAGE_TYPE(ulConverted);
}
LPCWSTR message_type_to_sz(ULONG ulType) {
ALPC_MESSAGE_TYPE mType = get_message_type(ulType);
switch (mType)
{
case None: return L"None";
case Request: return L"Request";
case Reply: return L"Reply";
case Datagram: return L"Datagram";
case LostReply: return L"LostReply";
case PortClosed: return L"PortClosed";
case ClientDied: return L"ClientDied";
case Exception: return L"Exception";
case DebugEvent: return L"DebugEvent";
case ErrorEvent: return L"ErrorEvent";
case ConnectionRequest: return L"ConnectionRequest";
case ConnectionReply: return L"ConnectionReply";
case UNKNOWN12: return L"UNKNOWN12";
case PortDisconnected: return L"PortDisconnected";
default: return L"Unknown";
}
}
VOID print_port_message(ALPC_MESSAGE portMessage) {
for (int i = 0; i <= portMessage.PortHeader.u1.s1.DataLength; i++) {
BYTE* pbyReadPointer = (BYTE*)portMessage.PortMessage + i;
BYTE byRead = *pbyReadPointer;
printf("%c", byRead);
}
wprintf(L"\n");
}
VOID print_clientSID_from_alpc_message(HANDLE hConnectionPort, PPORT_MESSAGE pPortMessage) {
NTSTATUS lSuccess;
LPVOID pAlloced;
SIZE_T ulRequiredSize;
SIZE_T ulAllocedSize = 0x1c;
// Allow memory for SID
pAlloced = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulAllocedSize);
lSuccess = NtAlpcQueryInformationMessage(
hConnectionPort,
pPortMessage,
ALPC_MESSAGE_INFORMATION_CLASS::AlpcMessageSidInformation,
pAlloced,
ulAllocedSize,
&ulRequiredSize
);
if (NT_SUCCESS(lSuccess)) {
PSID pSID = (PSID)pAlloced;
LPWSTR szSID;
ConvertSidToStringSidW(
pSID,
&szSID
);
wprintf(L"%s\n", szSID);
}
}
NTSTATUS impersonate_client(HANDLE hPort, ALPC_MESSAGE pmReceived) {
BOOL bSuccess;
// usually not needed for local impersonation
/*setWindowAccess();
setDesktopAccess();*/
wchar_t command[] = L"C:\\Windows\\System32\\cmd.exe";
bSuccess = execImpersonatedWindowCommand(hPort, pmReceived, command);
return bSuccess;
}
VOID add_request_message(PALPC_MESSAGE pMessage, LPCSTR messageContent) {
Add a message
//LPVOID lpPortMessage = &(pMessage.PortMessage);
int lMsgLen = wcslen(messageContent);
//char msg[100] = "Hello Client";
//int lMsgLen = strlen(msg);
//memmove(lpPortMessage, msg, lMsgLen);
//pMessage.PortHeader.u1.s1.DataLength = lMsgLen;
//pMessage.PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + lMsgLen;
pMessage.PortHeader.u1.s1.TotalLength = sizeof(pMessage);
LPVOID lpPortMessage = pMessage->PortMessage;
//char msg[100] = "Hello Client";
//int lMsgLen = strlen(msg);
int lMsgLen = strlen(messageContent);
memmove(lpPortMessage, messageContent, lMsgLen);
pMessage->PortHeader.u1.s1.DataLength = lMsgLen;
pMessage->PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + lMsgLen;
}
VOID print_received_alpc_message(ALPC_MESSAGE pmReceived, HANDLE hAlpcPort, BOOL printRequestingSID) {
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)pmReceived.PortHeader.ClientId.UniqueProcess);
//GetProcessImageFileName(hProcess, szProcessName, MAX_PATH);
// PROCESS CONNECTION
wprintf(L"[+] Received data!\n\tFom Process PID: %d (Thead TID: %d) [Process: %s]\n\tType: %s\n\tConnectionMessage Length: %d\n",
pmReceived.PortHeader.ClientId.UniqueProcess,
pmReceived.PortHeader.ClientId.UniqueThread,
szProcessName,
message_type_to_sz(pmReceived.PortHeader.u2.s2.Type),
pmReceived.PortHeader.u1.s1.DataLength
);
if (pmReceived.PortHeader.u1.s1.DataLength > 0) {
wprintf(L"\tConnecting Message: ");
print_port_message(pmReceived);
}
else { wprintf(L"\n"); }
if (printRequestingSID) {
wprintf(L"\tClient SID: ");
print_clientSID_from_alpc_message(hAlpcPort, (PPORT_MESSAGE)&pmReceived);
}
}
typedef enum _POOL_TYPE
{
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, * PPOOL_TYPE;
typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION;
typedef struct _SYSTEM_HANDLE
{
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
VOID print_valid_message_attribues(PALPC_MESSAGE_ATTRIBUTES pMsgAttr, BOOL bIsServer = FALSE) {
int iFoundFlags = 0;
wprintf(L"[*] Valid Message Attributes:\n");
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_TOKEN_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_TOKEN_ATTRIBUTE\n");
ALPC_TOKEN_ATTR tokenAttr = *(PALPC_TOKEN_ATTR)AlpcGetMessageAttribute(pMsgAttr, ALPC_MESSAGE_TOKEN_ATTRIBUTE);
wprintf(L"\t TokenId: %lu -- AuthenticationId: %lu -- ModifiedId: %lu \n", tokenAttr.TokenId, tokenAttr.AuthenticationId, tokenAttr.ModifiedId);
iFoundFlags += ALPC_MESSAGE_TOKEN_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_SECURITY_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_SECURITY_ATTRIBUTE\n");
ALPC_SECURITY_ATTR securitAttr = *(PALPC_SECURITY_ATTR)AlpcGetMessageAttribute(pMsgAttr, ALPC_MESSAGE_SECURITY_ATTRIBUTE);
iFoundFlags += ALPC_MESSAGE_SECURITY_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_CONTEXT_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_CONTEXT_ATTRIBUTE\n");
if( bIsServer ){
ALPC_CONTEXT_ATTR contextAttr = *(PALPC_CONTEXT_ATTR)AlpcGetMessageAttribute(pMsgAttr, ALPC_MESSAGE_CONTEXT_ATTRIBUTE);
CS_PORT_CONTEXT csPortContext = *(PCS_PORT_CONTEXT)contextAttr.PortContext;
wprintf(L"\t Caller ID: %d\n", csPortContext.ID);
}
iFoundFlags += ALPC_MESSAGE_CONTEXT_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_VIEW_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_VIEW_ATTRIBUTE\n");
ALPC_DATA_VIEW_ATTR viewAttr = *(PALPC_DATA_VIEW_ATTR)AlpcGetMessageAttribute(pMsgAttr, ALPC_MESSAGE_VIEW_ATTRIBUTE);
wprintf(L"\t ViewSize: %d\n", viewAttr.ViewSize);
iFoundFlags += ALPC_MESSAGE_VIEW_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_HANDLE_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_HANDLE_ATTRIBUTE\n");
ALPC_HANDLE_ATTR handleAttr = *(PALPC_HANDLE_ATTR)AlpcGetMessageAttribute(pMsgAttr, ALPC_MESSAGE_HANDLE_ATTRIBUTE);
// We could Query the object type like this, code snippet taken from: https://github.com/SinaKarvandi/Process-Magics/blob/master/EnumAllHandles/EnumAllHandles/EnumAllHandles.cpp
//POBJECT_TYPE_INFORMATION OBJECT_TYPE;
//ULONG GuessSize = 256;
//ULONG ulRequiredSize;
Allocate Memory
//OBJECT_TYPE = (POBJECT_TYPE_INFORMATION)VirtualAlloc(NULL, (SIZE_T)GuessSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
//NTSTATUS lSuccess = NtQueryObject(handleAttr.Handle, ObjectTypeInformation, OBJECT_TYPE, GuessSize, &ulRequiredSize);
// We could read the file like this
//LPVOID lpAllocTest = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
//BOOL success = ReadFile(handleAttr.Handle, lpAllocTest, 10, NULL, NULL);
iFoundFlags += ALPC_MESSAGE_HANDLE_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_DIRECT_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_DIRECT_ATTRIBUTE\n");
iFoundFlags += ALPC_MESSAGE_DIRECT_ATTRIBUTE;
}
if (pMsgAttr->ValidAttributes & ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE) {
wprintf(L"\tALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE\n");
iFoundFlags += ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE;
}
if (iFoundFlags != pMsgAttr->ValidAttributes) {
wprintf(L"\t 0x%X Unkwon Message Attribute(s)\n", pMsgAttr->ValidAttributes - iFoundFlags);
}
}
VOID print_port_flags(ULONG ulPortAttributeFlags) {
int iFoundFlags = 0;
wprintf(L"[*] Valid Message Attributes: ");
if (ALPC_PORTFLG_LPCPORT & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_LPCPORT | ");
iFoundFlags += ALPC_PORTFLG_LPCPORT;
}
if (ALPC_PORTFLG_ALLOWIMPERSONATION & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_ALLOWIMPERSONATION | ");
iFoundFlags += ALPC_PORTFLG_ALLOWIMPERSONATION;
}
if (ALPC_PORTFLG_ALLOW_LPC_REQUESTS & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_ALLOW_LPC_REQUESTS | ");
iFoundFlags += ALPC_PORTFLG_ALLOW_LPC_REQUESTS;
}
if (ALPC_PORTFLG_WAITABLE_PORT & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_WAITABLE_PORT | ");
iFoundFlags += ALPC_PORTFLG_WAITABLE_PORT;
}
if (ALPC_PORTFLG_SYSTEM_PROCESS & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_SYSTEM_PROCESS | ");
iFoundFlags += ALPC_PORTFLG_SYSTEM_PROCESS;
}
if (ALPC_PORTFLG_ALLOW_DUP_OBJECT & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_ALLOW_DUP_OBJECT | ");
iFoundFlags += ALPC_PORTFLG_ALLOW_DUP_OBJECT;
}
if (ALPC_PORTFLG_LRPC_WAKE_POLICY1 & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_LRPC_WAKE_POLICY1 | ");
iFoundFlags += ALPC_PORTFLG_LRPC_WAKE_POLICY1;
}
if (ALPC_PORTFLG_LRPC_WAKE_POLICY2 & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_LRPC_WAKE_POLICY2 | ");
iFoundFlags += ALPC_PORTFLG_LRPC_WAKE_POLICY2;
}
if (ALPC_PORTFLG_LRPC_WAKE_POLICY3 & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_LRPC_WAKE_POLICY3 | ");
iFoundFlags += ALPC_PORTFLG_LRPC_WAKE_POLICY3;
}
if (ALPC_PORTFLG_DIRECT_MESSAGE & ulPortAttributeFlags) {
wprintf(L"ALPC_PORTFLG_DIRECT_MESSAGE | ");
iFoundFlags += ALPC_PORTFLG_DIRECT_MESSAGE;
}
if (iFoundFlags != ulPortAttributeFlags) {
wprintf(L"\n[!]\t 0x%X unkwon Port Flag(s)\n", ulPortAttributeFlags - iFoundFlags);
}
else {
wprintf(L"\n");
}
}
BOOL accept_connection_request() {
//
// ACCEPT OR DENY DECISION
//
NTSTATUS lSuccess;
BOOL bAutoAcceptConnection = TRUE;
BOOL bAcceptConnection;
if (!bAutoAcceptConnection) {
wprintf(L"[.] Do you want to accept the connection? [Y]: ");
WCHAR wcAcceptConnection[2];
//std::wcin.getline(wcAcceptConnection, 2);
if (wcscmp(wcAcceptConnection, L"Y") == 0 || wcscmp(wcAcceptConnection, L"y") == 0) {
bAcceptConnection = TRUE;
}
else {
bAcceptConnection = FALSE;
};
}
else { bAcceptConnection = TRUE; }
return bAcceptConnection;
}
PSECURITY_DESCRIPTOR create_sd_from_string(LPCWSTR szDACL) {
PSECURITY_DESCRIPTOR pSD;
ULONG ulSDSize = 0;
BOOL success = ConvertStringSecurityDescriptorToSecurityDescriptorW(
szDACL,
SDDL_REVISION_1,
&pSD,
&ulSDSize
);
return pSD;
}
PALPC_MESSAGE_ATTRIBUTES alloc_message_attribute(ULONG ulAttributeFlags) {
NTSTATUS lSuccess;
PALPC_MESSAGE_ATTRIBUTES pAttributeBuffer;
LPVOID lpBuffer;
SIZE_T lpReqBufSize;
SIZE_T ulAllocBufSize;
ulAllocBufSize = AlpcGetHeaderSize(ulAttributeFlags); // this calculates: sizeof(ALPC_MESSAGE_ATTRIBUTES) + size of attribute structures
lpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulAllocBufSize);
if (GetLastError() != 0) {
wprintf(L"[-] Failed to allocate memory for ALPC Message attributes.\n");
return NULL;
}
pAttributeBuffer = (PALPC_MESSAGE_ATTRIBUTES)lpBuffer;
//wprintf(L"[*] Initializing ReceiveMessage Attributes (0x%X)...", ulAttributeFlags);
lSuccess = AlpcInitializeMessageAttribute(
ulAttributeFlags, // attributes
pAttributeBuffer, // pointer to attributes structure
ulAllocBufSize, // buffer size
&lpReqBufSize
);
if (!NT_SUCCESS(lSuccess)) {
//wprintf(L"Error: 0x%X\n", lSuccess);
//pAttributeBuffer->ValidAttributes = ulAttributeFlags;
return NULL;
}
else {
//wprintf(L"Success.\n");
return pAttributeBuffer;
}
}
PALPC_MESSAGE_ATTRIBUTES setup_sample_message_attributes(HANDLE hAlpcPort, HANDLE hSection, ULONG ulMessageAttributes) {
NTSTATUS lSuccess;
INT iNextMsgAttrBufferOffset;
SIZE_T ulReqBufSize;
SIZE_T ulMessageAttributeBufSize = AlpcGetHeaderSize(ulMessageAttributes);
LPVOID lpAllocTest = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulMessageAttributeBufSize); // NOTE: This buffer is never freed... for this sample i just don't care for this
PALPC_MESSAGE_ATTRIBUTES pMsgAttrSend = (PALPC_MESSAGE_ATTRIBUTES)lpAllocTest;
lSuccess = AlpcInitializeMessageAttribute(
ulMessageAttributes, // the MessageAttribute
pMsgAttrSend, // pointer to allocated buffer that is used to holf attributes structures
ulMessageAttributeBufSize, // buffer that has been allocated
&ulReqBufSize // the size that would be needed (in case of the buffer allocated was too small)
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error calling AlpcInitializeMessageAttribute: 0x%X\n", lSuccess);
}
iNextMsgAttrBufferOffset = 8; // 4 bytes allocated attributes + 4 bytes valid attributes
if (ulMessageAttributes & ALPC_MESSAGE_SECURITY_ATTRIBUTE) {
// ALPC_MESSAGE_SECURITY_ATTRIBUTE
SECURITY_QUALITY_OF_SERVICE SecurityQos;
ALPC_SECURITY_ATTR securityAttr;
RtlZeroMemory(&securityAttr, sizeof(securityAttr));
SecurityQos.ImpersonationLevel = SecurityImpersonation; // SecurityIdentification;
SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
SecurityQos.EffectiveOnly = 0;
SecurityQos.Length = sizeof(SecurityQos);
securityAttr.pQOS = &SecurityQos;
securityAttr.Flags = 0; // 0x10000;
lSuccess = NtAlpcCreateSecurityContext(hAlpcPort, 0, &securityAttr);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Error creating security context: 0x%X\n", lSuccess);
}
else {
memmove((PBYTE)pMsgAttrSend + iNextMsgAttrBufferOffset, &securityAttr, sizeof(securityAttr));
iNextMsgAttrBufferOffset += sizeof(securityAttr);
}
//RtlSecureZeroMemory(&securityAttr, sizeof(securityAttr));
/*securityAttr.ContextHandle = &securityContext;
securityAttr.Flags = 0;
securityAttr.pQOS = &SecurityQos;*/
}
if (ulMessageAttributes & ALPC_MESSAGE_VIEW_ATTRIBUTE) {
// ALPC_MESSAGE_VIEW_ATTRIBUTE
ALPC_DATA_VIEW_ATTR viewAttr;
viewAttr.Flags = 0; //unknown
viewAttr.SectionHandle = hSection;
viewAttr.ViewBase = 0;
viewAttr.ViewSize = 20*1024;//50;//sizeof(PORT_VIEW);
lSuccess = NtAlpcCreateSectionView(
hAlpcPort, //_In_ HANDLE PortHandle,
0, // _Reserved_ ULONG Flags,
&viewAttr //_Inout_ PALPC_DATA_VIEW_ATTR ViewAttributes
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Error creating SectionView: 0x%X\n", lSuccess);
}
else {
// Fill section with some sample junk
RtlFillMemory(viewAttr.ViewBase, 0x41, 50);
// place ALPC_MESSAGE_VIEW_ATTRIBUTE structure
memmove((PBYTE)pMsgAttrSend + iNextMsgAttrBufferOffset, &viewAttr, sizeof(viewAttr));
};
iNextMsgAttrBufferOffset += sizeof(viewAttr);
}
if (ulMessageAttributes & ALPC_MESSAGE_HANDLE_ATTRIBUTE) {
// ALPC_MESSAGE_HANDLE_ATTRIBUTE
HANDLE hFile = CreateFileW(L"C:\\Users\\Public\\testfile.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ALPC_HANDLE_ATTR handleAttr;
handleAttr.Handle = hFile;
handleAttr.ObjectType = 0;
handleAttr.Flags = 0;
handleAttr.DesiredAccess = GENERIC_READ;
memmove((PBYTE)pMsgAttrSend + iNextMsgAttrBufferOffset, &handleAttr, sizeof(handleAttr));
iNextMsgAttrBufferOffset += sizeof(handleAttr);
}
if (ulMessageAttributes & ALPC_MESSAGE_HANDLE_ATTRIBUTE) {
// ALPC_MESSAGE_DIRECT_ATTRIBUTE
/// not yet implemented
}
if (ulMessageAttributes & ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE) {
//ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE
/// not yet implemented
}
return pMsgAttrSend;
}
文件CPP-ALPC-Basic-Client.cpp
//#include <winnt.h>
//#include <sddl.h>
#include "..\ALPC-Utils\ALPC.h"
#include "..\ALPC-Utils\CommonALPC.cpp"
const long MAX_MESSAGE_SIZE = 0x100;
int main() {
HANDLE hSrvCommPort;
NTSTATUS lSuccess;
CLIENT_ID clientID;
ALPC_MESSAGE pmReceived;
ALPC_MESSAGE pmSend;
SIZE_T ulSendSize;
SIZE_T ulReceivedSize;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
ALPC_PORT_ATTRIBUTES PortAttributes;
PALPC_MESSAGE_ATTRIBUTES pMsgAttrSend;
PALPC_MESSAGE_ATTRIBUTES pMsgAttrReceived;
ALPC_MESSAGE_ATTRIBUTES inMsgAttr;
UNICODE_STRING usPortName;
LPCWSTR pwsPortName = L"\\RPC Control\\CSALPCPort"; // the name of the ALPC port we're attempting to connect to
PSID pSID = NULL;
BOOL bVerifyServerSID = FALSE;
//
// INITIALIZAITONS
//
DWORD dwPID = GetCurrentProcessId();
DWORD dwTID = GetCurrentThreadId();
clientID.UniqueProcess = &dwPID;
clientID.UniqueThread = &dwTID;
// Received Message attributes.. I'm fine with getting all of them
pMsgAttrReceived = alloc_message_attribute(ALPC_MESSAGE_ATTRIBUTE_ALL);
// QOS
SecurityQos.ImpersonationLevel = SecurityImpersonation; // SecurityIdentification; // ;
SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
SecurityQos.EffectiveOnly = 0;
SecurityQos.Length = sizeof(SecurityQos);
// ALPC Port Attributs
PortAttributes.Flags = ALPC_PORTFLG_ALLOW_DUP_OBJECT | ALPC_PORTFLG_ALLOWIMPERSONATION | ALPC_PORTFLG_LRPC_WAKE_POLICY1 | ALPC_PORTFLG_LRPC_WAKE_POLICY2 | ALPC_PORTFLG_LRPC_WAKE_POLICY3; // | ALPC_PORTFLG_DIRECT_MESSAGE;
PortAttributes.MaxMessageLength = sizeof(ALPC_MESSAGE); // technically the hard limit for this is 65535, if no constrains you can use AlpcMaxAllowedMessageLength() to set this limit
PortAttributes.MemoryBandwidth = 512;
PortAttributes.MaxSectionSize = 0xffffffff; // 20000;
PortAttributes.MaxViewSize = 0xffffffff; // 20000; // sizeof(PORT_VIEW);
PortAttributes.MaxTotalSectionSize = 0xffffffff;// 20000;
PortAttributes.DupObjectTypes = 0xffffffff;
PortAttributes.MaxPoolUsage = 0xffffffff; // 0x4000;
PortAttributes.SecurityQos = SecurityQos;
wprintf(L"[*] Starting Client. PID: %d | TID: %d\n", dwPID, dwTID);
RtlInitUnicodeString(&usPortName, pwsPortName); // Initialize Unicode String
//
// CONNECT TO SERVER PORT
//
RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
add_request_message(&pmSend, "Hello Server");
ulSendSize = sizeof(pmSend);
// OPTIONALLY: Verify SID
if (bVerifyServerSID) {
ConvertStringSidToSid(L"S-1-5-21-258271829-1673813934-3670761721-1000", &pSID);
}
wprintf(L"[*] Connecting to port '%s'...", pwsPortName);
/*LARGE_INTEGER timeout;
timeout.QuadPart = 10000000;*/
lSuccess = NtAlpcConnectPort(
&hSrvCommPort, // REQUIRED: empty Communication port handle, fill be set by kernel
&usPortName, // REQUIRED: Server Connect port name to connect to
NULL, // OPTIONAL: Object Attributes, none in this case
&PortAttributes, // OPTIONAL: PortAtrributes, used to set various port connection attributes, most imporatnly port flags
ALPC_SYNC_CONNECTION, // OPTOONAL: Message Flags, no Flags
pSID, // OPTIONAL: Server SID
(PPORT_MESSAGE)&pmSend, // connection message
&ulSendSize, // connection message size
NULL,//pMsgAttrSend, // out messages attribtus
pMsgAttrReceived, // in message attributes
0 //&timeout // OPTIONAL: Timeout, none in this case
);
if (lSuccess == STATUS_PORT_CONNECTION_REFUSED) {
wprintf(L"\n[*] The Server denied the connection request.\n");
return 0;
}
else if (lSuccess == STATUS_SERVER_SID_MISMATCH) {
wprintf(L"\n[*] The specified Server SID does not match with the Server. Connected to the wrong server?.\n");
return 0;
}
else if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
print_received_alpc_message(pmSend, NULL, false);
print_valid_message_attribues(pMsgAttrReceived);
// Impersonation Attempt
/*lSuccess = impersonate_client(hSrvCommPort, pmSend);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Failed to impersonate: 0x%X\n", lSuccess);
};*/
//
// Send Message To Server
//
RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
RtlSecureZeroMemory(&pmSend, sizeof(pmSend));
add_request_message(&pmSend, "Whatzzzzzuuuuuup");
HANDLE hServerSection;
SIZE_T nServerSectionSize;
wprintf(L"[*] Creating Port Section...");
lSuccess = NtAlpcCreatePortSection(
hSrvCommPort, // _In_ HANDLE PortHandle,
0, // _In_ flags // 0x40000 found in rpcrt4.dll
NULL, // OPTIONAL SectionHandle,
1024, // SectionSize,
&hServerSection, // _Out_ HANDLE AlpcSectionHandle,
&nServerSectionSize // _Out_ ActualSectionSize
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success, Section created. Size: %d\n", nServerSectionSize);
pMsgAttrSend = setup_sample_message_attributes(hSrvCommPort, hServerSection, ALPC_MESSAGE_VIEW_ATTRIBUTE); //ALPC_MESSAGE_SECURITY_ATTRIBUTE
wprintf(L"[*] [PID: %d; TID: %d] Sending Message (len: %d) to Port ....", GetCurrentProcessId(), GetCurrentThreadId(), pmSend.PortHeader.u1.s1.DataLength);
pMsgAttrSend->ValidAttributes |= ALPC_MESSAGE_VIEW_ATTRIBUTE; // Mark an attribute as valid
lSuccess = NtAlpcSendWaitReceivePort(
hSrvCommPort, // our port handle
ALPC_MSGFLG_SYNC_REQUEST, // message Flags
(PPORT_MESSAGE)&pmSend, // sending message
pMsgAttrSend, // sending attributes
(PPORT_MESSAGE)&pmReceived, // receiving message
&ulReceivedSize, // receiving message length
pMsgAttrReceived, // receive message attributes
0 // no timeout
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
print_received_alpc_message(pmReceived, NULL, false);
print_valid_message_attribues(pMsgAttrReceived);
//
// CLOSING Port
//
wprintf(L"[*] Closing Port connection...");
NtAlpcDisconnectPort(hSrvCommPort, 0);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
CloseHandle(hSrvCommPort);
getchar();
// Finish
return 0;
}
文件CPP-ALPC-Basic-Server.cpp
#include<stdio.h>
#include "..\ALPC-Utils\ALPC.h"
#include "..\ALPC-Utils\CommonALPC.cpp"
#pragma comment( lib, "ntdll" )
#pragma comment( lib, "User32" )
int main(){
//
// DEFINITIONS
//
NTSTATUS lSuccess;
HANDLE hConnectionPort;
HANDLE hCommunicationPort;
UNICODE_STRING usAlpcPortName;
OBJECT_ATTRIBUTES objAttributes;
ALPC_PORT_ATTRIBUTES PortAttributes;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
ALPC_MESSAGE pmReceived;
ALPC_MESSAGE pmRequest;
SIZE_T ulReceivedSize;
PALPC_MESSAGE_ATTRIBUTES pMsgAttrSend;
PALPC_MESSAGE_ATTRIBUTES pMsgAttrReceived;
LPCWSTR pwsPortName = L"\\RPC Control\\CSALPCPort"; // the name of the ALPC port we're creating
CS_PORT_CONTEXT portContext;
UUID uuid;
BOOL bAttemptImpersonation = TRUE;
//
// INITIALIZAITONS
//
DWORD dwPID = GetCurrentProcessId();
DWORD dwTID = GetCurrentThreadId();
// QOS
//RtlZeroMemory(&SecurityQos, sizeof(SECURITY_QUALITY_OF_SERVICE));
SecurityQos.ImpersonationLevel = SecurityIdentification; // SecurityImpersonation; // ; // ; // ;// ;
SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
SecurityQos.EffectiveOnly = 0;
SecurityQos.Length = sizeof(SecurityQos);
// ALPC Port Attributs
PortAttributes.Flags = ALPC_PORTFLG_ALLOW_DUP_OBJECT | ALPC_PORTFLG_ALLOWIMPERSONATION | ALPC_PORTFLG_LRPC_WAKE_POLICY1 | ALPC_PORTFLG_LRPC_WAKE_POLICY2 | ALPC_PORTFLG_LRPC_WAKE_POLICY3; //0xb84a3f0;// ALPC_PORTFLG_ALLOW_DUP_OBJECT | ALPC_PORTFLG_AllowImpersonation | ALPC_PORTFLG_LRPC_WAKE_POLICY1 | ALPC_PORTFLG_LRPC_WAKE_POLICY2 | ALPC_PORTFLG_LRPC_WAKE_POLICY3; // ; //0x8080000;// ALPC_PORFLG_ALLOW_LPC_REQUESTS;// ALPC_PORFLG_ALLOW_LPC_REQUESTS;// | ALPC_PORFLG_SYSTEM_PROCESS;//0x010000 | 0x020000; // Found '0x3080000' in rpcrt4.dll
PortAttributes.MaxMessageLength = sizeof(ALPC_MESSAGE); // technically the hard limit for this is 65535, if no constrains you can use AlpcMaxAllowedMessageLength() to set this limit
PortAttributes.MemoryBandwidth = 512;
PortAttributes.MaxPoolUsage = 0xffffffff;
PortAttributes.MaxSectionSize = 0xffffffff; // 20000;
PortAttributes.MaxViewSize = 0xffffffff; // 20000; // sizeof(PORT_VIEW);
PortAttributes.MaxTotalSectionSize = 0xffffffff; // 20000;
PortAttributes.DupObjectTypes = 0xffffffff;
RtlSecureZeroMemory(&SecurityQos, sizeof(SecurityQos));
PortAttributes.SecurityQos = SecurityQos;
// Security Descriptopr
LPCWSTR szDACL = L"D:(A;OICI;GAGW;;;AU)";// Allow full control to authenticated users
PSECURITY_DESCRIPTOR pSD = create_sd_from_string(szDACL);
// Received Message attributes.. I'm fine with getting all of them
pMsgAttrReceived = alloc_message_attribute(ALPC_MESSAGE_ATTRIBUTE_ALL);
wprintf(L"[*] Starting Server. PID: %d | TID: %d\n", dwPID, dwTID);
//
// CREATE PORT
//
RtlInitUnicodeString(&usAlpcPortName, pwsPortName); // Initialize Unicode String
InitializeObjectAttributes( // set up OBJECT_ATTRIBUTES structure
&objAttributes, // the pointer to the OBJECT_ATTRIBUTES structure
&usAlpcPortName, // the name the object we want to obtain a handle for
0, // no flags, ref.: https://docs.microsoft.com/en-us/windows/win32/api/ntdef/nf-ntdef-initializeobjectattributes
NULL, // no root directry handle as our port name is a full qualified path
NULL//pSD // security descriptor
);
wprintf(L"[*] Creating ALPC Port '%s'...", pwsPortName);
lSuccess = NtAlpcCreatePort(
&hConnectionPort, // the handle to our port name
&objAttributes, // the OBJECT_ATTRIBUTES structure we just initialized
&PortAttributes //0 // additional port attributes
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
print_port_flags(PortAttributes.Flags);
//
// Create Section - just to play around with sections, not necessarily needed
//
HANDLE hServerSection;
SIZE_T nServerSectionSize;
wprintf(L"[*] Creating Port Section...");
lSuccess = NtAlpcCreatePortSection(
hConnectionPort, //_In_ HANDLE PortHandle,
0, //_In_ ULONG Flags, // 0x40000 found in rpcrt4.dll
NULL, //_In_opt_ HANDLE SectionHandle,
1000, // _In_ SIZE_T SectionSize,
&hServerSection, //_Out_ HANDLE AlpcSectionHandle,
&nServerSectionSize //_Out_ PSIZE_T ActualSectionSize
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success, Section created. Size: %d\n", nServerSectionSize);
//
// Setup Message attributes
// --> We set these up once, and reuse the buffer while specifing different valid attributes for different messages
//
pMsgAttrSend = setup_sample_message_attributes(hConnectionPort, hServerSection, ALPC_MESSAGE_SECURITY_ATTRIBUTE | ALPC_MESSAGE_VIEW_ATTRIBUTE | ALPC_MESSAGE_HANDLE_ATTRIBUTE);
//
// WAIT FOR INITIAL CONNECTION
//
wprintf(L"[*] Wait for incoming connections...");
RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
lSuccess = NtAlpcSendWaitReceivePort(
hConnectionPort,
ALPC_MSGFLG_NONE, // no flags
NULL, // SendMessage_
NULL, // SendMessageAttributes
(PPORT_MESSAGE)&pmReceived, // ReceiveBuffer
&ulReceivedSize, // BufferLength
pMsgAttrReceived,//&test, // ReceiveMessageAttributes
0 // no timeout
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X.\n", lSuccess);
return 1;
}
else {
wprintf(L"Success.\n");
}
print_received_alpc_message(pmReceived, NULL, false);
print_valid_message_attribues(pMsgAttrReceived, TRUE);
//
// ACCEPT OR REJECT MESSAGE
//
BOOL bAcceptConnection = accept_connection_request();
RtlSecureZeroMemory(&pmRequest, sizeof(pmRequest));
pmRequest.PortHeader.MessageId = pmReceived.PortHeader.MessageId; // Set the messageID from the received client connection to send the message back to the same client
// Create client context so I can identify the client in every call
portContext.PID = (ULONG)pmReceived.PortHeader.ClientId.UniqueProcess;
portContext.TID = (ULONG)pmReceived.PortHeader.ClientId.UniqueThread;
portContext.ID = portContext.PID + portContext.TID; // not a good UUID for production purposes...just as an example, could be anything
pMsgAttrSend->ValidAttributes |= ALPC_MESSAGE_SECURITY_ATTRIBUTE; // ALPC_MESSAGE_HANDLE_ATTRIBUTE; // Mark the an attribute as valid
if (bAcceptConnection) {
wprintf(L"[*] Accepting Incoming Connection...");
add_request_message(&pmRequest, "I'll accept your connection...");
}
else {
wprintf(L"[*] Denying Incoming Connection...");
add_request_message(&pmRequest, "Nope, you're not allowed to connect...");
}
lSuccess = NtAlpcAcceptConnectPort(
&hCommunicationPort, // Communication port handle
hConnectionPort, // Connection port handle
ALPC_SYNC_CONNECTION, // connection flags
NULL, // no object attributs
&PortAttributes, //0, // port attributes
&portContext, // port context
(PPORT_MESSAGE)&pmRequest, // connection request
pMsgAttrSend, // connection message attributes
bAcceptConnection // accepting the connection
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Done\n");
//
// WAIT FOR INCOMING DATA
//
RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
RtlSecureZeroMemory(&pmRequest, sizeof(pmRequest));
wprintf(L"[*] Waiting for incoming data...");
lSuccess = NtAlpcSendWaitReceivePort(
hConnectionPort, // we need to use the connection port
ALPC_MSGFLG_LPC_MODE, // message flags
NULL,//(PPORT_MESSAGE)&pmRequest, //Sending message
NULL, //pMsgAttrSend, // SendMessageAttributes
(PPORT_MESSAGE)&pmReceived, // ReceivingMessage
&ulReceivedSize, // Receive BufferLength
pMsgAttrReceived, // ReceiveMessageAttributes
0 // no timeout
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
print_received_alpc_message(pmReceived, hConnectionPort, true);
print_valid_message_attribues(pMsgAttrReceived, TRUE);
//
// ATTEMPT IMPERSONATION
//
if (bAttemptImpersonation) {
wprintf(L"[*] Trying to impersonate client...\n");
lSuccess = impersonate_client(hCommunicationPort, pmReceived);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Error: 0x%X\n", lSuccess);
}
else wprintf(L"Done.\n");
}
//
// REPLY TO client
// -- note this could as well have been included in the previous NtAlpcSendWaitReceivePort call, this is just to show case that you could also do something with the message before responding
//
add_request_message(&pmRequest, "Data received!");
pmRequest.PortHeader.MessageId = pmReceived.PortHeader.MessageId;
pMsgAttrSend->ValidAttributes |= ALPC_MESSAGE_VIEW_ATTRIBUTE; // ALPC_MESSAGE_SECURITY_ATTRIBUTE; // Mark the an attribute as valid
wprintf(L"[*] Sending data to port");
lSuccess = NtAlpcSendWaitReceivePort(
hConnectionPort, // we need to use the connection port
ALPC_MSGFLG_REPLY_MESSAGE, // no flags
(PPORT_MESSAGE)&pmRequest, // // SendMessage_
pMsgAttrSend, // SendMessageAttributes
NULL, //(PPORT_MESSAGE)&pmReceived,//ReceiveMessage, // ReceiveBuffer
NULL, //&pmReceivedSize, // Receive BufferLength
NULL, // pMsgAttrReceived, // ReceiveMessageAttributes
0 // no timeout
);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"[-] Error: 0x%X\n", lSuccess);
return 1;
}
else wprintf(L"Success.\n");
// We could wait for new data, but this is just a PoC...
//wprintf(L"Sleeping for 1 seconds..");
//Sleep(1000);
//while (TRUE) {
// wprintf(L"[*] Wait for incoming connections...");
// RtlSecureZeroMemory(&pmReceived, sizeof(pmReceived));
// lSuccess = NtAlpcSendWaitReceivePort(
// hConnectionPort,
// ALPC_MSGFLG_LPC_MODE, // no flags
// NULL, // SendMessage_
// NULL, // SendMessageAttributes
// (PPORT_MESSAGE)&pmReceived, // ReceiveBuffer
// &ulReceivedSize, // BufferLength
// pMsgAttrReceived,//&test, // ReceiveMessageAttributes
// 0 // no timeout
// );
// if (!NT_SUCCESS(lSuccess)) {
// wprintf(L"Error: 0x%X.\n", lSuccess);
// return 1;
// }
// else {
// wprintf(L"Success.\n");
// }
// print_received_alpc_message(pmReceived, hConnectionPort, FALSE);
// print_valid_message_attribues(pMsgAttrReceived, TRUE);
//}
//
// CLOSING Port
//
wprintf(L"[*] Closing Port connection...");
NtAlpcDisconnectPort(hCommunicationPort, 0);
NtAlpcDisconnectPort(hConnectionPort, 0);
if (!NT_SUCCESS(lSuccess)) {
wprintf(L"Error: 0x%X\n", lSuccess);
}
else wprintf(L"Success.\n");
CloseHandle(hConnectionPort);
CloseHandle(hCommunicationPort);
getchar();
// Finish
return 0;
}
编译运行结果如下图: