系统安全C/C++一线开发 [2023]阻止window hook exploit meme 对于安全软件 自己的窗口往往成为最容易被攻击的目标.如window hook exploit这种windows癌症设计引起的问题,理论上,**应该所有的窗口程序都应该这样做从而缓解自己不被攻击** 解决的方法很简单: 1. 给自己设置CFG保护(必选) 2. 使用VEH监控stack overflow事件(可选) 3. hook kedispatchtable,监控win32k的callback function(某些反作弊是这样做的) 4. hook dispatchuserapcroutine,监控来自其他进程的apc,因为最终所谓的peekmeesage都是插入APC(某些反作弊是这样做的) 阅读全文 2023-12-30 huoji 1 条评论
二进制安全一线开发 [2023]profsvc.dll!CreateTempDirectoryForUser导致开机卡慢以及开机黑屏但是过一会就好了的问题 **profsvc.dll!CreateTempDirectoryForUser**在win1809后增加了一个功能,用于标记是否可以删除 hard是不能删除 soft是可以删除 然后他开机时候 给temp这个文件夹设置了soft代表当磁盘空间不足时候可以删除这些文件 **但是设置的实现方法是递归遍历目录打标记.** 因此你的windows临时目录和用户临时目录的文件数量决定了开机速度 **但是有一个例外** 所有的安全软件总是会在minifilter中的precreate或者postcreate地方匹配自己的规则.而本来就因为临时文件过多导致的卡的问题,结果再结合安全软件在匹配规则导致了更卡. 这就是为什么小红伞/卡巴斯基/火绒/360等安全软件 有在某些机器上开机黑屏卡慢的问题. 解决方法:清理临时文件 在11月的时候也有人发现了这个问题: https://zhuanlan.zhihu.com/p/667566995 阅读全文 2023-12-16 huoji 0 条评论
系统安全C/C++ [2018]在 Windows 10 上 WriteProcessMemory 比 NtWriteVirtualMemory 慢很多 WriteProcessMemory 不仅仅是一个NT包装函数,它还执行一些额外的工作(例如保护内存、刷新指令等) 通过逆向WPM 调用 NtQueryVirtualMemory 来确定我们正在写入的区域中页面的访问保护。如果访问保护不是正确的,WPM 将设置 ACCESS_VIOLATION 错误代码并返回(如果访问保护是 PAGE_NOACCES 或 PAGE_READONLY)。 如果没有,它会调用 NtProtectVirtualMemory 设置适当的访问保护。检查之后,函数调用 NtWriteVirtualMemory 和 NtFlushInstructionCache,对它们进行更多检查,然后返回。 这就是为什么慢的原因 阅读全文 2023-09-10 huoji 0 条评论
系统安全二进制安全C/C++一线开发 [2022]终端安全: 一文从浅入深介绍windows WFP框架 Windows 中的 WFP 框架是一个用于网络流量管理的工具,它可以帮助用户控制数据包在网络中的流动,从而提高网络安全性和性能。本文将深入介绍 Windows 中的 WFP 框架,并通过一个简单的实例(基于 WFP 框架的 DNS 流量解析工具)让大家更好地理解它. 阅读全文 2022-12-10 huoji 0 条评论
系统安全二进制安全 [2022]新瓶装旧酒: 微软CreateProcessNotify的设计缺陷 这个问题至少 至少 从被发现到现在有3年的历史了,个人认为不算漏洞了.所以开一篇文章说说这个问题. 这是att&ck上的对应T对本技术的描述: https://attack.mitre.org/techniques/T1564/010/ 阅读全文 2022-10-12 huoji 0 条评论
C/C++ [2022]windows官方提升debug权限代码 ```cpp HRESULT EnableDebugPrivilege(void) { OSVERSIONINFO OsVer; OsVer.dwOSVersionInfoSize = sizeof(OsVer); if (!GetVersionEx(&OsVer)) { return WIN32_LAST_STATUS(); } if (OsVer.dwPlatformId != VER_PLATFORM_WIN32_NT) { return S_OK; } #ifdef _WIN32_WCE return E_NOTIMPL; #else HRESULT Status = S_OK; HANDLE Token; PTOKEN_PRIVILEGES NewPrivileges; LUID LuidPrivilege; static s_PrivilegeEnabled = FALSE; if (s_PrivilegeEnabled) { return S_OK; } // // Make sure we have access to adjust and to get the // old token privileges // if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &Token)) { Status = WIN32_LAST_STATUS(); goto EH_Exit; } // // Initialize the privilege adjustment structure // LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &LuidPrivilege); NewPrivileges = (PTOKEN_PRIVILEGES) calloc(1, sizeof(TOKEN_PRIVILEGES) + (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES)); if (NewPrivileges == NULL) { Status = E_OUTOFMEMORY; goto EH_Token; } NewPrivileges->PrivilegeCount = 1; NewPrivileges->Privileges[0].Luid = LuidPrivilege; NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // // Enable the privilege // if (!AdjustTokenPrivileges( Token, FALSE, NewPrivileges, 0, NULL, NULL )) { Status = WIN32_LAST_STATUS(); } free(NewPrivileges); EH_Token: CloseHandle(Token); EH_Exit: if (Status == S_OK) { s_PrivilegeEnabled = TRUE; } return Status; #endif // #ifdef _WIN32_WCE } ``` 阅读全文 2022-01-07 huoji 0 条评论
系统安全二进制安全C/C++ [2021]Windows Services Manager 工作原理 Windows Services Manager这个组件的工作原理比我之前想的还诡异.这里简单说一下"服务"是怎么被管理的 R3下如果你不直接操控服务注册表而是用API如OpenServiceA、CreateServiceA这些API后,会调用到RPC,发往RPC服务端 - services.exe ### handle不是真handle 我们都知道 OpenService、CretaeService这些函数在没有错误的时候都会返回一个句柄.在服务端里面是这样实现的: ![](https://key08.com/usr/uploads/2021/12/452801300.png) 服务端申请一个heap内存->创建一个内核对象,交给内核管理->返回ScServiceObject 在使用其他的API比如ChangeServiceConfig、DeleteService这些API的时候,客户端需要提供一个之前OpenService、CretaeService函数返回的句柄,这没什么.但是到了服务端也就是services.exe的时候,这个"句柄"就是一个heap内存地址. ### 微软判断句柄是否有效的"高级"方法 以RDeleteService为例,微软通过一个叫做ScIsValidServiceHandle的函数判断句柄是否有效: ![](https://key08.com/usr/uploads/2021/12/1937175394.png) 实际上这个判断就是判断内存是否可用,内存前几个字节是否等于特定的签名: ![](https://key08.com/usr/uploads/2021/12/3160170665.png) 其中48726573h是一个签名,char后叫做"Hres" 但是网上的openNt的签名不知道是微软故意的还是怎么的,是跟WIN7的不一样的(也可能是年代太久远改了) 网上的: ![](https://key08.com/usr/uploads/2021/12/4151614666.png) 这波很高级 ### 句柄变成结构 在服务端参数传进来的句柄从SC_HANDLE会变成一个叫做LPSC_HANDLE_STRUCT的结构,你可以简单粗暴的这样理解: ```cpp LPSC_HANDLE_STRUCT serviceHandleStruct = (LPSC_HANDLE_STRUCT)hService; ``` 这个"LPSC_HANDLE_STRUCT"长这样: ```cpp typedef struct _SC_HANDLE_STRUCT { DWORD Signature; // For block identification to detect some app errors DWORD Flags; // See definitions above DWORD AccessGranted; // Access granted to client. union { // Object specific data struct { LPWSTR DatabaseName; // Name of database opened } ScManagerObject; struct { LPSERVICE_RECORD ServiceRecord; // Pointer to service record } ScServiceObject; } Type; } SC_HANDLE_STRUCT, * LPSC_HANDLE_STRUCT; ``` 请注意,网上的是错的,网上的OPEN NT结构长这样: https://github.com/Hengle/windows_nt_3_5_source_code/blob/d2894c9125ff1c14028435ed1b21164f6b2b871a/windows_nt_3_5_source_code/NT-782/PRIVATE/WINDOWS/SCREG/SC/SERVER/SCOPEN.H#L52 ```cpp typedef struct _SC_HANDLE_STRUCT{ DWORD Signature; // For block identification to detect some app errors DWORD AccessGranted; // Access granted to client. union { // Object specific data struct { LPWSTR DatabaseName; // Name of database opened } ScManagerObject; struct { LPSERVICE_RECORD ServiceRecord; // Pointer to service record } ScServiceObject; } Type; } SC_HANDLE_STRUCT, *LPSC_HANDLE_STRUCT; ``` 这个是错的。 之后,服务端会通过这个SC_HANDLE_STRUCT结构,检查其中的权限: ![](https://key08.com/usr/uploads/2021/12/729026050.png) 然后从内核删除 ![](https://key08.com/usr/uploads/2021/12/1276980355.png) 而其他的,比如查询config的,则通过服务名寻找到服务注册表项,然后查询之类的(md,到最后还不是查注册表) 阅读全文 2021-12-29 huoji 0 条评论