Skip to content

Commit f960be5

Browse files
committed
Fix fail to get KphpTrustedPublicKey's offset
1 parent f7043a9 commit f960be5

2 files changed

Lines changed: 93 additions & 71 deletions

File tree

SbieKernelPatch/SbieUtil.h

Lines changed: 69 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
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

129
namespace 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
}

SbieKernelPatch/main.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,23 @@ int main(int argc, char* argv[])
256256
}
257257
std::cout << "[+] Genrate and write default \'" << CERTIFICATE_FILE << "\' over!" << std::endl;
258258
}
259+
260+
// 提升权限以操作驱动
261+
HANDLE hToken = NULL;
262+
TOKEN_PRIVILEGES priv = { 0 };
263+
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
264+
{
265+
priv.PrivilegeCount = 1;
266+
priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
267+
268+
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid))
269+
AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL);
270+
271+
CloseHandle(hToken);
272+
}
273+
else {
274+
std::cout << "[!] Error: OpenProcessToken Failed!" << std::endl;
275+
}
259276

260277
// 安装/启动EchoDrv驱动
261278
std::string cur_path = Utils::GetCurrentProcessDir();
@@ -326,14 +343,15 @@ int main(int argc, char* argv[])
326343

327344
std::cout << "[+] SbieDrv.sys base address: 0x" << std::hex << SbieDrvBaseAddress << std::dec << std::endl;
328345

329-
// 读取KphpTrustedPublicKey公钥, 利用pdb信息获取变量偏移
330-
std::cout << "[=] Begin get KphpTrustedPublicKey offset from pdb..." << std::endl;
331-
uint64_t KphpTrustedPublicKeyOffset = SbieUtil::GetSymbolOffset(SBIEDRV_NAME, SBIEPDB_NAME, "KphpTrustedPublicKey"),
332-
KphpTrustedPublicKeyAddress = SbieDrvBaseAddress + KphpTrustedPublicKeyOffset;
333-
if (KphpTrustedPublicKeyOffset < 0) {
346+
// 读取KphpTrustedPublicKey公钥, 从文件中特征码匹配获取变量偏移
347+
std::cout << "[=] Begin get KphpTrustedPublicKey offset from file..." << std::endl;
348+
uint64_t KphpTrustedPublicKeyOffsetSigned = SbieUtil::GetKphVerifySignatureOffset(SBIEDRV_NAME);
349+
if (KphpTrustedPublicKeyOffsetSigned == 0) {
334350
std::cout << "[!] Error: GetSymbolOffset KphpTrustedPublicKeyOffset from " << SBIEPDB_NAME << " Failed!" << std::endl;
335351
return -1;
336352
}
353+
uint64_t KphpTrustedPublicKeyOffset = static_cast<uint64_t>(KphpTrustedPublicKeyOffsetSigned),
354+
KphpTrustedPublicKeyAddress = SbieDrvBaseAddress + KphpTrustedPublicKeyOffset;
337355
std::cout << "[+] KphpTrustedPublicKey offset: 0x" << std::hex << KphpTrustedPublicKeyOffset << std::dec << std::endl;
338356

339357
uint8_t KphpTrustedPublicKey[72] = { 0 };
@@ -371,7 +389,7 @@ int main(int argc, char* argv[])
371389
//开始修改SandMan.exe.sig
372390
if (!Utils::FileExists(SANDMAN_SIG_BAK)) {
373391
//备份SandMax.exe.sig
374-
if (rename(SANDMAN_SIG, SANDMAN_SIG_BAK) = 0) {
392+
if (rename(SANDMAN_SIG, SANDMAN_SIG_BAK) != 0) {
375393
std::cout << "[!] Warning: Rename " << SANDMAN_SIG << " to " << SANDMAN_SIG_BAK << " failed!" << std::endl;
376394
}
377395
}

0 commit comments

Comments
 (0)