1. 前言
- 目标:使用VSCode”调试“frida脚本
- 环境
- 设备:Pixel 3 Android9 180720.030
- frida:14.2.6
- Node.js:14.15.4
- npm:6.14.10
- Visual Studio Code 1.52.1 (user setup)
- VSCode使用的是IntelliJ IDEA Keybindings
- 2021/1/31
我们使用TypeScript
编写frida脚本,再通过frida-compile
把TypeScript
编译成JavaScript
代码。
- 使用
TypeScript
的好处
- 自动补全
- 类型检查
- 内联文档
- 重构工具
- ......
首先介绍搭建TypeScript
调试环境,再具体介绍Frida调试环境的配置
2. 搭建TypeScript调试环境
2.1 搭建TypeScript开发环境
2.1.1 安装Node.js和npm
Node.js下载
https://nodejs.org/en/download/
npm和Node.js是捆绑在一起的
配置npm
npm使用的默认源(registry
)是https://registry.npmjs.org
,在国外访问很慢,就算挂代理访问也慢,所以直接替换成国内的源http://registry.npm.taobao.org
,操作如下:
得到配置文件路径
npm config get
修改用户配置文件
- 配置文件优先级:
- per-project config file (/path/to/my/project/.npmrc)
- per-user config file (~/.npmrc)
- global config file ($PREFIX/etc/npmrc)
- npm builtin config file (/path/to/npm/npmrc)
2.1.2 建立项目目录
使用以下命令创建项目的目录:
1 2 3 4 | mkdir ts3
cd ts3
mkdir src
mkdir dist
|
建立好的目录如下:
2.1.3 初始化 NPM
在项目的根目录下,执行下面的命令:
现在项目结构如下:
1 2 3 4 | ts3
├─dist
└─src
└─package.json
|
package.json介绍
2.1.4 安装TypeScript
在项目的根目录下,执行下面的命令:
1 | npm install - g typescript
|
加了参数-g
,会在全局环境安装TypeScript
,不加只会在当前工程下安装TypeScript
2.1.5 创建并配置tsconfig.json
在项目的根目录下,执行下面的命令:
现在项目结构如下:
1 2 3 4 5 | ts3
├─dist
└─src
└─package.json
└─tsconfig.json
|
tsconfig.json介绍
在 tsconfig.json
中取消下面属性项的注释,并修改其属性的值:
这样设置之后,我们在 ./src
中编码 .ts
文件,.ts
文件编译成 .js
后,输出到 ./dist
中。
1 2 | "outDir" : "./dist" ,
"rootDir" : "./src" ,
|
2.1.6 Hello TypeScript
将下面代码复制到./src/index.ts
中:
1 2 | const hello: string = 'hello, Genliese' ;
console.log(hello);
|
在项目的根目录下,执行下面的命令:
tsc
是编译命令,详情查看:https://www.tslang.cn/docs/handbook/typescript-in-5-minutes.html
tsc
的编译选项,详情查看:https://www.tslang.cn/docs/handbook/compiler-options.html
1 2 3 4 | / / 编译
tsc
/ / 执行
node . / dist / index.js
|
执行结果如下:
2.1.7 使用自动实时编译
手动编译还是比较麻烦,如果能够保存代码后,能自动编译就好了。
详情查看:https://go.microsoft.com/fwlink/?LinkId=733558
Ctrl + F9
运行构建任务,将显示以下选项:
选择 tsc: watch - tsconfig.json
,回车运行之后,编辑的代码保存之后,就会自动编译。
2.2 代码检查
代码检查主要是用来发现代码错误和统一代码风格。
详情查看:https://ts.xcatliu.com/engineering/lint.html
2.2.1 安装ESLint
ESLint
可以安装在当前项目中或全局环境下,因为代码检查是项目的重要组成部分,所以我们一般会将它安装在当前项目中(也可以安装在全局,因为package.json
中记录有依赖库,别人下载项目后,直接npm install
即可安装所有依赖库)。可以运行下面的脚本来安装:
1 | npm install eslint - - save - dev
|
由于 ESLint
默认使用 Espree
进行语法解析,无法识别 TypeScript
的一些语法,故我们需要安装 typescript-eslint-parser
,替代掉默认的解析器,别忘了同时安装 typescript
:
1 | npm install typescript typescript - eslint - parser - - save - dev
|
由于 typescript-eslint-parser
对一部分 ESLint
规则支持性不好,故我们需要安装 eslint-plugin-typescript
,弥补一些支持性不好的规则。
1 | npm install eslint - plugin - typescript - - save - dev
|
现在项目结构如下:
1 2 3 4 5 6 7 | ts3
├─dist
└─node_modules
└─src
└─package - lock.json
└─package.json
└─tsconfig.json
|
package-lock.json是锁定依赖库的版本
package-lock.json介绍
2.2.2 创建配置文件 .eslintrc.js
ESLint
需要一个配置文件来决定对哪些规则进行检查,配置文件的名称一般是 .eslintrc.js
或 .eslintrc.json
。
当运行 ESLint
的时候检查一个文件的时候,它会首先尝试读取该文件的目录下的配置文件,然后再一级一级往上查找,将所找到的配置合并起来,作为当前被检查文件的配置。
在项目的根目录下,执行下面的命令:
1 2 | / / 创建配置文件
. / node_modules / . bin / eslint - - init
|
按需求,选择相应的选项:
图中出现了WARN
,编辑package.json
修改对应字段:
1 2 3 4 5 | "description" : "default" ,
"repository" : {
"type" : "git" ,
"url" : "none"
},
|
现在项目结构如下:
1 2 3 4 5 6 7 8 | ts3
├─dist
└─node_modules
└─src
└─.eslintrc.js
└─package - lock.json
└─package.json
└─tsconfig.json
|
编辑 .eslintrc.js
,增加 parser: 'typescript-eslint-parser',
替换掉默认的解析器,使之识别 TypeScript
的一些语法,如下面所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | module.exports = {
parser: 'typescript-eslint-parser' ,
env: {
es6: true,
node: true,
},
extends: 'airbnb-base' ,
globals : {
Atomics: 'readonly' ,
SharedArrayBuffer: 'readonly' ,
},
parserOptions: {
ecmaVersion: 2018 ,
sourceType: 'module' ,
},
rules: {
},
};
|
2.2.3 在 VSCode中集成ESLint检查
在编辑器中集成 ESLint
检查,可以在开发过程中就发现错误,极大的增加了开发效率。
要在 VSCode
中集成 ESLint
检查,我们需要先安装 ESLint
插件,点击「扩展」按钮,搜索 ESLint
,然后安装即可。
VSCode
中的 ESLint
插件默认是不会检查 .ts
后缀的,需要在「文件 => 首选项 => 设置」中
添加以下配置:
1 2 3 4 5 | {
"eslint.validate" : [
"typescript"
]
}
|
将下面代码复制到./src/index.ts
中:
1 2 3 4 | let num: number = 1 ;
if (num = = 2 ) {
console.log(num);
}
|
现在项目结构如下:
1 2 3 4 5 6 7 8 9 | ts3
├─dist
└─node_modules
└─src
└─index.ts
└─.eslintrc.js
└─package - lock.json
└─package.json
└─tsconfig.json
|
现在编辑器,应该会提示 4
个错误:
我们按照错误提示,修改成正确的代码风格(在错误处按Alt+Enter
):
console.log
一般是在调试阶段使用,发布正式版本时,应该移除。所以这里没有提示红色的致命错误,而是使用了警告。
2.2.4 错误纠正
将下面代码复制到./src/index.ts
中:
1 2 3 4 | import Cat from './Cat' ;
const kitty: Cat = new Cat( 'kitty' );
kitty.say();
|
将下面代码复制到./src/Cat.ts
中:
1 2 3 4 5 6 7 8 9 10 11 | export default class Cat {
private name: string;
constructor(name: string) {
this.name = name;
}
say() {
console.log(this.name);
}
}
|
现在项目结构如下:
1 2 3 4 5 6 7 8 9 10 | ts3
├─dist
└─node_modules
└─src
└─Cat.ts
└─index.ts
└─.eslintrc.js
└─package - lock.json
└─package.json
└─tsconfig.json
|
上述代码复制粘贴,保存之后,会提示这样的错误:
错误1
1 | Unable to resolve path to module './Cat' .eslint[ import / no - unresolved](https: / / github.com / benmosher / eslint - plugin - import / blob / v2. 22.1 / docs / rules / no - unresolved.md)
|
解决办法是使用 eslint-import-resolver-alias
,先安装依赖,执行下面的命令:
1 | npm install eslint - plugin - import eslint - import - resolver - alias - - save - dev
|
然后,在 .eslintrc.js
配置中,编辑成如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | module.exports = {
parser: 'typescript-eslint-parser' ,
env: {
browser: true,
es6: true,
},
extends: 'airbnb-base' ,
globals : {
Atomics: 'readonly' ,
SharedArrayBuffer: 'readonly' ,
},
parserOptions: {
ecmaVersion: 2018 ,
sourceType: 'module' ,
},
rules: {
},
settings: {
/ / import / resolver起的作用
'import/resolver' : {
alias: {
map : [
[ '@' , './src' ],
],
extensions: [ '.ts' ],
},
},
},
};
|
错误2
1 | Missing file extension "ts" for "./Cat" eslint[ import / extensions](https: / / github.com / benmosher / eslint - plugin - import / blob / v2. 22.1 / docs / rules / extensions.md)
|
在 .eslintrc.js
配置中,编辑成如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | module.exports = {
parser: 'typescript-eslint-parser' ,
env: {
browser: true,
es6: true,
},
extends: 'airbnb-base' ,
globals : {
Atomics: 'readonly' ,
SharedArrayBuffer: 'readonly' ,
},
parserOptions: {
ecmaVersion: 2018 ,
sourceType: 'module' ,
},
rules: {
/ / import / extensions起的作用
'import/extensions' : [
2 , / / 0 = off, 1 = warn, 2 = error
'ignorePackages' ,
{
ts: 'never' ,
},
],
},
settings: {
'import/resolver' : {
alias: {
map : [
[ '@' , './src' ],
],
extensions: [ '.ts' ],
},
},
},
};
|
2.3 调试TypeScript
如何 F5
开始调试 TypeScript
,并且还具备断点调试功能,答案是,使用 TS-node
。
详情查看:https://github.com/TypeStrong/ts-node
在项目的根目录下,执行下面的命令:
Run->Add Configuration
然后修改成如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | {
/ / 使用 IntelliSense 了解相关属性。
/ / 悬停以查看现有属性的描述。
/ / 欲了解更多信息,请访问: https: / / go.microsoft.com / fwlink / ?linkid = 830387
"version" : "0.2.0" ,
"configurations" : [
{
"type" : "node" ,
"request" : "launch" ,
"name" : "Launch Program" ,
"runtimeArgs" : [
"-r" ,
"ts-node/register"
],
"args" : [
"${workspaceFolder}/src/index.ts"
]
}
]
}
|
按 F5
开始愉快的调试吧,F9
是添加断点:
如果出现unbound breakpoint
的问题,修改debug.javascript.usePreview
为false即可
3. Frida调试环境的配置
Frida的安装参考Frida官方文档
我们已经搭建好了TypeScript调试环境,下面继续Frida调试环境的配置,可以参考frida-agent-example项目的配置文件。
frida-agent-example的package.json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | {
"name" : "frida-agent-example" ,
"version" : "1.0.0" ,
"description" : "Example Frida agent written in TypeScript" ,
"private" : true,
/ / 入口函数
"main" : "agent/index.ts" ,
/ / 下面的脚本可以用npm run prepare、npm run build和npm run prepar watch运行
"scripts" : {
"prepare" : "npm run build" ,
"build" : "frida-compile agent/index.ts -o _agent.js -c" ,
"watch" : "frida-compile agent/index.ts -o _agent.js -w"
},
/ / 依赖库,可以在项目根目录用npm install进行安装
"devDependencies" : {
"@types/frida-gum" : "^16.2.0" ,
"@types/node" : "^14.14.10" ,
"frida-compile" : "^10.0.0"
}
}
|
也就是我们可以需要将以下内容拷贝到自己的package.json
文件中,然后在项目根目录下执行npm install
安装下面的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | {
/ / 下面的脚本可以用npm run prepare、npm run build和npm run prepar watch运行
"scripts" : {
"prepare" : "npm run build" ,
"build" : "frida-compile src/index.ts -o dist/index.js -c" ,
"watch" : "frida-compile src/index.ts -o dist/index.js -w"
},
/ / 依赖库,可以在项目根目录用npm install进行安装
"devDependencies" : {
"@types/frida-gum" : "^16.2.0" ,
"@types/node" : "^14.14.10" ,
"frida-compile" : "^10.0.0"
}
}
|
4. 开始调试Frida脚本
注意点
- 没有找到方法直接用VSCode进行附加调试,而是用chrome的DelTools工具进行的附加调试,用vscode编写
TypeScript
语言的Frida代码,并结合实时编译、DelTools工具自动监测脚本是否修改和Frida自动监测脚本是否修改的特性,可以达到比较理性的调试效果
- 没有找到方法直接用VSCode进行附加调试,而是用chrome的DelTools工具进行的附加调试,用vscode编写
TypeScript
语言的Frida代码,并结合实时编译、DelTools工具自动监测脚本是否修改和Frida自动监测脚本是否修改的特性,可以达到比较理性的调试效果
- 实时编译:通过
frida-compile src/index.ts -o dist/index.js -w
命令可以实时把成TypeScript
编译成JavaScript
代码
- DelTools工具自动监测脚本是否修改:如果修改了,自动更新被调试的脚本
- Frida自动监测脚本是否修改:如果修改了,注入的脚本也会跟着修改
1.开启实时编译
Ctrl+F9
选择npm: watch
2.启动frida-server
3.注入脚本
.\frida.exe -U -f com.android.chrome --debug --runtime=v8 --no-pause -l "...\ts3\dist\index.js"
监听端口为本地的9229
4.chrome的DelTools工具进行附加调试
打开chrome,输入chrome://inspect
添加连接——本地端口9229
在Sources
界面,Ctrl+P
选择要调试的脚本
格式化脚本
格式化前
格式化后
5.Ctrl+B下断点
6.vscode修改脚本
实时编译
DelTools工具自动监测脚本是否修改
Frida自动监测脚本是否修改
5. 问题记录
5.1 pycharm调试frida脚本
参考正确配置 Visual Studio Code 开发和调试 TypeScript中用pycharm调试frida脚本,PyCharm给js文件和ts文件下断点都没有反应,不知道是为什么
5.2 chrome的DelTools工具显示不出来文件
如果chrome的DelTools工具显示不出来文件,那么点击Configure
配置,Enable port forwarding
,然后再取消
5.3 chrome的DelTools工具显示的脚本名是script1
这是因为你用api的方式注入的脚本,是直接用变量输入的code,没有文件名,所以chrome默认取名为script1
5.4 get_usb_device有时候会找不到设备 device not found
加延迟就行了get_usb_device(10)
5.5 如果frida注入脚本,导致app退出,可以尝试重启手机
6. 参考
正确配置 Visual Studio Code 开发和调试 TypeScript
FRIDA 使用经验交流分享
7. 附件
工程文件:
链接:https://pan.baidu.com/s/18qlGc1OFSOu4Y29mEmQY3g
提取码:abco
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2021-2-2 20:16
被genliese编辑
,原因: