imlk 发表于 2020-4-28 18:00

基于frida的AutoJS加解密工具

本帖最后由 imlk 于 2020-5-15 12:00 编辑

# 📤 autojs-unpacker
项目地址:https://github.com/KB5201314/autojs-unpacker

由于偶然接触到相关的东西,写了一个基于FRIDA的针对AutoJS应用程序的逆向工程工具,顺便练习了一下frida的使用。 它可以解密`project`目录中的js文件,并且支持重新加密,方便调试autojs中的js代码。

## 能力
- 解密单个文件
- 加密单个文件
- 解密/加密项目目录中的所有文件
- 支持将app运行在模拟器中
- [ ] 支持"encryptLevel": 1之外的其它加密
- 增加修改js代码后免重新打包动态加载(实际上是改完js后adb push到相应的/data/data/com.example.pkg/files/project/目录,然后重启应用)

## 要求

- 设备被root(因为frida要求要以root权限启动frida-server)
- 能够运行目标app(只要进程能起来就行,这个工具借助frida来调用目标app中的加密解密函数)
- 建议在Linux环境下使用该工具


## 参数说明:
- `-h` 打印帮助信息
- **`-U` 连接到一个usb设备或者Android官方模拟器(大部分情况下,会需要该参数,否则默认会是选择当前电脑)**
   > 在有多种设备的情况下,你也可以通过其它方式指定目标设备,如用`-D emulator-5554`连接到id为`emulator-5554`的设备。设备id可以用`frida-ls-devices`查看
   > 本工具用于选择设备的参数与`frida-ps`工具相同,具体可看`-h`选项的输出结果
- `-m` 后接字母d表示解密,接e表示加密,l表示热加载替换
- `-p` 指示目标app的包名
- `--if`、`--of` 输入输出文件的路径
- `--id`、`--od` 递归解密/加密project文件夹时,输入文件夹和产生结果的文件夹
- `--isui` 加密单个文件时,指示待加密的是一个拥有ui界面的js文件,具体看这个js文件内容开头是否为`"ui";`,一般来说,app的入口js文件会是个使用ui的js文件(这个在project.json中有指定,一般是main.js,加密时需要给使用到ui界面的文件加上特殊的文件头,否则将以脚本模式解释执行)


