11#pragma once
22/* ****************************************************************/ /* *
33 * \file SbieUtil.h
4- * \brief Sbie相关函数, 获取HWID, 获取pdb中变量偏移等
4+ * \brief Sbie相关函数, 获取HWID, 获取pdb中变量偏移等
55 *********************************************************************/
66#include < windows.h>
77#include < string>
8- #include < dbghelp.h>
9-
10- #pragma comment(lib, "dbghelp.lib")
118
129namespace SbieUtil {
10+ // Sandboxie 原始公钥, 特征码
11+ static const uint8_t KphpOriginalPublicKey[] = {
12+ 0x45 , 0x43 , 0x53 , 0x31 , 0x20 , 0x00 , 0x00 , 0x00 , 0x05 , 0x7A , 0x12 , 0x5A , 0xF8 , 0x54 , 0x01 , 0x42 ,
13+ 0xDB , 0x19 , 0x87 , 0xFC , 0xC4 , 0xE3 , 0xD3 , 0x8D , 0x46 , 0x7B , 0x74 , 0x01 , 0x12 , 0xFC , 0x78 , 0xEB ,
14+ 0xEF , 0x7F , 0xF6 , 0xAF , 0x4D , 0x9A , 0x3A , 0xF6 , 0x64 , 0x90 , 0xDB , 0xE3 , 0x48 , 0xAB , 0x3E , 0xA7 ,
15+ 0x2F , 0xC1 , 0x18 , 0x32 , 0xBD , 0x23 , 0x02 , 0x9D , 0x3F , 0xF3 , 0x27 , 0x86 , 0x71 , 0x45 , 0x26 , 0x14 ,
16+ 0x14 , 0xF5 , 0x19 , 0xAA , 0x2D , 0xEE , 0x50 , 0x10
17+ };
18+
1319 // SMBIOS Structure header
1420 typedef struct _dmi_header {
1521 UCHAR type;
@@ -28,7 +34,7 @@ namespace SbieUtil {
2834 UCHAR SMBIOSTableData[1 ];
2935 } RawSMBIOSData;
3036
31- // 将单字节转为 HEX 字符串( 宽字符)
37+ // 将单字节转为 HEX 字符串 ( 宽字符)
3238 wchar_t * hexbyte (UCHAR b, wchar_t * ptr)
3339 {
3440 static const wchar_t * digits = L" 0123456789ABCDEF" ;
@@ -37,12 +43,12 @@ namespace SbieUtil {
3743 return ptr;
3844 }
3945
40- // 获取固件UUID, 成功返回 TRUE
46+ // 获取固件UUID, 成功返回 TRUE
4147 BOOL GetFwUuid (UCHAR * uuid)
4248 {
4349 BOOL result = FALSE ;
4450
45- // 第一次调用获取所需缓冲大小
51+ // 第一次调用获取所需缓冲大小
4652 UINT bufferSize = GetSystemFirmwareTable (' RSMB' , 0 , NULL , 0 );
4753 if (bufferSize == 0 )
4854 return FALSE ;
@@ -68,7 +74,7 @@ namespace SbieUtil {
6874 // Type 0x01 = System Information
6975 if (h->type == 0x01 && h->length >= 0x19 )
7076 {
71- UCHAR * uuidField = data + 0x08 ; // UUID 偏移
77+ UCHAR * uuidField = data + 0x08 ; // UUID ƫ��
7278
7379 BOOL all_zero = TRUE , all_one = TRUE ;
7480 for (int i = 0 ; i < 16 && (all_zero || all_one); i++)
@@ -79,7 +85,7 @@ namespace SbieUtil {
7985
8086 if (!all_zero && !all_one)
8187 {
82- // SMBIOS 2.6+ UUID 前3个字段是小端
88+ // SMBIOS 2.6+ UUID 前3个字段是小端
8389 uuid[0 ] = uuidField[3 ];
8490 uuid[1 ] = uuidField[2 ];
8591 uuid[2 ] = uuidField[1 ];
@@ -96,9 +102,9 @@ namespace SbieUtil {
96102 break ;
97103 }
98104
99- // 跳过 formatted area
105+ // 跳过 formatted area
100106 UCHAR * next = data + h->length ;
101- // 跳过 unformatted strings 区域( 以 0x0000 结束)
107+ // 跳过 unformatted strings 区域 ( 以 0x0000 结束)
102108 while (next < smb->SMBIOSTableData + smb->Length &&
103109 (next[0 ] != 0 || next[1 ] != 0 ))
104110 next++;
@@ -110,7 +116,7 @@ namespace SbieUtil {
110116 return result;
111117 }
112118
113- // 转换 wchar_t* 到 std::string (UTF-8 编码)
119+ // 转换 wchar_t* 到 std::string (UTF-8 编码)
114120 std::string WcharToString (const wchar_t * wstr)
115121 {
116122 if (!wstr) return std::string ();
@@ -123,7 +129,7 @@ namespace SbieUtil {
123129 return str;
124130 }
125131
126- // 初始化并格式化为 UUID 字符串
132+ // 初始化并格式化为 UUID 字符串
127133 std::string InitFwUuid ()
128134 {
129135 wchar_t g_uuid_str[40 ] = { 0 };
@@ -155,62 +161,60 @@ namespace SbieUtil {
155161 }
156162
157163 /* *
158- * @brief 从模块文件 + PDB 中获取符号的模块内偏移.
159- *
160- * @param modulePath 文件路径
161- * @param pdbSearchPath PDB路径
162- * @param symbolName 符号名
163- * @param baseAddress 基址
164- * @return
164+ * @brief 从SbieDrv.sys 扫描 KphpTrustedPublicKey 获取 RVA
165+ *
166+ * @param sbieDrvPath SbieDrv.sys 的用户态文件路径
167+ * @return RVA 偏移, 失败返回 0
165168 */
166- long long GetSymbolOffset (
167- const std::string& modulePath,
168- const std::string& pdbSearchPath,
169- const std::string& symbolName,
170- DWORD64 baseAddress = 0x10000000 )
169+ uint64_t GetKphVerifySignatureOffset (const std::string& sbieDrvPath)
171170 {
172- HANDLE hProcess = GetCurrentProcess ();
173-
174- if (!SymInitialize (hProcess, NULL , FALSE )) {
175- return -1 ;
176- }
177-
178- // 加载模块
179- DWORD64 moduleBase = SymLoadModuleEx (hProcess, NULL ,
180- modulePath.c_str (), NULL , baseAddress, 0 , NULL , 0 );
181-
182- if (!moduleBase) {
183- SymCleanup (hProcess);
184- return -1 ;
171+ std::vector<uint8_t > fileData;
172+ if (!Utils::ReadFileToMem (sbieDrvPath, fileData)) {
173+ std::cerr << " [!] Failed to read: " << sbieDrvPath << std::endl;
174+ return 0 ;
185175 }
176+ if (fileData.size () < sizeof (IMAGE_DOS_HEADER ))
177+ return 0 ;
178+
179+ uint8_t * base = fileData.data ();
180+ size_t fileSize = fileData.size ();
181+ // DOS Header
182+ auto * dosHeader = reinterpret_cast <IMAGE_DOS_HEADER *>(base);
183+ if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE )
184+ return 0 ;
185+ if ((size_t )dosHeader->e_lfanew + sizeof (IMAGE_NT_HEADERS ) > fileSize)
186+ return 0 ;
187+ // NT Headers
188+ auto * ntHeaders = reinterpret_cast <IMAGE_NT_HEADERS *>(base + dosHeader->e_lfanew );
189+ if (ntHeaders->Signature != IMAGE_NT_SIGNATURE )
190+ return 0 ;
191+ // Section Headers
192+ IMAGE_SECTION_HEADER * sections = IMAGE_FIRST_SECTION (ntHeaders);
193+ WORD numSections = ntHeaders->FileHeader .NumberOfSections ;
194+ constexpr size_t patternSize = sizeof (KphpOriginalPublicKey);
195+ for (WORD i = 0 ; i < numSections; i++) {
196+ if ( (memcmp (sections[i].Name , " .data" , 5 ) != 0 ) &&
197+ (memcmp (sections[i].Name , " .rdata" , 6 ) != 0 ) ) {
198+
199+ continue ;
200+ }
186201
187- // 设置符号搜索路径
188- if (!SymSetSearchPath (hProcess, pdbSearchPath.c_str ())) {
189- SymUnloadModule64 (hProcess, moduleBase);
190- SymCleanup (hProcess);
191- return -1 ;
192- }
202+ DWORD rawOffset = sections[i].PointerToRawData ;
203+ DWORD rawSize = sections[i].SizeOfRawData ;
204+ DWORD sectionRva = sections[i].VirtualAddress ;
205+ if (rawOffset + rawSize > fileSize)
206+ continue ;
207+ if (rawSize < patternSize)
208+ continue ;
209+ // 在该段的原始数据中扫描特征码
210+ uint8_t * sectionBase = base + rawOffset;
211+ for (DWORD j = 0 ; j + patternSize <= rawSize; j++) {
212+ if (memcmp (sectionBase + j, KphpOriginalPublicKey, patternSize) == 0 ) {
213+ return static_cast <uint64_t >(sectionRva + j);
214+ }
215+ }
193216
194- // 查找符号
195- BYTE buffer[sizeof (SYMBOL_INFO ) + 512 ];
196- PSYMBOL_INFO symbol = reinterpret_cast <PSYMBOL_INFO >(buffer);
197- ZeroMemory (symbol, sizeof (buffer));
198- symbol->SizeOfStruct = sizeof (SYMBOL_INFO );
199- symbol->MaxNameLen = 512 ;
200-
201- if (!SymFromName (hProcess, symbolName.c_str (), symbol)) {
202- SymUnloadModule64 (hProcess, moduleBase);
203- SymCleanup (hProcess);
204- return -1 ;
205217 }
206-
207- DWORD64 address = symbol->Address ;
208- long long offset = static_cast <long long >(address - moduleBase);
209-
210- // 卸载模块 & 清理
211- SymUnloadModule64 (hProcess, moduleBase);
212- SymCleanup (hProcess);
213-
214- return offset;
215- }
218+ return 0 ;
219+ }
216220}
0 commit comments