转载:黑客和修改 Windows 通用应用程序

发布于 2024-05-23  744 次阅读


DLL-Injection 和 Function-Hooking,在 UWP-Apps 中使用大多数(如果不是全部)注入和挂钩技术都可以完美地工作。

UWP 应用程序和“标准”Win32 应用程序之间关于函数挂钩和 Dll 注入的几个主要区别:

第一:
UWP 应用程序在其中呈现其内容的窗口不属于应用程序可执行文件。取而代之的是“ ApplicationFrameHost ”,因此您不应以窗口为目标,而应以进程本身为目标。
注意:因此,当注入 UWP 应用程序时,您无法创建新窗口,例如消息框。

第二:
您要注入的 DLL 必须具有“读取、执行”以及为“所有应用程序包”组设置的“读取”权限。您可以通过 DLL 文件的属性选项卡进行设置,但名称可能因您的系统语言而异。

您也可以使用StackOverflow 中的以下小代码片段 (所以不要介意“goto”)以编程方式设置权限。

代码片段

DWORD SetPermissions(std::wstring wstrFilePath) {
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS eaAccess;
    SECURITY_INFORMATION siInfo = DACL_SECURITY_INFORMATION;
    DWORD dwResult = ERROR_SUCCESS;
    PSID pSID;
    // Get a pointer to the existing DACL
    dwResult = GetNamedSecurityInfo(wstrFilePath.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, & pOldDACL, NULL, & pSD);
    if (dwResult != ERROR_SUCCESS)
        goto Cleanup;
    // Get the SID for ALL APPLICATION PACKAGES using its SID string
    ConvertStringSidToSid(L"S-1-15-2-1", & pSID);
    if (pSID == NULL)
        goto Cleanup;
    ZeroMemory( & eaAccess, sizeof(EXPLICIT_ACCESS));
    eaAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
    eaAccess.grfAccessMode = SET_ACCESS;
    eaAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
    eaAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    eaAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    eaAccess.Trustee.ptstrName = (LPWSTR) pSID;
    // Create a new ACL that merges the new ACE into the existing DACL
    dwResult = SetEntriesInAcl(1, & eaAccess, pOldDACL, & pNewDACL);
    if (ERROR_SUCCESS != dwResult)
        goto Cleanup;
    // Attach the new ACL as the object's DACL
    dwResult = SetNamedSecurityInfo((LPWSTR) wstrFilePath.c_str(), SE_FILE_OBJECT, siInfo, NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwResult)
        goto Cleanup;
Cleanup:
    if (pSD != NULL)
        LocalFree((HLOCAL) pSD);
    if (pNewDACL != NULL)
        LocalFree((HLOCAL) pNewDACL);
    return dwResult;
}

之后,使用您喜欢的注入器/方法注入您的 DLL,您的 DLL 代码将神奇地运行。
由于 UWP 应用程序在底层使用 Win32 API,因此您可以期望在其中加载 KernelBase.dll、Kernel32.dll、ntdll.dll 和 user32.dll。您还会发现 d2d1.dll 和 d3d11.dll 或 d3d12.dll(在少数应用中使用)加载在所有 UWP 应用中,包括新的 UWP 计算器应用。

对于函数挂钩,正如您现在所期望的,它的工作方式与 Win32 程序的工作方式相同。

以控制(隐藏)“C:\ Program Files文件\ WindowsApps \”目录下:
如果不采取控制(隐藏)“C:\ Program Files文件\ WindowsApps \”目录下,或任何你可能拥有它,你不能访问UWP-Apps 文件。
但是您可以控制它,以及任何子目录及其文件,而不会出现任何问题。

您也可以始终以 NT-Authority 身份打开一个 shell并以这种方式访问​​它们。
如果你只是想修改一个简单的配置文件或其他东西,你应该没问题。但是,某些应用程序(并非所有应用程序)会检查其文件是否被篡改。但这很容易规避。

你所要做的就是钩住“KernelBase.dll”中的“CreateFileW”-Method,监控文件访问,然后重新路由这些访问请求,从某个你可以访问的目录加载你的修改版本。

这是一个使用前面提到的 MinHook 库完成刚才描述的示例。

代码片段:

