APP逆向必备(反编译hook算法)

day03 逆向必备

目标:了解app逆向的流程和必要的环境准备。

课堂随笔

day03 逆向必备

今日概要:
    - 安装运行
    - 抓包分析
    - **反编译apk**
    - **在Java代码中定位 + Hook校验**
    - **基于Python还原算法**

1.反编译apk
    - 简单APP,抓包 + 模拟发送(臧航+爱安丘)
    - 复杂APP,抓包动态(车智赢)  APK -> Java代码

    1.1 反编译工具
        jadx(推荐)、JEB、GDA、MT管理

    1.2 依赖jre(推荐jdk【jre+其他】)
        - jre,普通用户想要运行java程序写的工具
        - jdk,开发人员,写代码时类库+编译->工具,运行jre
        注意:必须1.8版本

        windows系统:
            - 下载exe文件
            - 安装在你知道的目录(不要有中文、不要用有空格)
                D:\soft\jdk
                    - bin
                        - java.exe   类似Python.exe
                    ...
            - 系统环境变量 D:\soft\jdk\bin\
                >>>java --version

        mac系统:
            - 自带java

    1.3 下载jadx & 解压
        - github:https://github.com/skylot/jadx/releases
        - 网盘
        - 版本:v1.2.0(推荐)

        - D:\coding\jadx\bin\
            - jadx-gui      mac
            - jadx-gui.bat  win
        - 打开

    1.4 反编译apk
        - 成功
        - 失败(有壳)

2.Java代码中定位
    根据抓包抓到的数据,找到一些关键字,去java代码寻找蛛丝马迹。
    - URL定位:/api/axxxx/xxx
    - 直接搜索:pwd  "pwd"   &pwd   pwd=   &pwd=
    - 间接搜索:其他好找
    - Hook搜索:找内存TreeMap,put换成我的put方法 + 调用栈(了解)
        TreeMap obj = new TreeMap();   obj = {}
        obj.put("_appid","123")        obj["_appid"] = "123"
        obj.put("pwd","99")
        obj.put("name","xxxx")


        循环obj,获取键值对
        _appid=123&age=99&pwd=xxxx

    分析:pwd大概率是md5加密(猜测)
        - 数据证明:明文 -> md5算法 -> 密文比对
        - Hook证明+获取相关数据

3.基于frida的Hook

    3.1 电脑安装frida模块
        - Python3.7系统解释器
        - 创建项目 + 基于Python3.7系统创建虚拟环境
        - 安装模块
            pip install frida==16.0.1
            pip install frida-tools==12.0.1

        - 报错
            - 下载egg文件
            - 放在指定目录
            - 再安装

    3.2 手机端
        - adb查看CPU架构
            >>>adb shell getprop ro.product.cpu.abi
        - 下载frida-server
            - 版本:16.0.1
        - 解压并找到解压后的文件,不是文件夹
            - 文件       frida-server-16.0.1-android-arm64
            - 文件夹/文件 frida-server-16.0.1-android-arm64
            注意:可以文件重命名 fd-16.0.1

        - 上传到手机
            >>>adb push ....   /data/local/tmp/

        - 查看 & 赋予可执行权限
            >>>adb shell
            >>>su    ->shell获取ROOT权限
            >>>cd /data/local/tmp/
            >>>ls
            >>>chmod 755 frida-server-16.0.1-android-arm64

    3.3 启动+编写Hook脚本+运行
        - 启动手机上的frida-server
            >>>adb shell
            >>>su
            >>>cd /data/local/tmp/
            >>>./frida-server-16.0.1-android-arm64

        - 端口转发
            >>>adb forward tcp:27042 tcp:27042
            >>>adb forward tcp:27043 tcp:27043

            - 固定脚本,python代码执行上述两条命令

        - 编写Hook脚本+运行(项目+虚拟环境+frida+frida-tools)
            - 固定脚本,查看手机中的进程
            - 固定模板,修改内部Hook脚本

            - 例如:车智赢登录



        问题:
            1.frida-server 和 端口转发 注意次数
            2.端口固定
            3.frida框架:JS方式写Hook   ->  找固定的java替换

    3.4 Hook脚本形式(编写+运行)
        - 基于Python+JavaScript
            - attach,手动app启动 + 运行Hook脚本
            - spawn, 运行Hook脚本:重启APP+HOOK

        - JavaScript + 终端命令(环境frida)
            - attach
            - spawn