## 用法
1-2步是frida环境的搭建过程,frida官方有相关文档(https://frida.re/docs/android/) 网上也有一些别人写的教程,这里我就不啰嗦了简单写一写
**在运行本工具前,请务必确保frida官方提供的工具(如frida-ps之类的)在你的环境中已经能够运行**。

1. 通过pip安装`frida`

   ```shell
   pip install frida
   ```

2. 通过USB将您的android设备连接到计算机,或启动一个Android模拟器,并以root用户启动`frida-server`。
    > frida是一种CS架构,在目标Android机器上运行一个`frida-server`后,本机可以连接到该server,然后借助该server来完成一系列操作。

    首先从(https://github.com/frida/frida/releases)这里下载一个`frida-server`文件,比如我们的目标环境是Android,并且是arm设备,我们就下载一个(https://github.com/frida/frida/releases/download/12.8.20/frida-server-12.8.20-android-arm.xz)
      
    下载完成解压缩重命名成`frida-server`,我们首先在shell中进入该文件所在目录,用adb push到目标机器上

    ```shell
    adb push ./frida-server /data/local/tmp/
    ```

    然后执行:

    ```shell
    adb shell su -c /data/local/tmp/frida-server
    ```

    切记不要关闭当前shell
               
    试一下在本机执行frida提供的工具`frida-ps -U`,如果能看到输出说明环境已经搭建好了。

**下面进入本工具的使用部分**
该工具由`unpacker.py`和`payload.js`两个部分组成,前者负责连接目标机器和处理文件,后者被前者加载到目标机器中负责加密解密。
原理是:
读取待解密的js文件内容,然后借助frida调用待破解的app中存在的解密函数,并将待解密数据作为参数,最后获取解密后的数据保存到本机上方便编辑。
编辑完以后用类似的过程调用加密函数,把改完的js文件加密回去。

3. clone或网页下载本仓库到本机任意目录下,然后在shell中进入该目录

   ```shell
   git clone git@github.com:KB5201314/autojs-unpacker.git
   cd autojs-unpacker
   ```

5. 在本机上解压目标apk(其实我们是想解密apk里`assets/project/`目录下的文件)

6. 在手机上启动目标应用程序,确保它正在运行。

7. 举例解密一个`main.js`:

   ```shell
   ./unpacker.py -U -m d -p com.example.pkg --if ./unzip/assets/project/main.js --of ./src/main.js
   # 解释:
   # ./unpacker.py是脚本的路径
   # -U 表示连接到USB设备或Android官方模拟器,
   # -m d 表示decrypt,解密模式
   # -p com.example.pkg 是指定包名
   # --if ./unzip/assets/project/main.js 是本机上的输入文件路径为./unzip/assets/project/main.js
   # --of ./src/main.js 是指定解密结果输出到本机上的./src/main.js这个路径
   ```

   你将看到这样的输出,说明文件已经被解密到`./src/main.js`:

   ```
    ./unzip/assets/project/main.js -> ./src/main.js               OK
   ```

8. 按照你的意愿对`./src/main.js`的逻辑进行修改
   接下来你可以选择重新加密并替换掉apk中问文件,或者使用本工具的hot load功能将你所做的修改快速应用到app中,下面将分别举例这两种模型:

**重新打包apk**
8. 重新加密该文件:加密`./src/main.js`,输出文件为`./en/main.js`

   ```shell
   ./unpacker.py -U -m e -p com.example.pkg --if ./src/main.js --of ./en/main.js --isui
   # 模式改成e, 即encrypt,加密模式
   # 由于该文件是使用ui界面的js文件,它有一个独特的文件头,加密时请指定参数--isui
   ```

   你将看到这样的输出,说明加密成功:

   ```
    ./src/main.js -> ./en/main.js         OK
   ```

9. 替换apk中的文件:

   用任意压缩工具打开原始apk,将你修改过且重新加密后的文件替换掉对应的原js文件

10. 对修改后的apk文件重新签名,安装运行

**不打包apk,直接hot load到设备中看效果**
8. 假设你已经对`./src/main.js`做了修改,可以使用该工具热加载到目标设备中

   原理:
   首次启动目标app后,会在`/data/data/com.example.pkg/files/project/`目录下缓存apk中的js文件,该工具通过替换这里的缓存文件来完成热加载。不需要重新打包安装即可快速看到效果。
   

   同样由于该原理限制,这种修改是临时的,不会对apk造成修改,而且在对目标app执行`清除数据`的操作后可以消除热加载产生的修改

   使用前,请额外注意下面关于`--of`选项的含义

   ```shell
   ./unpacker.py -U -m l -p com.example.pkg --if ./src/main.js --of main.js --isui   # 模式改成l, 即hot load,热加载
   # --if 指定修改后的明文js文件(未加密的文件)
   # --of 指示替换到哪个位置下。需要注意这里的位置是相对于project目录的位置,比如你想要替换掉apk中的assets/project/main.js这个文件,那么你应该指定参数--of main.js
   # 由于该文件是使用ui界面的js文件,它有一个独特的文件头,加密时请指定参数--isui
   ```
   
   你将看到这样的输出,并且目标app会自动重启,说明热加载替换成功:

   ```
    ./src/main.js -> (data)main.js         OK
    com.example.pkgOK
   ```

## 后续待改进及一些想法
(因为暂时不需要,应该不会去做了,欢迎提pr):
- 支持"encryptLevel": 1之外的其它加密

代码很简单,适合用来学习frida工具的编写。
如果喜欢该项目或者帮到了你,欢迎给star或者帮忙提交pull request实现后面的这些想法。


xben 发表于 2020-4-29 19:08

本帖最后由 xben 于 2020-4-29 19:14 编辑

报错
assets\project\crack.js -> src\crack.jsTraceback (most recent call last):
File "unpacker.py", line 121, in <module>
    decrypt_file(src_file, des_file)
File "unpacker.py", line 76, in decrypt_file
    bs_new = script.exports.decrypt(bs)
File "D:\Program Files\python\lib\site-packages\frida\core.py", line 401, in method
    return script._rpc_request('call', js_name, args, **kwargs)
File "D:\Program Files\python\lib\site-packages\frida\core.py", line 26, in wrapper
    return f(*args, **kwargs)
File "D:\Program Files\python\lib\site-packages\frida\core.py", line 333, in _rpc_request
    raise result
frida.core.RPCException: Error: javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
    at frida/node_modules/frida-java-bridge/lib/env.js:124
    at frida/node_modules/frida-java-bridge/lib/class-factory.js:1556
    at /script1.js:25
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at frida/node_modules/frida-java-bridge/index.js:389
    at frida/node_modules/frida-java-bridge/index.js:338
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at /_java.js:2916
    at frida/node_modules/frida-java-bridge/index.js:307

a634085832 发表于 2020-5-12 22:39

本帖最后由 a634085832 于 2020-5-13 08:53 编辑


运行报这个错
C:/Users/hokoory/Desktop/autojs-unpacker-master/main.js -> C:/Users/hokoory/Desktop/autojs-unpacker-master/main1.jsbs
Traceback (most recent call last):
File "C:/Users/hokoory/Desktop/autojs-unpacker-master/unpacker.py", line 96, in _start
    self.decrypt_file(self.options.input_file, self.options.output_file)
File "C:/Users/hokoory/Desktop/autojs-unpacker-master/unpacker.py", line 148, in decrypt_file
    bs_new = self.script.exports.decrypt(bs)
File "C:\Users\hokoory\AppData\Local\Programs\Python\Python37\lib\site-packages\frida\core.py", line 401, in method
    return script._rpc_request('call', js_name, args, **kwargs)
File "C:\Users\hokoory\AppData\Local\Programs\Python\Python37\lib\site-packages\frida\core.py", line 26, in wrapper
    return f(*args, **kwargs)
File "C:\Users\hokoory\AppData\Local\Programs\Python\Python37\lib\site-packages\frida\core.py", line 333, in _rpc_request
    raise result
frida.core.RPCException: Error: java.lang.NoSuchFieldException: Companion
    at frida/node_modules/frida-java-bridge/lib/env.js:124
    at frida/node_modules/frida-java-bridge/lib/class-factory.js:1037
    at /script1.js:21
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at frida/node_modules/frida-java-bridge/index.js:389
    at frida/node_modules/frida-java-bridge/index.js:340
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at /_java.js:2916
    at frida/node_modules/frida-java-bridge/index.js:307
Error: java.lang.NoSuchFieldException: Companion
    at frida/node_modules/frida-java-bridge/lib/env.js:124
    at frida/node_modules/frida-java-bridge/lib/class-factory.js:1037
    at /script1.js:21
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at frida/node_modules/frida-java-bridge/index.js:389
    at frida/node_modules/frida-java-bridge/index.js:340
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at /_java.js:2916
    at frida/node_modules/frida-java-bridge/index.js:307


蔡庄 发表于 2020-4-28 18:23

大佬,可以帮我解密几个文件吗,手机没ROOT{:1_907:}

zcsllin 发表于 2020-4-28 21:20

潋凌努力变优秀 发表于 2020-4-28 21:48

唉~ 实在是看不懂,“在本机上解压apk,取出assets目录下的project目录。通过此工具可以解密其中的js文件,……”,既然这样为什么还要在手机安装目标APK,我混乱了……

imlk 发表于 2020-4-29 00:26

潋凌努力变优秀 发表于 2020-4-28 21:48
唉~ 实在是看不懂,“在本机上解压apk,取出assets目录下的project目录。通过此工具可以解密其中的js文件, ...

在目标手机上安装APK是因为要用frida去调用apk里的加密和解密函数

you74222 发表于 2020-4-29 08:17

可以做个视频吗?方便学习:)

netxboy 发表于 2020-4-29 11:44

不太懂,能做何用呢。。

jerry828 发表于 2020-4-29 14:08

学习学习!!

z5487693 发表于 2020-4-29 17:53

好东西收藏一波
页: [1] 2 3 4
查看完整版本: 基于frida的AutoJS加解密工具