#include <Windows.h>
#include <atlbase.h>
#include <Shlobj.h>
#include <string>
#include "MinHook.h"
// Path to modified game files store in AppData
std::wstring MOD_FILES_PATH;
// Path to the apps protected resources in WindowsApps
// Don't use the full path name, just keep the Publisher.AppName part
std::wstring APP_LOCATION(L"C:\\ProgramFiles\\WindowsApps\\Publisher.AppName");
// Sets a hook on the function at origAddress function and provides a trampoline to the original function
BOOL setHook(LPVOID * origAddress, LPVOID * hookFunction, LPVOID * trampFunction);
// Attaches a hook on a function given the name of the owning module and the name of the function
BOOL attach(LPWSTR wstrModule, LPCSTR strFunction, LPVOID * hook, LPVOID * original);
// Basic hook setup for CreateFileW
typedef HANDLE(WINAPI * PfnCreateFileW)(LPCWSTR lpFilename, DWORD dwAccess,
    DWORD dwSharing, LPSECURITY_ATTRIBUTES saAttributes, DWORD dwCreation,
    DWORD dwAttributes, HANDLE hTemplate);
PfnCreateFileW pfnCreateFileW = NULL; // Will hold the trampoline to the original CreateFileW function
// CreateFileW hook function
HANDLE WINAPI HfnCreateFileW(LPCWSTR lpFilename, DWORD dwAccess, DWORD dwSharing, LPSECURITY_ATTRIBUTES saAttributes, DWORD dwCreation, DWORD dwAttributes, HANDLE hTemplate) {
    std::wstring filePath(lpFilename);
    // Check if the app is accessing protected resources
    if (filePath.find(APP_LOCATION) != filePath.npos) {
        std::wstring newPath(MOD_FILES_PATH);
        // Windows provides the app the location of the WindowsApps directory, so the first half the file path will use back slashes
        // After that, some apps will use back slashes while others use forward slashes so be aware of what the app uses
        newPath += filePath.substr(filePath.find(L"\\", APP_LOCATION.size()) + 1,
            filePath.size());
        // Check if the file being accessed exists at the new path and reroute access to that file
        // Don't reroute directories as bad things can happen such as directories being ghost locked
        if (PathFileExists(newPath.c_str()) && !PathIsDirectory(newPath.c_str()))
            return pfnCreateFileW(newPath.c_str(), dwAccess, dwSharing, saAttributes,
                dwCreation, dwAttributes, hTemplate);
    }
    // Let the app load other files normally
    return pfnCreateFileW(lpFilename, dwAccess, dwSharing, saAttributes,
        dwCreation, dwAttributes, hTemplate);
}
BOOL Initialize() {
    // Initialize MinHook
    if (MH_Initialize() != MH_OK)
        return FALSE;
    // Get the path to the apps AppData folder
    // When inside a UWP app, CSIDL_LOCAL_APPDATA returns the location of the apps AC folder in AppData
    TCHAR szPath[MAX_PATH];
    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, szPath))) {
        // Get the path to the mod files folder
        std::wstring appData(szPath);
        appData = appData.substr(0, appData.rfind(L"AC")); // Get the base directory
        appData += L"LocalState\\ModFiles\\"; // Get the location of any new files you want the app to use
        MOD_FILES_PATH = appData;
    } else
        return FALSE;
    // Attach a hook on CreateProcessW and return the status of the hook
    BOOL hook = TRUE;
    hook &= attach(L"KernelBase.dll", "CreateFileW", (LPVOID * ) & HfnCreateFileW,
        (LPVOID * ) & pfnCreateFileW);
    return hook;
}
BOOL Uninitialize() {
    // Uninitialize MinHook
    if (MH_Uninitialize() != MH_OK)
        return FALSE; // This status will end up being ignored
    return TRUE;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        return Initialize(); // If initialization failed, the DLL will detach
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        Uninitialize(); // Return value doesn't matter when detaching
        break;
    }
    return TRUE;
}
BOOL setHook(LPVOID * origAddress, LPVOID * hookFunction, LPVOID * trampFunction) {
    if (MH_CreateHook(origAddress, hookFunction,
            reinterpret_cast < LPVOID * > (trampFunction)) != MH_OK)
        return FALSE;
    if (MH_EnableHook(origAddress) != MH_OK)
        return FALSE;
    return TRUE;
}
BOOL attach(LPWSTR wstrModule, LPCSTR strFunction, LPVOID * hook, LPVOID * original) {
    HMODULE hModule = GetModuleHandle(wstrModule);
    if (hModule == NULL)
        return FALSE;
    FARPROC hFunction = GetProcAddress(hModule, strFunction);
    if (hFunction == NULL)
        return FALSE;
    return setHook((LPVOID * ) hFunction, hook, original);
}

