利用映像劫持(IFEO)实现特定进程运行参数检查
謬紗特
2024年07月20日 14:54

前几天水群看到群友有个需求:禁止 chrome 带 --no-sandbox 启动

马上就想到了利用 IFEO 劫持 chrome.exe,先执行自己的checker 再决定是否继续执行

直接演示一下 IFEO Debugger 的作用

在注册表 `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options` 添加项 `chrome.exe` ,再对此项添加 `Debugger` 字符串值,数据设置为我的 `Demo.exe` ,如图

专栏没代码块,辣鸡

func main() {

for _, arg := range os.Args { println(arg) } }

此时执行 `./chrome.exe --no-sandbox` 得到的输出是

可以看到第一个参数是 Debug 目标(通过 $PATH 执行的话不是绝对路径),之后的就是原本要传给 chrome 的参数

程序实现

func main() {

// 为了避免通过 $PATH 执行的时候找不到位置 // 直接默认 checker 与目标程序在同一目录     // 获取本体可执行文件所在目录     d, err := os.Executable()     if err != nil {         panic(err)     }     xDir := filepath.Dir(d) // 拼接原程序绝对路径 // $PATH 调用有可能不存在 .exe 后缀     origProg := filepath.Base(os.Args[1])     origName := strings.TrimSuffix(origProg, ".exe")     origPath := filepath.Join(xDir, origName+".exe")     args := os.Args[2:] // 除去自身和 debug 目标 filters := []string{"--no-sandbox", "--disable-web-security"}     foundFilteredArgs := make([]string, 0)     for _, arg := range args {         for _, filter := range filters { // 全部 ToLower 再比较,大小写不敏感             arg = strings.ToLower(arg)             filter = strings.ToLower(filter)             if arg == filter {                 foundFilteredArgs = append(foundFilteredArgs, arg)             }         }     } if len(foundFilteredArgs) != 0 { // do anything... ppid := syscall.Getppid() // 父进程 PID fmt.Println("ppid:", ppid) fmt.Println("foundFilteredArgs:", foundFilteredArgs) } else { // 因为目标程序已经被 IFEO 劫持到本体了 // 所以现在肯定不能直接运行原程序 // 方案1: 原地创建原程序的副本,小部分程序不适用 // 方案2: 临时移除 IFEO Debugger 完事加回去,需要注意权限问题 // 演示前者 copyPath := filepath.Join(xDir, origName+"_copy"+".exe") _ = copyFile(origPath, copyPath) cmd := exec.Command(copyPath, args...) cmd.Start() // Start() 是异步, Run() 会阻塞 } }

程序目的只是为了防止手贱,有防病毒需求的还是找杀软