Files
2022-05-23 18:26:30 +02:00

453 lines
16 KiB
C++

#include "psapi.h"
#include "ALPC.h"
#include "Command.cpp"
// 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" )
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;
ConvertSidToStringSid(
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 = ConvertStringSecurityDescriptorToSecurityDescriptor(
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 = CreateFile(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;
}