还有一些事情:
您不能像使用 CreateProcess 的常规 Win32 程序一样启动 UWP 应用程序。幸运的是,M$ 为我们提供了IApplicationActivationManager接口,允许开发人员从常规 Win32 程序启动 UWP 应用程序。

如果我们想在应用程序启动之前对其执行某些操作,我们可以使用以下代码在此之前暂停它。

代码片段:

// Gets the current application's UserModelId and PackageId from the registry
// Substitute your own methods in place of these
std::wstring appName = GetApplicationUserModelId();
std::wstring appFullName = GetApplicationPackageId();

HRESULT hResult = S_OK;

// Create a new instance of IPackageDebugSettings
ATL::CComQIPtr debugSettings;
hResult = debugSettings.CoCreateInstance(CLSID_PackageDebugSettings, NULL, CLSCTX_ALL);
if(hResult != S_OK) return hResult;

// Enable debugging
hResult = debugSettings->EnableDebugging(appFullName.c_str(), NULL, NULL);
if(hResult != S_OK) return hResult;

// Launch the application using the function discussed above
DWORD dwProcessId = 0;
hResult = LaunchApplication(appName, &dwProcessId);
if(hResult != S_OK) return hResult;

/* Do more stuff after the app has been resumed */

// Stop debugging the application so it can run as normal
hResult = debugSettings->DisableDebugging(appFullName.c_str());
if(hResult != S_OK) return hResult;

使用上面的代码,您的程序将挂起,直到应用程序恢复,因为它正在等待应用程序在其启动状态回复 IApplicationActivationManager。要恢复应用程序,您只需在启用调试时指定可执行文件的路径:

代码片段:

// Enable Debugging with a custom debugger executable
hResult = debugSettings->EnableDebugging(appFullName.c_str(), pathToExecutable.c_str(), NULL);
if(hResult != S_OK) return hResult;

Windows 将使用命令行参数 -p 后跟进程 ID 将应用程序进程的进程 ID 传递给充当调试器的可执行文件。从调试器可执行文件中,您可以在应用程序暂停时做任何您想做的事情,例如注入 mod,最后使用 NtResumeProcess 恢复应用程序。

#define IMPORT extern __declspec(dllimport)

IMPORT int __argc;
IMPORT char** __argv;
//IMPORT wchar_t** __wargv;

// Turning this into a normal Windows program so it's invisible when run
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    DWORD dwProcessId = 0;

    // Process the arguments passed to the debugger
    for (int i = 1; i < __argc; i += 2)
    {
        std::string arg(__argv[i]);
        if (arg == "-p")
            dwProcessId = atoi(__argv[i + 1]);
    }

    if(dwProcessId == 0)
        return E_FAIL;

    // Can do additional error checking to make sure the app is active and not tombstoned

    ModLoader::InjectMods(dwProcessId);
    ProcessUtils::ResumeProcess(dwProcessId); // Uses NtResumeProcess

    return S_OK;

重要提示:call

// Initialize COM objects, only need to do this once per thread
DWORD hresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(hresult)) return hresult;

在您启动应用程序或执行任何操作之前,请先调用它:

CoUninitialize();

参考资料:
(1)UWP App Modding的基础和中级技术
(2)Hacking和Modding Windows Universal Apps

我真诚地希望我的这两个答案对将来在 UWP App 挂钩/修改主题上搜索 SE 的人有所帮助。

转载:逆向工程 - 如何对 Windows 10 UWP 应用进行逆向工程? - 吾爱随笔录 - 问答 (52sbl.cn)

届ける言葉を今は育ててる
最后更新于 2024-05-23