当前位置: 首页 > news >正文

使用frida来spawn Fork 的子进程

索引

  • 需求
    • 测试程序
        • 父进程代码
        • 子进程代码
    • x64dbg
        • 插件功能
        • 开始调试
    • frida
    • 运行环境
        • 用到的文件和代码

需求

最近在学基础的Windows逆向知识,遇到个小问题。一个进程使用CreateProcessW创建的进程该如何在启动时附加,我想调试这个子进程启动时运行的函数。

谷歌搜索都给我翻烂了,最后发现还是得用英文搜。比如x64dbg attach child process就出现了这个结果: How to debug child process?

在测试完这个x64dbg插件之后,我想着frida有没有这样的功能,于是也搜索了一下frida hook muti process,也出现了一个方案,说是frida10就已经有了这个功能: Frida hook multiple processes

下面我简单说一下这两种的使用方法

测试程序

先用C++写一个简单的测试程序,用来创建子进程,代码很简单,直接调用CreateProcessW来启动一个子进程

父进程代码
#include <windows.h>
#include <iostream>
#include <stdio.h>int main() {// 定义进程信息结构体PROCESS_INFORMATION pi;// 定义启动信息结构体STARTUPINFO si;// 初始化结构体ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));// Notepad 可执行文件的路径LPCWSTR notepadPath = L"SubProcess.exe";// 文件路径作为命令行参数LPWSTR cmdLine = NULL;DWORD currentProcessId = GetCurrentProcessId();// 创建新进程if (CreateProcessW(notepadPath, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {printf("新进程已成功创建!\n");printf("新进程的进程ID:%d, 当前进程id: %d \n", pi.dwProcessId, currentProcessId);// 可以等待进程结束,或者继续执行其他操作// WaitForSingleObject(pi.hProcess, INFINITE);// 关闭进程和线程句柄CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}else {printf("无法创建新进程。错误代码:%d", GetLastError());}int i = 0;while (true) {i += 1;printf("*************** 父进程id: %d, 第%d次等待 *******************\n", currentProcessId, i);Sleep(2000);}return 0;
}
子进程代码
#include <stdio.h>
#include <windows.h>int main()
{int i = 0;DWORD currentProcessId = GetCurrentProcessId();while (true) {i += 1;printf("############### 子进程id: %d, 第%d次等待 ####################\n", currentProcessId, i);Sleep(3000);}
}

x64dbg

x64dbg是使用插件来附加子进程

插件地址:https://github.com/therealdreg/DbgChild

安装步骤:

  1. 先下载releases下面的文件DbgChild.Beta.10.zip
  2. 解压到x64dbg目录
  3. 打开x64dbg,插件里面就有DbgChild

解压后的目录结构
在这里插入图片描述
复制到x64dbg之后的目录结构
在这里插入图片描述

插件功能

我说一下我用的几个选项的含义
在这里插入图片描述

  1. 主动去触发hook进程创建
  2. 自动hook进程创建,一般选这个就行
  3. 取消hook NTDLL,我看演示的视频在启动子进程的时候都会主动点一次这个,不过下面有个自动取消hook默认是勾选的,我测试的时候不点这个也可以
  4. 启动监听程序,这个是必须的,且要在创建子进程之前启动
开始调试

勾选第二个选项并启动监听程序,使用x64dbg打开ForkProcess.exe,运行程序,这时候会有一个很长的等待,我开始以为是卡住了,后面发现它只是比较慢,要等个一分钟吧。用任务管理搜索其实SubProcess.exe已经启动了,不知道是哪里卡住了。

接着就会弹出一个新的x64dbg窗口,并且已经附加到了SubProcess了,
在这里插入图片描述
这里不清楚为啥子进程没有在入口断点断住,不过影响不大,因为x64dbg会记忆断点位置,我只需要现在打上断点,那么在下次启动的时候就会自动断下,比如这里在SubProcess的x64dbg程序里用Ctrl+G跳转到printf函数并且打上断点。重复上面的操作重新启动ForkProcess的时候,附加到SubProcess的x64dbg就会断在printf

如果在启动ForkProcess之后再想去附加SubProcess,printf的前几次就无法下断点了。

frida

