▒ 目录 ▒
- 🛫 问题
- 描述
- 环境
- 1️⃣ 代码编写
- 开源代码搜索
- 自己撸代码
- procexp确定句柄对应的文件名并过滤
- 2️⃣ PsExec.exe提权
- 定位找不到`EABackgroundService.exe`的问题
- PsExec.exe提权
- PsExec.exe原理
- 🛬 结论
- 📖 参考资料
🛫 问题
描述
由于工作原因,需要对EA平台进行分析,其中一项就是监控文件操作。
本篇文章主要目的是Frida实操应用,如果有更深入的需求,推荐使用ProcMon.exe
,通过各种删选条件进行监控操作。
ps: 对于有些软件,会检测
ProcMon.exe
等各种软件,需要这时候可以使用frida进行监控。
环境
版本号 | 描述 | |
---|---|---|
文章日期 | 2023-05-05 | |
操作系统 | Win11 - 21H2 - 22000.1335 | |
Python | 3.7.1 | |
frida.exe | 15.0.18 | |
1️⃣ 代码编写
开源代码搜索
首先想到的就是找下有没有开源的代码,结果找到一个
https://github.com/nowsecure/frida-fs
,代码下好,编译好了,结果发现,只是个文件操作的库。
后来有找了该作者的另一个库
https://github.com/nowsecure/fsmon
,这次看清楚了,支持Android、ios、mac,唯独不支持windows!!!
总之,没有找到合适的监控文件的frida代码。
自己撸代码
文件读写相关的函数有ReadFile、WriteFile、CreateFileW(CreateFileA最终调用的也是CreateFileW)等,我们以
CreateFileW
为例,讲解下frida提供的各种接口及含义。
Module.findExportByName
,根据模块名(“kernel32.dll”)和导出函数名(“CreateFileW”),获取目标函数地址。Interceptor.attach
,执行hook的函数,传递一个目标函数地址和hook后的处理方法集合。onEnter & onLeave
,处理函数集合的两个常见方法,分别代表调用函数前和调用后的处理。
- 对于
onEnter: function (args)
,我们可以查看并修改参数相关值。- 对于
onLeave: function (retval)
,这里我们查看并修改函数返回结果。
完整代码:
const win32 = Process.platform === 'windows';
if (win32) {
Interceptor.attach(Module.findExportByName("kernel32.dll", "ReadFile"), {
onEnter: function (args) {
const hFile = args[0];
const lpBuffer = args[1];
const nNumberOfBytesToRead = args[2];
const lpNumberOfBytesRead = args[3];
const lpOverlapped = args[4];
console.log(`ReadFile called with hFile: ${hFile}, lpBuffer: ${lpBuffer}, nNumberOfBytesToRead: ${nNumberOfBytesToRead}, lpNumberOfBytesRead: ${lpNumberOfBytesRead}, lpOverlapped: ${lpOverlapped}`);
},
onLeave: function (retval) {
console.log(`ReadFile returned: ${retval}`);
}
});
Interceptor.attach(Module.findExportByName("kernel32.dll", "CreateFileW"), {
onEnter: function(args) {
var fileName = args[0].readUtf16String();
console.log("Opening file: " + fileName);
if (fileName.endsWith('\\IS')) {
// Thread.sleep(5*1000)
}
},
onLeave: function (retval) {
console.log(`Opening returned: ${retval}`);
}
});
Interceptor.attach(Module.findExportByName("kernel32.dll", "WriteFile"), {
onEnter: function(args) {
var fileHandle = args[0];
// console.log("Enter Writing ", fileHandle.toInt32() === 0xbc4);
if (fileHandle.toInt32() === 0xbc4) {
return
}
console.log("Writing " + '0' + " bytes to file handle " + fileHandle);
var buffer = args[1];
var length = args[2];
console.log("Writing " + length + " bytes to file handle " + fileHandle);
},
onLeave: function (retval) {
// console.log(`Writing returned: ${retval}`);
}
});
}
procexp确定句柄对应的文件名并过滤
上述代码执行后,会有大量的日志输出,我们可以通过
fileHandle.toInt32()
过滤我们关心的句柄。
比如,我们不关心frida自己的句柄产生的日志,我们通过procexp
查看frida相关句柄(0xb3c),当fileHandle.toInt32() === 0xb3c
时,直接返回,不再输出日志。
代码如下:
Interceptor.attach(Module.findExportByName("kernel32.dll", "WriteFile"), {
onEnter: function(args) {
var fileHandle = args[0];
// console.log("Enter Writing ", fileHandle.toInt32() === 0xbc4);
if (fileHandle.toInt32() === 0xb3c) {
return
}
2️⃣ PsExec.exe提权
定位找不到EABackgroundService.exe
的问题
代码写完后,发现直接执行frida命令,会提示找不到进程。
排查一圈后,发现EABackgroundService.exe
进程是SYSTEM
权限,frida无权查看该进程。
PsExec.exe提权
很自然的,想到了PsExec.exe,查了资料,发现增加
-i -d -s
这三个参数就能将frida提取为SYSTEM,这三个参数的含义如下:
- -i 运行程序,使其与远程系统上指定会话的桌面进行交互。 如果未指定会话,则进程在控制台会话中运行。 尝试使用重定向的标准 IO) 以交互方式 (运行控制台应用程序时 ,需要 此标志。
- -d 不要等待进程终止 (非交互式) 。
- -s 在系统帐户中运行远程进程。
PsExec.exe原理
PsExec.exe是Sysinternals Suite中的一个工具,它可以在本地或远程计算机上启动进程。它的原理是通过在远程计算机上安装一个服务程序(PsExecSvc.exe),该服务程序允许PsExec.exe在远程计算机上执行命令。
它的提权原理是利用 Windows 系统中的一个名为“服务控制管理器”的组件,该组件可以启动和停止系统服务。
PsExec.exe 利用这个组件启动一个新的服务,该服务的权限可以被设置为 LocalSystem,这是 Windows 系统中最高的权限级别之一。一旦服务被启动,PsExec.exe 就可以在该服务的上下文中启动进程,从而获得了更高的权限。
具体来说,PsExec.exe 的提权过程如下:
- PsExec.exe 启动一个新的服务,该服务的权限可以被设置为 LocalSystem。
- 在该服务的上下文中,PsExec.exe 启动一个新的进程。
- 新的进程继承了服务的权限,因此具有更高的权限。
需要注意的是,使用 PsExec.exe 进行提权需要具有管理员权限。否则,PsExec.exe 将无法启动新的服务。此外,使用 PsExec.exe 进行提权也可能会被杀毒软件视为恶意行为,因此需要谨慎使用。
🛬 结论
EA平台使用了很多技术,如protobuf、rpc、各种加密等,有需要分析的,可以一起探讨。
📖 参考资料
- PsExec.exe下载地址及使用说明 https://learn.microsoft.com/zh-cn/sysinternals/downloads/psexec
ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。