可以通过
InitiateSystemShutdownEx
或InitiateShutdown
WinAPI使用相同的功能,尤其是在安装更新方面。所以我想研究一下它们用于该
Restart
按钮的代码。通常,我会使用Spy ++查找父窗口的WndProc
,然后将进程加载到IDA Pro中并在其上放置一个断点。然后捕获BM_CLICK
消息的条件。在这种情况下,整个设置都是其自己的窗口。该按钮未在Spy ++中出现:
任何想法如何从那里继续进行?
#1 楼
在将其添加为“另一个答案”之前,我已经进行了仔细的思考,而不是编辑今天早上在我上面发布的现有答案。我觉得这个答案值得自己补充,因为它不仅简单
我花了两个多小时来避免只剪切和粘贴来自其他站点的内容。关于这一点,我只将内容包含在此内容中,这样即使将来的原始网站(从中获取该内容的网站)将来都将关闭,此答案仍将保持相关性。
我试图按照OP的要求,着重于使我们能够挂钩和修改UWP Apps中的代码的要素。
入侵和修改Windows通用应用程序:
DLL注入和函数挂钩在UWP-App中使用大多数(即使不是全部)注入和挂钩技术也能很好地工作。
UWP应用程序和“标准” Win32应用程序之间在函数挂钩和Dll注入方面有两个主要区别:
第一:
UWP app呈现其内容的对象,而不是由Apps
第二个:
要注入的DLL必须具有“读取, “执行”以及为“所有应用程序包”组设置的“读取”权限。
您可以通过DLL文件的属性标签进行设置,但名称可能会随
您的系统语言。
您也可以使用请使用
StackOverflow中的以下小代码段(所以不要介意“转到”)以编程方式设置权限。
代码段
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,然后DLLs代码就会神奇地起作用。
由于UWP-Apps在后台使用Win32 API,因此可以期待KernelBase.dll,
Kernel32.dll,ntdll.dll和user32.dll要加载到其中。您还将在所有UWP应用程序(包括新的UWP计算器应用程序)中找到d2d1.dll和
对于函数挂钩,正如您现在所期望的,它的工作方式与Win32程序相同。
控制(隐藏)“ C:\ Program Files \ WindowsApps \”目录:
如果不控制(隐藏)的“ C:\ Program Files \ WindowsApps \”目录,或者在任何可能的位置,都无法访问UWP-Apps的文件。
但是,您可以控制此文件及其任何子目录及其文件,而不会出现任何问题。
您还可以始终以NT-Authority的身份打开一个外壳并以这种方式访问它们。
如果您只想修改一个简单的配置文件或其他内容,就可以了。
/>但是,某些应用程序(不是全部)会检查其文件是否被篡改。但这很容易被规避。
您所要做的就是在“ KernelBase.dll”中挂接“ CreateFileW”方法,监视文件
访问,然后重新路由这些访问请求以从某些目录加载修改的版本
目录,您就可以访问它。
代码片段:
#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程序。
对我们来说,幸运的是,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;
}
重要说明:调用
// Initialize COM objects, only need to do this once per thread
DWORD hresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (!SUCCEEDED(hresult)) return hresult;
在启动应用程序或进行任何后续操作之前,请先调用它: br />(1)UWP App Modding的基本和中间技术
(2)Hacking and Modding Windows通用应用程序
我衷心希望我的这两个答案对搜索任何内容的人有帮助将来会在UWP App挂钩/修改主题上进行SE。
评论
好答案!我将确保阅读代码示例和参考-荣誉。
–barnaby-b
18年1月15日在15:31
是的,谢谢。这个答案更接近回答我的原始问题。 (您的其他答案是关于全局挂钩的。不幸的是,在这种情况下,您将无法做很多事情。我也可以通过捕获鼠标来单击UWP应用程序的窗口,即Windows.UI.Core.CoreWindow。单击事件在其带有IDA的WndProc中。遗憾的是,从这一点开始是不容易的。或者如何到达可帮助进一步从按钮单击路由呼叫的类。
–c00000fd
18年1月15日在21:42
我会将其标记为答案,以便您可以获得工作的赏金。我只想指出,还有很多工作要做。您可以通过电子邮件与我联系吗?解决后,我会在这里发布更新。
–c00000fd
18年1月16日在1:45
谢谢c00000fd!最近几天一直在加班(甚至在这个周末也都在加班),因此没有时间处理您提到的Windows Update中实际的“重新启动”按钮。希望在接下来的几天中,我将能够为该确切的“重新启动”按钮问题创建解决方案,并在此处进行更新。还将根据要求通过电子邮件发送给您。 @ barnaby-b-谢谢你的夸奖!
– TechLord
18年1月16日在4:35
出色的工作,TechLord,以及对这整件事c00000fd的出色反馈和态度!我希望看到您继续使用该重新启动按钮解决方案TechLord。另外,一旦您将事情固定下来,c00000fd也将很高兴为您提供更新。谢谢你们俩!
–dsasmblr
18年1月16日在18:13
#2 楼
如所承诺的,我将对OP提出的问题发表更具体的答案。决定将其作为一个单独的答案写出来,因为我认为此内容会脱颖而出,不适合我上面发布的两个答案中的任何一个。 />解决他的第一个问题:
但是,在这种情况下,整个设置都是其自己的窗口。
按钮没有出现在Spy ++中
好吧,当使用Spy ++以外的其他工具时,该按钮确实出现了。
我将在帮助下粘贴2个工具的屏幕截图可以发现RESTART按钮的属性。
使用作为Microsoft SDK一部分的INSPECT TOOL:
并同时使用UI Spy工具(请注意,也可以使用许多其他工具)...
现在我们将看到我们破解了什么代码当我们单击RESTART按钮时为ON:
首先,运行系统设置管理器(在任务管理器中将看到SystemSettings.exe)。
通过以下方式“附加”到SystemSettings.exe进程一个调试器(为此目的,我使用了[优秀] x64dbg调试器)。
确保在调试器设置中勾选“ DLL加载中断”,如下所示:
现在,我们*单击“立即重新启动”按钮*(位于Windows设置窗口中) w)。随着“ SettingsHandlers_nt.dll”被加载到进程中,我们将破坏调试器。
这是处理设置窗口事件(单击等)的主要dll。
这是控制流图的一部分,实际上它决定
重新启动:
结果不尽相同,可以通过
InitiateSystemShutdownEx或InitiateShutdown WinAPIs获得,特别是关于安装更新的
。
OP是正确的。
MusUpdateHandlers.dll处理Microsoft Update之后,[自动]的实际决策部分将重新启动,如下所示:
以及这里:
我添加了最后两个屏幕截图,因为OP想要知道什么是API我希望UPDATE之后系统重新启动时调用...
我希望这现在可以得出@ c00000fd想知道的答案...
评论
您好TechLord,您能帮我解决一下问题吗:reverseengineering.stackexchange.com/questions/23454/…非常感谢:)
–沙燕
3月18日14:05
#3 楼
“我想了解有关如何挂接并进入功能的详细信息,该功能在UWP应用中处理按钮单击事件。”
我建议使用EventHook库来挂接全局Windows用户事件。该库可以作为Nuget包使用。
Github和我的fork上有项目库(名为Windows用户操作钩)可以在这里访问。这与我上面提到的库(EventHook库)相同。如果您想掌握源代码,可以访问Github仓库。 :(这些是可以全局挂接的事件)
鼠标事件
剪贴板事件
应用程序事件
/>打印事件
用法-通过nuget安装
安装包EventHook
样本代码:
KeyboardWatcher.Start();
KeyboardWatcher.OnKeyInput += (s, e) =>
{
Console.WriteLine(string.Format("Key {0} event of key {1}", e.KeyData.EventType, e.KeyData.Keyname));
};
MouseWatcher.Start();
MouseWatcher.OnMouseInput += (s, e) =>
{
Console.WriteLine(string.Format("Mouse event {0} at point {1},{2}", e.Message.ToString(), e.Point.x, e.Point.y));
};
ClipboardWatcher.Start();
ClipboardWatcher.OnClipboardModified += (s, e) =>
{
Console.WriteLine(string.Format("Clipboard updated with data '{0}' of format {1}", e.Data, e.DataFormat.ToString()));
};
ApplicationWatcher.Start();
ApplicationWatcher.OnApplicationWindowChange += (s, e) =>
{
Console.WriteLine(string.Format("Application window of '{0}' with the title '{1}' was {2}", e.ApplicationData.AppName, e.ApplicationData.AppTitle, e.Event));
};
PrintWatcher.Start();
PrintWatcher.OnPrintEvent += (s, e) =>
{
Console.WriteLine(string.Format("Printer '{0}' currently printing {1} pages.", e.EventData.PrinterName, e.EventData.Pages));
};
Console.Read();
KeyboardWatcher.Stop();
MouseWatcher.Stop();
ClipboardWatcher.Stop();
ApplicationWatcher.Stop();
PrintWatcher.Stop();
我确定一旦您了解了我们如何能够全局地挂接各种Windows用户事件。
在您的案例中,使用该库,我们将能够编写一个小型C#程序,例如,该程序将挂接mouse-press事件单击“立即重新启动”按钮,从而使我们能够控制后续事件。
由于这个问题是关于挂钩UWP应用程序的,所以我想举一个例子,其中该库用于专门挂钩UWP应用程序,以便在需要时可以将该仓库中的代码用作示例。
请注意,我并不是直接从该回购中摘录任何内容,因为我只想表明该库也可以与UWP Apps很好地配合使用。您可以在这里访问我的Github Repo UWPHook的叉子。
#4 楼
我在每个名为SystemSettting *。*的文件中的System32文件夹中搜索Shutdown一词。我使用Total Commander是因为它可以搜索多种编码,例如ASCII和Unicode:然后内置的查看器显示了对
InitiateSystemShutdownExW
的引用:。
从MSDN:
InitiateSystemShutdownEx函数启动指定计算机的关闭和可选的重新启动,并有选择地记录关闭的原因。
BOOL WINAPI InitiateSystemShutdownEx(
_In_opt_ LPTSTR lpMachineName,
_In_opt_ LPTSTR lpMessage,
_In_ DWORD dwTimeout,
_In_ BOOL bForceAppsClosed,
_In_ BOOL bRebootAfterShutdown,
_In_ DWORD dwReason
);
要进行验证,下一步是使用Ida Pro或API Monitor之类的工具在此API上设置断点。
评论
我不确定SystemSettingsThresholdAdminFlowUI.dll当时是否甚至映射到C:\ Windows \ ImmersiveControlPanel \ SystemSettings.exe进程。
–c00000fd
18年1月10日在3:59
您可以使用例如Process Explorer,但您可能是对的,它以另一种方式调用了此api。
–雷姆科
18年1月10日在9:49
要调试必须使用PLMDebug的UWP应用,可以使用windbg或x64dbg。
– mrexodia
18年1月10日在15:29
@mrexodia:是的,显然,您需要使用PLMDebug来关闭UWP应用程序上的进程生命周期管理。换句话说,这样它就不会在后台被代理暂停。但是,就其本身而言,您无需对其进行调试。它不是调试器。
–c00000fd
18年1月11日在6:42
评论
我很乐意看到有人提供解决方案。也许考虑在此时开始赏金,以吸引沉重打击者的更多兴趣?@dsasmblr:来了。擦掉要点。希望有人能回答。