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这些函数在没有错误的时候都会返回一个句柄.在服务端里面是这样实现的:  服务端申请一个heap内存->创建一个内核对象,交给内核管理->返回ScServiceObject 在使用其他的API比如ChangeServiceConfig、DeleteService这些API的时候,客户端需要提供一个之前OpenService、CretaeService函数返回的句柄,这没什么.但是到了服务端也就是services.exe的时候,这个"句柄"就是一个heap内存地址. ### 微软判断句柄是否有效的"高级"方法 以RDeleteService为例,微软通过一个叫做ScIsValidServiceHandle的函数判断句柄是否有效:  实际上这个判断就是判断内存是否可用,内存前几个字节是否等于特定的签名:  其中48726573h是一个签名,char后叫做"Hres" 但是网上的openNt的签名不知道是微软故意的还是怎么的,是跟WIN7的不一样的(也可能是年代太久远改了) 网上的:  这波很高级 ### 句柄变成结构 在服务端参数传进来的句柄从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结构,检查其中的权限:  然后从内核删除  而其他的,比如查询config的,则通过服务名寻找到服务注册表项,然后查询之类的(md,到最后还不是查注册表) 阅读全文 2021-12-29 huoji 0 条评论
系统安全二进制安全C/C++汇编 [2020]微软windows defender研究.pdf 主要说了微软的defender是如何做虚拟执行的 反cpuid反虚拟机  虚拟文件系统(注意这是不可见的,平时也没这些目录,但是在杀毒的时候defender就会生成)  虚拟注册表  JavaScript引擎  vmp、net 脱壳/jit解析  pdf文件 链接:https://pan.baidu.com/s/15msYM6Ye1Bu5mJdr_vpMow 提取码:7nua 阅读全文 2021-10-23 huoji 0 条评论
系统安全二进制安全 [2021]微软的两处内存泄露 ### Microsoft Kernel Memory Leak ***Please note that this is only a brief code bug. It is not a security problem and will not cause any security problems*** There are memory leaks in two Microsoft APIs: ``` win32kbase!NtDCompositionCommitSynchronizationObject win32kbase!NtGdiGetCertificate ``` 阅读全文 2021-10-14 huoji 0 条评论
系统安全二进制安全C/C++ [2021]R0驱动内对Windows数字签名验证的大概流程 因为某些原因我不得不抛弃wintrust机制而自己在内核实现驱动数字签名验证,因此有了这篇文章: 首先PE文件有两种信息,一个是catalog一个是pe自带签名,目前文章只介绍PE自带签名,catalog签名较为简单,不做论述 数字签名验证分为几步: 1. 解析pe拿到security data 2. 通过asn1解析"signed security data"拿到证书信息(最为复杂) 3. 交叉验证证书链上的证书,拿到root证书,这个过程中还需要对证书是否被窜改进行确认,这个过程中确认时间戳 4. 检查root证书是否可信 5. 拿到证书hash算法,并且计算PE的hash,再拿PE的hash跟证书hash进行匹配,这一步确认PE是否有效 由于某些问题,不能直接开源代码,但是能稍微的介绍一下这个过程: 阅读全文 2021-09-23 huoji 0 条评论
系统安全 [2021]windows 11 :TPM 和数字主权 你可能已经注意到,也可能没有注意到,很多人都想知道 Microsoft 针对 Windows 11 的新的强制性 TPM 2.0 硬件要求。如果你环顾新闻稿、浅显的技术文档以及诸如“安全性”、“设备健康”、“固件漏洞”和“恶意软件”,你仍然没有得到一个关于为什么你需要这项技术的直接答案。  阅读本文的许多人可能在房子或办公室周围都有机器,它们是用甚至不到七年的硅制造的。这些仍然可以玩当今的最新游戏而不会出现故障或问题,除非你最近让你的祖母或 6 岁的侄子在机器上,否则你可能也没有恶意软件。 那么,你会问,为什么我的机器上突然需要一个 TPM 2.0 设备?嗯,答案很简单。这与你无关;是关于他们的。 阅读全文 2021-07-02 huoji 0 条评论
C/C++一线开发 [2021]微软ApiSetMap的MEME windows ApiSetMap机制是win7以后最奇怪的机制之一,老外在博客上评论是"but no one really know why its useful.".特征就是在你编译你的dll后你的一些导入表的api的dll本来是kernel32.dll的会变成api-min-xxxxx.dll 这会导致很多问题,**比如沙箱解析、和内存注入失败** ## 为什么会存在这个机制 微软目标是将“API”功能(堆分配、字符串操作等)与子系统实现(枚举进程、注册服务等)分离,因此使用ApiSetMap机制,准备分离这些api. 但是写到一半估计是不想继续写了,于是烂尾了.然后导致各种api-ms-xxxxx丢失 ## 解析 详细解析可以在先知社区查看: https://xz.aliyun.com/t/7019 对于沙箱,我用如下代码解析这个东西: ```cpp /* 解决掉api-ms-xxxxx */ typedef enum _WinVer { WINVER_7 = 0x0610, WINVER_7_SP1 = 0x0611, WINVER_8 = 0x0620, WINVER_81 = 0x0630, WINVER_10 = 0x0A00, WINVER_10_RS1 = 0x0A01, // Anniversary update WINVER_10_RS2 = 0x0A02, // Creators update WINVER_10_RS3 = 0x0A03, // Fall creators update WINVER_10_RS4 = 0x0A04, // Spring creators update WINVER_10_RS5 = 0x0A05, // October 2018 update WINVER_10_19H1 = 0x0A06, // May 2019 update 19H1 WINVER_10_19H2 = 0x0A07, // November 2019 update 19H2 WINVER_10_20H1 = 0x0A08, // April 2020 update 20H1 } WinVer; std::string get_dll_name_from_api_set_map(const std::string& api_set) { std::wstring wapi_set(api_set.begin(), api_set.end()); typedef LONG(__stdcall* fnRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation); fnRtlGetVersion pRtlGetVersion = (fnRtlGetVersion)GetProcAddress(LoadLibraryA("ntdll.dll"), "RtlGetVersion"); RTL_OSVERSIONINFOEXW verInfo = { 0 }; verInfo.dwOSVersionInfoSize = sizeof(verInfo); pRtlGetVersion((PRTL_OSVERSIONINFOW)&verInfo); ULONG ver_short = (verInfo.dwMajorVersion << 8) | (verInfo.dwMinorVersion << 4) | verInfo.wServicePackMajor; if (ver_short >= WINVER_10) { auto apiSetMap = (API_SET_NAMESPACE_ARRAY_10*)((X64PEB*)__readgsqword(0x60))->ApiSetMap; auto apiSetMapAsNumber = reinterpret_cast(apiSetMap); auto nsEntry = reinterpret_cast((apiSetMap->Start + apiSetMapAsNumber)); for (ULONG i = 0; i < apiSetMap->Count; i++) { UNICODE_STRING nameString, valueString; nameString.MaximumLength = static_cast(nsEntry->NameLength); nameString.Length = static_cast(nsEntry->NameLength); nameString.Buffer = reinterpret_cast(apiSetMapAsNumber + nsEntry->NameOffset); std::wstring name = std::wstring(nameString.Buffer, nameString.Length / sizeof(WCHAR)) + L".dll"; if (_wcsicmp(wapi_set.c_str(), name.c_str()) == 0) { auto valueEntry = reinterpret_cast(apiSetMapAsNumber + nsEntry->ValueOffset); if (nsEntry->ValueCount == 0) return ""; valueString.Buffer = reinterpret_cast(apiSetMapAsNumber + valueEntry->ValueOffset); valueString.MaximumLength = static_cast(valueEntry->ValueLength); valueString.Length = static_cast(valueEntry->ValueLength); auto value = std::wstring(valueString.Buffer, valueString.Length / sizeof(WCHAR)); //note: there might be more than one value, but we will just return the first one.. return std::string(value.begin(), value.end()); } nsEntry++; } } else { __debugbreak(); } return ""; } ``` 阅读全文 2021-06-07 huoji 0 条评论