diff --git a/projects/WinDurango.KernelX/CMakeLists.txt b/projects/WinDurango.KernelX/CMakeLists.txt index 3628c5e..b748a0c 100644 --- a/projects/WinDurango.KernelX/CMakeLists.txt +++ b/projects/WinDurango.KernelX/CMakeLists.txt @@ -4,20 +4,12 @@ project(WinDurango.KernelX VERSION 1.0.0) set(VERSION_SUFFIX "-dev.1") # used for non-stable versions, otherwise blank set(CMAKE_CXX_STANDARD 20) -include(FetchContent) - -# Safetyhook -FetchContent_Declare( - safetyhook - GIT_REPOSITORY "https://github.com/cursey/safetyhook.git" - GIT_TAG "origin/main" -) -FetchContent_MakeAvailable(safetyhook) - set(FILES src/kernelx.cpp src/dllmain.cpp src/Hooks.cpp + src/CurrentApp.cpp + include/WinDurango.KernelX/CurrentApp.h include/WinDurango.KernelX/kernelx.h include/WinDurango.KernelX/Logan.h include/WinDurango.KernelX/Hooks.h @@ -25,7 +17,11 @@ set(FILES add_library(WinDurango.KernelX SHARED ${FILES}) -target_link_libraries(WinDurango.KernelX PRIVATE WinDurango.Common WinDurango.Implementation.WinRT) +target_link_libraries(WinDurango.KernelX PRIVATE + WinDurango.Common + WinDurango.Implementation.WinRT + "${CMAKE_SOURCE_DIR}/vcpkg_installed/vcpkg/pkgs/detours_x64-windows/lib/detours.lib" +) target_link_options(WinDurango.KernelX PUBLIC @@ -36,6 +32,7 @@ target_include_directories(WinDurango.KernelX PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/WinDurango.KernelX/ ${CMAKE_SOURCE_DIR}/projects/WinDurango.Common/include ${CMAKE_SOURCE_DIR}/projects/WinDurango.Implementation.WinRT/include + ${CMAKE_SOURCE_DIR}/vcpkg_installed/vcpkg/pkgs/detours_x64-windows/include/detours ) set_target_properties(WinDurango.KernelX PROPERTIES diff --git a/projects/WinDurango.KernelX/include/WinDurango.KernelX/CurrentApp.h b/projects/WinDurango.KernelX/include/WinDurango.KernelX/CurrentApp.h new file mode 100644 index 0000000..a3941c0 --- /dev/null +++ b/projects/WinDurango.KernelX/include/WinDurango.KernelX/CurrentApp.h @@ -0,0 +1,149 @@ +#pragma once +#include "CoreWindow.h" +#include +#include +#include +#include + +using namespace ABI::Windows::System; +using namespace ABI::Windows::Foundation; + +MIDL_INTERFACE("d52dc065-da3f-4685-995e-9b482eb5e603") +EraICurrentApp : IInspectable +{ + public: + virtual HRESULT STDMETHODCALLTYPE get_LicenseInformation( + ABI::Windows::ApplicationModel::Store::ILicenseInformation * *value) = 0; + virtual HRESULT STDMETHODCALLTYPE get_LinkUri(ABI::Windows::Foundation::IUriRuntimeClass * *value) = 0; + virtual HRESULT STDMETHODCALLTYPE get_AppId(GUID * value) = 0; + virtual HRESULT STDMETHODCALLTYPE RequestAppPurchaseAsync( + boolean includeReceipt, __FIAsyncOperation_1_HSTRING * *requestAppPurchaseOperation) = 0; + virtual HRESULT STDMETHODCALLTYPE RequestProductPurchaseAsync( + HSTRING productId, boolean includeReceipt, __FIAsyncOperation_1_HSTRING * *requestProductPurchaseOperation) = 0; + virtual HRESULT STDMETHODCALLTYPE LoadListingInformationAsync( + __FIAsyncOperation_1_Windows__CApplicationModel__CStore__CListingInformation * *loadListingOperation) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAppReceiptAsync(__FIAsyncOperation_1_HSTRING * *appReceiptOperation) = 0; + virtual HRESULT STDMETHODCALLTYPE GetProductReceiptAsync(HSTRING productId, __FIAsyncOperation_1_HSTRING * + *getProductReceiptOperation) = 0; +}; + +MIDL_INTERFACE("8eb7dc30-f170-4ed5-8e21-1516da3fd367") +EraILicenseInformation : IInspectable +{ + public: + virtual HRESULT STDMETHODCALLTYPE get_ProductLicenses( + __FIMapView_2_HSTRING_Windows__CApplicationModel__CStore__CProductLicense * *value) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsActive(boolean * value) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsTrial(boolean * value) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ExpirationDate(ABI::Windows::Foundation::DateTime * value) = 0; + virtual HRESULT STDMETHODCALLTYPE add_LicenseChanged( + ABI::Windows::ApplicationModel::Store::ILicenseChangedEventHandler * handler, + EventRegistrationToken * cookie) = 0; + virtual HRESULT STDMETHODCALLTYPE remove_LicenseChanged(EventRegistrationToken cookie) = 0; +}; + +MIDL_INTERFACE("AA98C583-A3C8-4F51-A5BC-463AE0C23EAA") +EraIXboxUserLicenseInformation : public IInspectable +{ + public: + virtual HRESULT STDMETHODCALLTYPE get_CurrentLicenseUserXuid(winrt::hstring * value) = 0; +}; + +class EraXboxUserLicenseInformationWrapper : public EraIXboxUserLicenseInformation +{ + public: + EraXboxUserLicenseInformationWrapper() + { + InterlockedIncrement(&m_RefCount); + } + + HRESULT QueryInterface(REFIID riid, void **ppvObject) override; + ULONG AddRef() override; + ULONG Release() override; + HRESULT GetIids(ULONG *iidCount, IID **iids) override; + HRESULT GetRuntimeClassName(HSTRING *className) override; + HRESULT GetTrustLevel(TrustLevel *trustLevel) override; + HRESULT STDMETHODCALLTYPE get_CurrentLicenseUserXuid(winrt::hstring *value) override; + +private: + ULONG m_RefCount = 0; +}; + +class EraLicenseInformationWrapper : public EraILicenseInformation +{ + public: + EraLicenseInformationWrapper(ABI::Windows::ApplicationModel::Store::ILicenseInformation *realLicenseInformation) : m_realLicenseInformation(realLicenseInformation) + { + InterlockedIncrement(&m_RefCount); + } + + HRESULT QueryInterface(REFIID riid, void **ppvObject) override; + ULONG AddRef() override; + ULONG Release() override; + + HRESULT GetIids(ULONG *iidCount, IID **iids) override; + HRESULT GetRuntimeClassName(HSTRING *className) override; + HRESULT GetTrustLevel(TrustLevel *trustLevel) override; + + HRESULT STDMETHODCALLTYPE + get_ProductLicenses(__FIMapView_2_HSTRING_Windows__CApplicationModel__CStore__CProductLicense **value) override; + + HRESULT STDMETHODCALLTYPE get_IsActive(boolean *value) override; + + HRESULT STDMETHODCALLTYPE get_IsTrial(boolean *value) override; + + HRESULT STDMETHODCALLTYPE get_ExpirationDate(ABI::Windows::Foundation::DateTime *value) override; + + HRESULT STDMETHODCALLTYPE + add_LicenseChanged(ABI::Windows::ApplicationModel::Store::ILicenseChangedEventHandler *handler, + EventRegistrationToken *cookie) override; + + HRESULT STDMETHODCALLTYPE remove_LicenseChanged(EventRegistrationToken cookie) override; + +private: + ULONG m_RefCount = 0; + ABI::Windows::ApplicationModel::Store::ILicenseInformation *m_realLicenseInformation; +}; + +class EraCurrentAppWrapper : EraICurrentApp +{ + public: + EraCurrentAppWrapper(ABI::Windows::ApplicationModel::Store::ICurrentApp *realApp) : m_realCurrentApp(realApp) + { + InterlockedIncrement(&m_RefCount); + } + + HRESULT QueryInterface(REFIID riid, void **ppvObject) override; + ULONG AddRef() override; + ULONG Release() override; + + HRESULT GetIids(ULONG *iidCount, IID **iids) override; + HRESULT GetRuntimeClassName(HSTRING *className) override; + HRESULT GetTrustLevel(TrustLevel *trustLevel) override; + + HRESULT STDMETHODCALLTYPE + get_LicenseInformation(ABI::Windows::ApplicationModel::Store::ILicenseInformation **value) override; + + HRESULT STDMETHODCALLTYPE get_LinkUri(ABI::Windows::Foundation::IUriRuntimeClass **value) override; + + HRESULT STDMETHODCALLTYPE get_AppId(GUID *value) override; + + HRESULT STDMETHODCALLTYPE RequestAppPurchaseAsync( + boolean includeReceipt, __FIAsyncOperation_1_HSTRING **requestAppPurchaseOperation) override; + + HRESULT STDMETHODCALLTYPE + RequestProductPurchaseAsync(HSTRING productId, boolean includeReceipt, + __FIAsyncOperation_1_HSTRING **requestProductPurchaseOperation) override; + + HRESULT STDMETHODCALLTYPE LoadListingInformationAsync( + __FIAsyncOperation_1_Windows__CApplicationModel__CStore__CListingInformation **loadListingOperation) override; + + HRESULT STDMETHODCALLTYPE GetAppReceiptAsync(__FIAsyncOperation_1_HSTRING **appReceiptOperation) override; + + HRESULT STDMETHODCALLTYPE + GetProductReceiptAsync(HSTRING productId, __FIAsyncOperation_1_HSTRING **getProductReceiptOperation) override; + +private: + ULONG m_RefCount = 0; + ABI::Windows::ApplicationModel::Store::ICurrentApp *m_realCurrentApp; +}; \ No newline at end of file diff --git a/projects/WinDurango.KernelX/include/WinDurango.KernelX/Hooks.h b/projects/WinDurango.KernelX/include/WinDurango.KernelX/Hooks.h index 776bd0b..ad0f7c4 100644 --- a/projects/WinDurango.KernelX/include/WinDurango.KernelX/Hooks.h +++ b/projects/WinDurango.KernelX/include/WinDurango.KernelX/Hooks.h @@ -1,4 +1,5 @@ #pragma once +#pragma comment(lib, "runtimeobject.lib") #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include typedef int32_t (__stdcall *GetActivationFactory_t)(HSTRING classId, IActivationFactory** factory); @@ -20,4 +22,19 @@ HRESULT XWinePatchImport(_In_opt_ HMODULE Module, _In_ HMODULE ImportModule, _In HRESULT PatchNeededImports(_In_opt_ HMODULE Module, _In_ HMODULE ImportModule, _In_ PCSTR Import, _In_ PVOID Function); HMODULE GetRuntimeModule(); inline HRESULT WINAPI EraRoGetActivationFactory(HSTRING classId, REFIID iid, void **factory); -HRESULT WINAPI GetActivationFactoryRedirect(PCWSTR str, REFIID riid, void **ppFactory); \ No newline at end of file +HRESULT WINAPI GetActivationFactoryRedirect(PCWSTR str, REFIID riid, void **ppFactory); + +HRESULT STDMETHODCALLTYPE EraAppActivateInstance(IActivationFactory *thisptr, IInspectable **instance); + +template inline T GetVTableMethod(void *table_base, std::uintptr_t index); + +inline bool IsClassName(HSTRING classId, const char *classIdName) +{ + const wchar_t *classIdString = WindowsGetStringRawBuffer(classId, nullptr); + std::wstring classIdWString(classIdString); + const std::string classIdStringUTF8(classIdWString.begin(), classIdWString.end()); + + return (classIdStringUTF8 == classIdName); +} + +HRESULT(WINAPI *TrueActivateInstance)(IActivationFactory *thisptr, IInspectable **instance) = nullptr; \ No newline at end of file diff --git a/projects/WinDurango.KernelX/src/CurrentApp.cpp b/projects/WinDurango.KernelX/src/CurrentApp.cpp new file mode 100644 index 0000000..c52f3e5 --- /dev/null +++ b/projects/WinDurango.KernelX/src/CurrentApp.cpp @@ -0,0 +1,232 @@ +#include "CurrentApp.h" + +HRESULT EraXboxUserLicenseInformationWrapper::QueryInterface(const IID &riid, void **ppvObject) +{ + if (riid == __uuidof(EraIXboxUserLicenseInformation)) + { + *ppvObject = reinterpret_cast(this); + AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG EraXboxUserLicenseInformationWrapper::AddRef() +{ + return InterlockedIncrement(&m_RefCount); +} + +ULONG EraXboxUserLicenseInformationWrapper::Release() +{ + ULONG refCount = InterlockedDecrement(&m_RefCount); + if (!refCount) delete this; + return refCount; +} + +HRESULT EraXboxUserLicenseInformationWrapper::GetIids(ULONG *iidCount, IID **iids) +{ + return E_NOTIMPL; +} + +HRESULT EraXboxUserLicenseInformationWrapper::GetRuntimeClassName(HSTRING *className) +{ + return E_NOTIMPL; +} + +HRESULT EraXboxUserLicenseInformationWrapper::GetTrustLevel(TrustLevel *trustLevel) +{ + return E_NOTIMPL; +} + +HRESULT EraXboxUserLicenseInformationWrapper::get_CurrentLicenseUserXuid(winrt::hstring *value) +{ + *value = L"0"; + return S_OK; +} + +HRESULT EraLicenseInformationWrapper::QueryInterface(const IID &riid, void **ppvObject) +{ + if (riid == __uuidof(EraILicenseInformation)) + { + *ppvObject = reinterpret_cast(this); + AddRef(); + return S_OK; + } + + if (riid == __uuidof(EraIXboxUserLicenseInformation)) + { + *ppvObject = reinterpret_cast(new EraXboxUserLicenseInformationWrapper()); + AddRef(); + return S_OK; + } + + HRESULT hr = m_realLicenseInformation->QueryInterface(riid, ppvObject); + if (FAILED(hr)) + { + char iidstr[sizeof("{AAAAAAAA-BBBB-CCCC-DDEE-FFGGHHIIJJKK}")]; + OLECHAR iidwstr[sizeof(iidstr)]; + StringFromGUID2(riid, iidwstr, ARRAYSIZE(iidwstr)); + WideCharToMultiByte(CP_UTF8, 0, iidwstr, -1, iidstr, sizeof(iidstr), nullptr, nullptr); + printf("[LicenseInformationWrapperX] Interface Not Implemented: %s\n", iidstr); + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG EraLicenseInformationWrapper::AddRef() +{ + return InterlockedIncrement(&m_RefCount); +} + +ULONG EraLicenseInformationWrapper::Release() +{ + ULONG refCount = InterlockedDecrement(&m_RefCount); + if (!refCount) delete this; + return refCount; +} + +HRESULT EraLicenseInformationWrapper::GetIids(ULONG *iidCount, IID **iids) +{ + return m_realLicenseInformation->GetIids(iidCount, iids); +} + +HRESULT EraLicenseInformationWrapper::GetRuntimeClassName(HSTRING *className) +{ + return m_realLicenseInformation->GetRuntimeClassName(className); +} + +HRESULT EraLicenseInformationWrapper::GetTrustLevel(TrustLevel *trustLevel) +{ + return m_realLicenseInformation->GetTrustLevel(trustLevel); +} + +HRESULT EraLicenseInformationWrapper::get_ProductLicenses(ABI::Windows::Foundation::Collections::__FIMapView_2_HSTRING_Windows__CApplicationModel__CStore__CProductLicense_t **value) +{ + return E_NOTIMPL; +} + +HRESULT EraLicenseInformationWrapper::get_IsActive(boolean *value) +{ + *value = true; + return S_OK; +} + +HRESULT EraLicenseInformationWrapper::get_IsTrial(boolean *value) +{ + *value = false; + return S_OK; +} + +HRESULT EraLicenseInformationWrapper::get_ExpirationDate(ABI::Windows::Foundation::DateTime *value) +{ + ABI::Windows::Foundation::DateTime time; + time.UniversalTime = UINT64_MAX; + + *value = time; + return S_OK; +} + +HRESULT EraLicenseInformationWrapper::add_LicenseChanged(ABI::Windows::ApplicationModel::Store::ILicenseChangedEventHandler *handler, EventRegistrationToken *cookie) +{ + return S_OK; +} + +HRESULT EraLicenseInformationWrapper::remove_LicenseChanged(EventRegistrationToken cookie) +{ + return S_OK; +} + +HRESULT __stdcall EraCurrentAppWrapper::QueryInterface(REFIID riid, void **ppvObject) +{ + if (riid == __uuidof(EraICurrentApp)) + { + *ppvObject = reinterpret_cast(this); + AddRef(); + return S_OK; + } + + HRESULT hr = m_realCurrentApp->QueryInterface(riid, ppvObject); + if (FAILED(hr)) + { + char iidstr[sizeof("{AAAAAAAA-BBBB-CCCC-DDEE-FFGGHHIIJJKK}")]; + OLECHAR iidwstr[sizeof(iidstr)]; + StringFromGUID2(riid, iidwstr, ARRAYSIZE(iidwstr)); + WideCharToMultiByte(CP_UTF8, 0, iidwstr, -1, iidstr, sizeof(iidstr), nullptr, nullptr); + printf("[EraCurrentAppWrapper] Interface Not Implemented: %s\n", iidstr); + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG __stdcall EraCurrentAppWrapper::AddRef() +{ + return InterlockedIncrement(&m_RefCount); +} + +ULONG __stdcall EraCurrentAppWrapper::Release() +{ + ULONG refCount = InterlockedDecrement(&m_RefCount); + if (!refCount) delete this; + return refCount; +} + +HRESULT EraCurrentAppWrapper::GetIids(ULONG *iidCount, IID **iids) +{ + return m_realCurrentApp->GetIids(iidCount, iids); +} + +HRESULT EraCurrentAppWrapper::GetRuntimeClassName(HSTRING *className) +{ + return m_realCurrentApp->GetRuntimeClassName(className); +} + +HRESULT EraCurrentAppWrapper::GetTrustLevel(TrustLevel *trustLevel) +{ + return m_realCurrentApp->GetTrustLevel(trustLevel); +} + +HRESULT EraCurrentAppWrapper::get_LicenseInformation(ABI::Windows::ApplicationModel::Store::ILicenseInformation **value) +{ + return E_NOTIMPL; +} + +HRESULT EraCurrentAppWrapper::get_LinkUri(ABI::Windows::Foundation::IUriRuntimeClass **value) +{ + return m_realCurrentApp->get_LinkUri(value); +} + +HRESULT EraCurrentAppWrapper::get_AppId(GUID *value) +{ + return m_realCurrentApp->get_AppId(value); +} + +HRESULT EraCurrentAppWrapper::RequestAppPurchaseAsync(boolean includeReceipt, ABI::Windows::Foundation::__FIAsyncOperation_1_HSTRING_t **requestAppPurchaseOperation) +{ + return m_realCurrentApp->RequestAppPurchaseAsync(includeReceipt, requestAppPurchaseOperation); +} + +HRESULT EraCurrentAppWrapper::RequestProductPurchaseAsync(HSTRING productId, boolean includeReceipt, ABI::Windows::Foundation::__FIAsyncOperation_1_HSTRING_t **requestProductPurchaseOperation) +{ + return S_OK; +} + +HRESULT EraCurrentAppWrapper::LoadListingInformationAsync(ABI::Windows::Foundation::__FIAsyncOperation_1_Windows__CApplicationModel__CStore__CListingInformation_t **loadListingOperation) +{ + return m_realCurrentApp->LoadListingInformationAsync(loadListingOperation); +} + +HRESULT EraCurrentAppWrapper::GetAppReceiptAsync( + ABI::Windows::Foundation::__FIAsyncOperation_1_HSTRING_t **appReceiptOperation) +{ + return m_realCurrentApp->GetAppReceiptAsync(appReceiptOperation); +} + +HRESULT EraCurrentAppWrapper::GetProductReceiptAsync( + HSTRING productId, ABI::Windows::Foundation::__FIAsyncOperation_1_HSTRING_t **getProductReceiptOperation) +{ + return m_realCurrentApp->GetProductReceiptAsync(productId, getProductReceiptOperation); +} \ No newline at end of file diff --git a/projects/WinDurango.KernelX/src/Hooks.cpp b/projects/WinDurango.KernelX/src/Hooks.cpp index a7e56a1..c10f9d1 100644 --- a/projects/WinDurango.KernelX/src/Hooks.cpp +++ b/projects/WinDurango.KernelX/src/Hooks.cpp @@ -2,6 +2,9 @@ #include "WinDurango.Common/Interfaces/Storage/Directory.h" #include "WinDurango.Common/WinDurango.h" #include "WinDurango.Implementation.WinRT/Interfaces/Storage/Directory.h" +#include "CurrentApp.h" + +using namespace ABI::Windows::ApplicationModel::Store; std::shared_ptr winDurango; GetActivationFactory_t p_GetActivationFactory; @@ -113,10 +116,19 @@ HMODULE GetRuntimeModule() return hModule; } -/* - * Dynamicly load a func - * https://stackoverflow.com/questions/8696653/dynamically-load-a-function-from-a-dll -*/ +template inline T GetVTableMethod(void *table_base, std::uintptr_t index) +{ + return (T)((*reinterpret_cast(table_base))[index]); +} + +HRESULT __stdcall EraAppActivateInstance(IActivationFactory *thisptr, IInspectable **instance) +{ + *instance = reinterpret_cast( + new EraLicenseInformationWrapper(reinterpret_cast(*instance))); + return S_OK; +} + + inline HRESULT WINAPI EraRoGetActivationFactory(HSTRING classId, REFIID iid, void **factory) { const wchar_t *rawString = WindowsGetStringRawBuffer(classId, nullptr); @@ -128,6 +140,21 @@ inline HRESULT WINAPI EraRoGetActivationFactory(HSTRING classId, REFIID iid, voi winDurango->log.Log("WinDurango::KernelX", "EraRoGetActivationFactory: {}", rss); + if (IsClassName(classId, "Windows.ApplicationModel.Store.CurrentApp")) + { + HRESULT hr = RoGetActivationFactory(classId, iid, factory); + + if (FAILED(hr)) + return hr; + + TrueActivateInstance = GetVTableMethod(*factory, 6); + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(reinterpret_cast(&TrueActivateInstance), reinterpret_cast(EraAppActivateInstance)); + DetourTransactionCommit(); + } + if (!p_GetActivationFactory) { HINSTANCE hGetActivationFactoryDLL = LoadLibrary("winrt_x.dll"); @@ -186,4 +213,4 @@ HRESULT WINAPI GetActivationFactoryRedirect(PCWSTR str, REFIID riid, void **ppFa WindowsDeleteString(className); return hr; -} \ No newline at end of file +} diff --git a/vcpkg.json b/vcpkg.json index e9bf53e..6116de6 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -2,6 +2,7 @@ "name": "windurango", "version": "1.0", "dependencies": [ - "cppwinrt" + "cppwinrt", + "detours" ] }