滥用合法驱动的艺术
本文首发于先知社区 https://xz.aliyun.com/news/92398 在红队行动的过程中越来越多的Windows机器开启了PPL并且安装了EDR,在用户态下直接对lsass进程的内存读取几乎变的不可能,我看完了世界上所有关于dump lsass的相关的技术,可以确定之前的技术在现代防御全开的机器下基本上都已经全部失效,本文将通过滥用合法驱动直接读取lsass的物理内存轻松绕过了PPL,顺便吊打所有EDR,完整的代码已经上传Github,为保证大部分读者阅读体验,快速补充相关的windows机制基础知识。 PPL的机制 PPL的全程是Protected Process Light(Windows进程保护等级),微软最初为了版权的控制设计的机制,现在拿来保护lsass进程不被用户态下的任意进程读取内存,即使你具备最高的管理员或者System权限依然无法读取被PPL保护起来的内存。 PPL的本质是进程在内核空间维护的数据,这个数据叫做_EPROCESS,里面有一个Protection,不同内部结构在_EPROCESS偏移不同,完整结构见文档,这个标志位是在进程创建开始的时候指定的,并且需要系统特定的签名证书才能成功设置 struct _EPROCESS { struct _KPROCESS Pcb; //0x0 struct _EX_PUSH_LOCK ProcessLock; //0x1c8 VOID* UniqueProcessId; //0x1d0 struct _LIST_ENTRY ActiveProcessLinks; //0x1d8 struct _EX_RUNDOWN_REF RundownProtect; //0x1e8 ...... struct _PS_PROTECTION Protection; //0x5fa //这个Protection就是我们控制的 这个数据的类型为_PS_PROTECTION,名字叫Level,Level保存着三个变量 //0x1 bytes (sizeof) struct _PS_PROTECTION { union { UCHAR Level; //0x0 struct { UCHAR Type:3; //0x0 UCHAR Audit:1; //0x0 UCHAR Signer:4; //0x0 }; }; }; 分别是Signer、Audit、Type,一个bytes里面有8bit,如下放置 bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 Signer(4 bits) | Audit(1 bit) | Type(3 bits) 不同的PPL进程也有自己的访问控制,在同一Type下比较时,Signe数值通常越大,代表信任/保护等级越高,观察到windows defender的组件是的保护等级是Light (Antimalware),系统核心进程的保护等级是Light (Windows)或者Light (winTcb) 从高到低,意味着系统进程可以访问windows defender的进程,而windows defender在Light (Antimalware)等级,意味着即使defender被漏洞等其他原因exploit了也无法访问比自己更高的保护等级 常规的安全软件的核心PPL进程被C:\Windows\System32\services.exe托管,着意味着第三方的组件的父进程都将被services拉起,这是合理的,因为即使是带签名的杀毒本身也无法直接拉起PPL进程,services在系统启动的那一刻就已经运行,具备受信任的能力被所有的杀毒/EDR组件托管,EDR安装时候向服务发起请求,托管到服务中,系统服务代劳核心PPL保护进程的启动 请注意,PPL只是保护等级,windows ACL依然生效,意味着如果一个进程PPL等级是普通用户进程,它在访问system进程的时候依然需要通过windows权限校验,结果显而易见是失败的。 Windows的虚拟内存和物理内存 现代64位的windows系统,每个进程都拥有自己独立的虚拟内存空间,所以不同进程之间写入同一个虚拟地址不会互相干扰。 ...