根据上面搜索到的链接显示,frida10就已经支持这个功能了。不过现在已经frida16了,这里面的代码也不能用了,得看github的最新代码:https://github.com/frida/frida-python/blob/main/examples/child_gating.py

直接拷下来,稍微做点改动,代码比较长,为了方便讲js和Python代码分开

child_gating.py

import threading
import os
import frida
from frida_tools.application import Reactorclass Application:def __init__(self):self._stop_requested = threading.Event()self._reactor = Reactor(run_until_return=lambda reactor: self._stop_requested.wait())self._device = frida.get_local_device()self._sessions = set()self._device.on("child-added", lambda child: self._reactor.schedule(lambda: self._on_child_added(child)))self._device.on("child-removed", lambda child: self._reactor.schedule(lambda: self._on_child_removed(child)))self._device.on("output", lambda pid, fd, data: self._reactor.schedule(lambda: self._on_output(pid, fd, data)))def run(self):self._reactor.schedule(lambda: self._start())self._reactor.run()def _start(self):argv = [r"T:\Code\VisualStudio\ForkProcess\x64\Release\ForkProcess.exe"]env = {}print(f"✔ spawn(argv={argv})")pid = self._device.spawn(argv, env=env, stdio="pipe")self._instrument(pid)def _stop_if_idle(self):if len(self._sessions) == 0:self._stop_requested.set()def _instrument(self, pid):print(f"✔ attach(pid={pid})")session = self._device.attach(pid)session.on("detached", lambda reason: self._reactor.schedule(lambda: self._on_detached(pid, session, reason)))print("✔ enable_child_gating()")session.enable_child_gating()print("✔ create_script()")frida_js_code = self.read_jscode()script = session.create_script(frida_js_code)script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message)))print("✔ load()")script.load()print(f"✔ resume(pid={pid})")self._device.resume(pid)self._sessions.add(session)def read_jscode(self):path = os.path.dirname(os.path.abspath(__file__))file = os.path.join(path, "child_gating.js")with open(file, encoding='utf-8') as f:jscode = f.read()return jscodedef _on_child_added(self, child):print(f"⚡ child_added: {child}")self._instrument(child.pid)def _on_child_removed(self, child):print(f"⚡ child_removed: {child}")def _on_output(self, pid, fd, data):pass#print(f"⚡ output: pid={pid}, fd={fd}, data={repr(data)}")def _on_detached(self, pid, session, reason):print(f"⚡ detached: pid={pid}, reason='{reason}'")self._sessions.remove(session)self._reactor.schedule(self._stop_if_idle, delay=0.5)def _on_message(self, pid, message):if message["type"] == "send":payload = message['payload']s = payload["format_str"] % tuple(payload["format_args"])print(f"⚡ message: pid={pid}, payload={s}")elif message["type"] == "error":print(f"⚡ message: pid={pid}, error: description={message['description']} stack={message['stack']}")else:print(f"⚡ message: pid={pid}, payload={message}")app = Application()
app.run()

child_gating.js

// 根据%读取printf的参数
function vspritf(format_str, args){let printf_args = [];if (format_str.indexOf("%") === -1) {return printf_args;}var pos = 0;for (let index = 0; index < format_str.length; index++) {pos = format_str.indexOf("%", pos);if(pos == -1)break;var format_ch = format_str.substr(pos+1, 1);let length = printf_args.length;let arg;switch (format_ch) {case "s":arg = args[length+1].readAnsiString()break;case "d": arg = args[length+1].toInt32()break;case "p":arg = args[length+1].toInt32()break;case "f":arg = args[length+1]break;default:arg = args[length+1]break;}printf_args.push(arg);pos += index+2;}return printf_args;
}let ProcessModAddress = Process.findModuleByName('ForkProcess.exe');
// Offset是在x64dbg里计算的偏移,
// 本来我想使用Module.findExportByName(null, "printf"),发现得到的偏移不知道是哪里的
let Offset = '0x1070';
// 如果没有获取到ForkProcess,说明是子进程
if(!ProcessModAddress){ProcessModAddress = Process.findModuleByName('SubProcess.exe');Offset = '0x1010';
}
// 通过偏移计算printf的实际地址
let pvPrintf = ProcessModAddress.base.add(Offset);
// 调用Windows获取进程pid的api
let pvGetCurrentProcessId = Module.findExportByName("kernel32.dll", "GetCurrentProcessId")
var GetCurrentProcessId = new NativeFunction(pvGetCurrentProcessId, 'uint32', []);console.log(GetCurrentProcessId(), Offset, pvPrintf)
// hook函数
Interceptor.attach(pvPrintf, {onEnter: function (args) {let format_str = args[0].readAnsiString()send({"format_str": format_str,"format_args": vspritf(format_str, args)})} 
});