4.Python进行算法的还原
    -   固定算法:AES、MD5、DES..
    - 自定义算法:看懂java代码 + 还原

5.实现业务功能
    - 自动登录
    - 自动注册....

## 感受
    1.不懂Java不行呀 【看懂&分析】
    2.算法的还原

1.逆向基本流程

常见app的逆向的基本流程:

  • 安装运行
  • 抓包分析
  • 反编译apk
  • 在Java代码中定位 + Hook校验
  • 基于Python还原算法

2.反编译APK

如果抓包发现一些参数是动态,明显看不出来是什么意思?那就需要反编译得到Java代码,然后再java代码中寻找算法。

例如:车智赢登录

image-20230405112224510

常见的反编译工具:jadx(推荐)、jeb、GDA

  • 反编译工具均依赖 JRE(Java运行环境),安装JDK(包含jre)
  • 下载jadx并解压至任意目录

2.1 jdk

需要在你的电脑上安装Java开发工具包JDK,JDK中包含JRE。

https://www.oracle.com/java/technologies/downloads/

# 请务必安装 JDK8==JDK1.8(后期工具需要)
https://www.oracle.com/java/technologies/downloads/#java8

image-20230110230227775

安装好之后需要配置下环境变量。

image-20210929163956511

image-20210929163410661

关于mac系统,自带JDK:

image-20210929152514354

/Library/Java/JavaVirtualMachines 

image-20210929152444076

2.2 jadx

版本推荐:jadx-1.2.0

  • 直接去官网

    https://github.com/skylot/jadx/releases
    
  • 去课件的网盘
    image-20230110230253664

注意:代码、文件尽量不要让他存在中文路径。

image-20210928184518710

image-20230405113608864

image-20230405113644802

3.定位

image-20230405112224510

在反编译得到的java中,根据抓包得到的关键字,去java代码中寻找指定算法的生成位置。

注意:这个过程需要掌握Java和安卓开发。

常见的可以搜索URL网址 或 参数关键字pwd"pwd"等,也可以搜索其他的关键字。

搜索网址: /tradercloud/sealed/login/login.ashx

image-20230307143438075

image-20230307143404857

image-20230307143422935

image-20230307143549046

4.hook验证

基于frida对代码进行验证,是否当前请求会执行此方法。

4.1 Python系解释器

请在系统解释器中安装Python3.7.9

https://www.python.org/downloads/release/python-379/

如果你现在电脑上只安装了python3.9,也可以再安装一个python3.8,Python支持多版本共存。

然后再用Python3.7.9 创建一个虚拟环境 + 项目,后续逆向课程都在此项目中进行。

image-20230405120229457

4.2 frida==16.0.1【电脑端】

pip install frida==16.0.1
pip install frida-tools==12.0.1

正常情况下,就可以安装成功:

image-20230405120449286

如果你在安装过程中,遇到以下错误,就需要:

  • 下载egg文件并放在指定目录
  • 再次安装 frida和frida-tools

image-20230405120615756

1.下载egg

https://pypi.doubanio.com/simple/frida/

image-20221104181557735

根据:frida版本 + Python版本 + 操作系统 来选择下载响应的egg文件。

2.放入指定目录

image-20230405120900447

在错误提示中有指定egg放置的目录。

3.再次安装

pip install frida==16.0.1
pip install frida-tools==12.0.1

4.3 frida-server【手机端】

1.手机CPU架构

用ADB与手机连接,然后再电脑中终端运行如下命令:

adb shell getprop ro.product.cpu.abi

image-20230405121220229

2.下载frida-server

https://github.com/frida/frida/releases

image-20221104182241472

image-20230405121403091

3.解压&上传到手机

将下载来的压缩包解压得到的 文件 上传到手机的 /data/local/tmp/目录。

注意:一定是解压后的文件,不是文件夹

  • 上传

    >>>adb push C:\soft\frida-server-16.0.1-arm64    /data/local/tmp/
    
  • 赋予可执行权限

    >>>adb shell
    >>>su
    >>>cd /data/local/tmp/
    >>>chmod 755 frida-server-16.0.1-android-arm64
    

4.4 启动和Hook

1.【手机端】frida-server

在手机上运行 /data/local/tmp 目录下的 frida-server-16.0.1-android-arm64

>>>adb shell
>>>su
>>>cd /data/local/tmp
>>>./frida-server-16.0.1-android-arm64

2.【电脑端】Hook

第一步:端口转发

adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043

image-20220301215522568

import subprocess

subprocess.getoutput("adb forward tcp:27042 tcp:27042")
subprocess.getoutput("adb forward tcp:27043 tcp:27043")

第二步:手机运行进程

# 枚举手机上的所有进程 & 前台进程
import frida

# 获取设备信息
rdev = frida.get_remote_device()

# 枚举所有的进程
processes = rdev.enumerate_processes()
for process in processes:
    print(process)

# 获取在前台运行的APP
front_app = rdev.get_frontmost_application()
print(front_app)

第三步:Hook脚本

import frida
import sys

# 连接手机设备
rdev = frida.get_remote_device()

session = rdev.attach("车智赢+")

scr = """
Java.perform(function () {

    // 包.类
    var UserModel = Java.use("com.che168.autotradercloud.user.model.UserModel");
    var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");

    UserModel.loginByPassword.implementation = function(str,str2,str3,responseCallback){
        console.log(str2,str3);
        var res = this.loginByPassword(str,str2,str3,responseCallback);
        return res;
    };

    SecurityUtil.encodeMD5.implementation = function(str){
        console.log("明文:",str);
        var res = this.encodeMD5(str);
        console.log("md5加密结果=",res);
        return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
    }

});
"""

script = session.create_script(scr)


def on_message(message, data):
    print(message, data)


script.on("message", on_message)

script.load()
sys.stdin.read()

4.5 Hook方式

1.Python脚本

  • attach:手动运行app,打开APP后,再运行Hook脚本。

    import frida
    import sys
    
    # 连接手机设备
    rdev = frida.get_remote_device()
    session = rdev.attach("车智赢+")
    
    scr = """
    Java.perform(function () {
        // 包.类
        var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");
        SecurityUtil.encodeMD5.implementation = function(str){
            console.log("明文:",str);
            var res = this.encodeMD5(str);
            console.log("md5加密结果=",res);
            return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
        }
    });
    """
    script = session.create_script(scr)
    def on_message(message, data):
        print(message, data)
    script.on("message", on_message)
    script.load()
    sys.stdin.read()
    
  • spawn,脚本自动重启APP并进行Hook

    import frida
    import sys
    
    rdev = frida.get_remote_device()
    pid = rdev.spawn(["com.che168.autotradercloud"])
    session = rdev.attach(pid)
    
    scr = """
    Java.perform(function () {
        // 包.类
        var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");
        SecurityUtil.encodeMD5.implementation = function(str){
            console.log("明文:",str);
            var res = this.encodeMD5(str);
            console.log("md5加密结果=",res);
            return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
        }
    });
    """
    script = session.create_script(scr)
    
    
    def on_message(message, data):
        print(message, data)
    
    
    script.on("message", on_message)
    script.load()
    rdev.resume(pid)
    sys.stdin.read()
    

2.JavaScript + 命令行

创建一个js文件,例如:demo.js

Java.perform(function () {
    // 包.类
    var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil");
    SecurityUtil.encodeMD5.implementation = function(str){
        console.log("明文:",str);
        var res = this.encodeMD5(str);
        console.log("md5加密结果=",res);
        return "305eb636-eb15-4e24-a29d-9fd60fbc91bf";
    }
});
  • attach,先启动app,然后再在终端执行:

    >>>frida -UF -l demo.js  
    
  • spwan,脚本自动重启APP并进行Hook

    >>>frida -U -f com.che168.autotradercloud -l demo.js
    
    注意:输入q + 再点击回车则退出
    

5.算法还原

将算法逆向出来之后,就要根据Java中的实现,用Python代码实现。

5.1 固定算法

image-20230307143549046

import hashlib

obj = hashlib.md5()
obj.update('密码'.encode('utf-8'))
hex_string = obj.hexdigest()
print(hex_string)

5.2 自定义算法

image-20230405123856208

import random
import string
import base64

def base64_encrypt(data_string):
    data_bytes = bytearray(data_string.encode('utf-8'))
    data_bytes[0] = data_bytes[0] ^ (len(data_bytes) & 0xFF)
    for i in range(1, len(data_bytes)):
        data_bytes[i] = (data_bytes[i - 1] ^ data_bytes[i]) & 0xFF
    res = base64.encodebytes(bytes(data_bytes))
    return res.strip().strip(b"==").decode('utf-8')
posted @ 2023-04-09 19:20  凫弥  阅读(1983)  评论(0编辑  收藏  举报