运行结果如下:
在这里插入图片描述
这里我只测试了Windows,Linux和安卓应该也可以,官网给的例子是Linux的,安卓的话自行测试

运行环境

  • python==3.8.17
  • frida==16.1.2
  • frida-tools==12.1.3
  • vs2017
用到的文件和代码

https://github.com/kanadeblisst00/frida_child_gating

相关文章:

使用frida来spawn Fork 的子进程

索引 需求测试程序父进程代码子进程代码 x64dbg插件功能开始调试 frida运行环境用到的文件和代码 需求 最近在学基础的Windows逆向知识&#xff0c;遇到个小问题。一个进程使用CreateProcessW创建的进程该如何在启动时附加&#xff0c;我想调试这个子进程启动时运行的函数。 …...

网工笔记整理:策略工具Filter-policy的使用

一、概述 Filter-Policy&#xff08;过滤-策略&#xff09;是一个很常用的路由信息过滤工具&#xff0c;能够对接收、发布、引入的路由进行过滤&#xff0c;可应用于IS-IS、OSPF、BGP等协议。 Filter-policy在距离矢量路由协议中的应用 filter-policy import&#xff1a;不发…...

数据结构和算法——查找算法

目录 线性查找法 二分查找法 插值查找法 斐波那契查找法 线性查找法 可以是有序的&#xff0c;也可以是无序的。 public class SeqSearch {public static void main(String[] args) {int[] arr new int[]{1, 9, 11, -1, 34, 89};int res seqSearch(arr, 34);}public st…...

Blender:对模型着色

Blender&#xff1a;使用立方体制作动漫头像-CSDN博客 上一步已经做了一个头像模型&#xff0c;我做的太丑了&#xff0c;就以这个外星人头像为例 首先切换到着色器编辑器 依次搜索&#xff1a;纹理坐标、映射、分离xyz和颜色渐变 这里的功能也是非常丰富和强大&#xff0c…...

加密市场波动:地缘政治与美股走弱引发不确定性!

伴随着国庆假期的结束&#xff0c;多日波动率维持低位的加密市场也似乎开始苏醒。近期多次突破28000美元未果的比特币&#xff0c;于9日15:00开始从27800美元附近下跌&#xff0c;最低跌至27260美元&#xff0c;同期以太坊也至1550美元左右&#xff0c;创近半个月来新低。 Coin…...

ElementUI编辑表格单元格与查看模式切换的应用

需求&#xff1a;有时候在填写表单的时候&#xff0c;想要在输入的时候是input输入框的状态&#xff0c;但是当鼠标移出输入框失去焦点时&#xff0c;希望是查看的状态&#xff0c;这种场景可以通过 v-if实现 vue2ElementUi里面使用如下&#xff1a; 1.el-table标签注册 cell-…...

spring-创建Webservice服务

Web service是一个平台独立的&#xff0c;松耦合的&#xff0c;自包含的、基于可编程的web的应用程序&#xff0c;可使用开放的XML标准来描述、发布、发现、协调和配置这些应用程序&#xff0c;用于开发分布式的互操作的应用程序。webservice用的是soap协议。 客户通过发送请求…...

Maven系列第3篇:详解maven解决依赖问题

maven系列目标&#xff1a;从入门开始开始掌握一个高级开发所需要的maven技能。 这是maven系列第3篇。 我们先来回顾一下什么是maven&#xff1f; maven是apache软件基金会组织维护的一款自动化构件工具&#xff0c;专注服务于java平台的项目构件和依赖管理。 本文主要内容…...

读书笔记:多Transformer的双向编码器表示法(Bert)-4

多Transformer的双向编码器表示法 Bidirectional Encoder Representations from Transformers&#xff0c;即Bert&#xff1b; 第二部分 探索BERT变体 从本章开始的诸多内容&#xff0c;以理解为目标&#xff0c;着重关注对音频相关的支持&#xff08;如果有的话&#xff09;…...

Stable Diffusion XL搭建

本文参考&#xff1a;Stable Diffusion XL1.0正式发布了&#xff0c;赶紧来尝鲜吧-云海天教程 Stable Diffision最新模型SDXL 1.0使用全教程 - 知乎 1、SDXL与SD的区别 &#xff08;1&#xff09;分辨率得到了提升 原先使用SD生成图片&#xff0c;一般都是生成512*512&…...

面试题-React(十一):性能优化之PureComponent和memo

一、React性能优化的重要性 随着应用的复杂性增加&#xff0c;React组件的渲染可能成为性能瓶颈。频繁的渲染可能导致不必要的性能开销和卡顿。为了确保应用的高性能和流畅用户体验&#xff0c;我们需要采取一些措施来优化组件的渲染。 二、PureComponent-自动浅比较 PureCo…...

<图像处理> Fast角点检测

Fast角点检测 基本原理是使用圆周长为N个像素的圆来判定其圆心像素P是否为角点&#xff0c;如下图所示为圆周长为16个像素的圆&#xff08;半径为3&#xff09;&#xff1b;OpenCV还提供圆周长为12和8个像素的圆来检测角点。 相对中心像素的位置信息 //圆周长为16 static c…...

基于centos、alpine制作Java JDK基础镜像

文章目录 前言一、 简介二、制作JDK/Java基础镜像1.准备事项2.制作Dockerfile脚本2.1.基于centos作为基础镜像2.2.基于alpine作为基础镜像3.构建镜像4.测试验证前言 在日常开发中,但凡项目需要docker容器化部署,制作项目镜像前都需要在Dockerfile中配置Java基础镜像。为什么…...

【AI视野·今日Robot 机器人论文速览 第五十二期】Wed, 11 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 11 Oct 2023 Totally 31 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers RoboHive: A Unified Framework for Robot Learning Authors Vikash Kumar, Rutav Shah, Gaoyue Zhou, Vincent Moens, Vittor…...

hive 知识总结

​编辑 社区公告教程下载分享问答JD 登 录 注册 01 hive 介绍与安装 1 hive介绍与原理分析 Hive是一个基于Hadoop的开源数据仓库工具&#xff0c;用于存储和处理海量结构化数据。它是Facebook 2008年8月开源的一个数据仓库框架&#xff0c;提供了类似于SQL语法的HQL&#xf…...

golang/云原生/Docker/DevOps/K8S/持续 集成/分布式/etcd 教程

3-6个月帮助学员掌握golang后端开发岗位必备技术点 教程时长: 150小时 五大核心专栏,原理源码案例分析项目实战直击工作岗位 golang&#xff1a;解决go语言编程问题 工程组件&#xff1a;解决golang工程化问题 分布式中间件&#xff1a;解决技术栈单一及分布式开发问题 云原生…...

jeecg库login登录过程分析笔记

jeecg库&#xff08;版本jeecg-boot-v3.5.1last&#xff09;实现了用户登录功能&#xff0c;二开时为了借鉴jeecg用户登录的方法&#xff0c;跑了一遍登录方法&#xff1a; org.jeecg.modules.system.controller.LoginController#login 定义这个方法的类的路径是&#xff1a;…...

echarts仪表盘vue

<div class"ybptx" ref"btryzb"></div>mounted() {this.getBtData();},getBtData() {var chart this.$echarts.init(this.$refs.btryzb);var data_czzf 88;var option {series: [{name: 内层数据刻度,type: gauge,radius: 80%,min: 0,max: 1…...

管道和重定向分号-连接符

本文介绍shell脚本常用命令连接符&#xff1a;管道符( | )、重定向( < 、>、>>、2> 、&> )、分号( ; ) 本文内容同微信公众号【凡登】&#xff0c;关注不迷路&#xff0c;学习上高速&#xff0c;欢迎关注共同学习。 1、管道 进程的通信方式之一&#xf…...

WSL VScode连接文件后无法修改(修改报错)

权限问题 usrname:用户名 dirpath:要修改的文件夹路径 sudo chown -R usrname /dirpath...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...