• 爬虫----记录某新闻详情页app逆向过程(app逆向初学第一次实战)


    仅供学习交流使用,非商业用途,如有侵权,请联系我删除!!!

    直接进入正题:


    1. 使用Charles抓包:

    在这里插入图片描述

    发现请求不能正常返回,返回“数据加载异常,点击屏幕刷新”

    • 这说明我们的抓包环境被识别出来了,解决方法:

      • 服务器可能对我们的证书做了验证,发现是Charles的证书就不给返回

      • 1️⃣ 可以使用xposed框架下的模块来进行绕过ssl证书验证。(简单)

      • 2️⃣ 反编译之后,找到ssl验证的代码,使用Frida进行hook函数来绕过验证。(针对性强)

    果然绕过验证之后,服务器返回了数据,Charles也顺利抓到包。

    在这里插入图片描述


    2. 分析抓包请求

    2.1 搜索接口内容定位请求:

    在这里插入图片描述

    发现只有一个请求内有需要的内容,查看其他数据,发现就是需要的详情内容。

    2.2 多次请求查看参数变化:

    在这里插入图片描述

    查看三次请求,有两次的id是一样的,变化的参数为timestamp和sign

    • 这个id就是新闻的id

    • 这个timestamp不难看出就是一个时间戳

    • 同一个新闻id,时间戳不同sign参数也不同,猜测有可能是根据时间戳以及别的一些参数使用md5(根据经验一看就是md5生成的32位小写加密)方法生成的签名。


    3. 通过jadx-gui反编译app定位加密函数

    因为本次app没有进行加固,所以为了节省时间,省去了查壳和脱壳的部分

    3.1 点击搜索按钮

    在这里插入图片描述

    3.2 直接搜索关键字,发现md5方法,跟进去!!

    在这里插入图片描述

    3.3 追踪加密函数,发现md5就是加密的函数

    在这里插入图片描述

    3.4 发现使用的就是java原本的md5加密方式

    在这里插入图片描述

    现在知道了加密方式,只要使用Frida进行hook md5这个方法,找到加密之前的明文,就可以来进行加密模拟啦~


    4. 使用Frida进行hook函数,得到加密前的明文

    4.1 找到运行中的包

    1. 使用adb在手机端运行frida-server服务器
    2. pc端在打开一个终端窗口,使用frida命令 frida-ps -U
    3. -U的意思为手机设备

    找到了某新闻:

    在这里插入图片描述

    某些程序的包名不是apk的名字,jadx-gui反编译之后可以在资源文件中的AndroidManifest.xml中找到包名:

    在这里插入图片描述
    在这里插入图片描述

    4.2 找到函数的位置

    这个类的md5方法

    com.dingduan.lib_network.interceptor.CommonParamInterceptor
    
    • 1

    hook的含义:

    • 获取到CommonParamInterceptor这个类
    • 这个类的md5方法.implementation的属性 = 一个函数 这个函数就是md5方法 可以修改参数、打印参数、修改返回值中间做一些处理

    hook代码:

    import frida, sys
    
    
    def on_message(message, data):
        print("[%s] => %s" % (message, data))
    
    # 连接usb设备 包名为找到的包名
    session = frida.get_usb_device().attach('xx新闻')
    
    jscode_hook = """
    Java.perform(
    	// 这个函数里面是具体hook的代码
        function(){
            console.log("1. start hook");
            let CommonParamInterceptor = Java.use("com.dingduan.lib_network.interceptor.CommonParamInterceptor");
            CommonParamInterceptor["md5"].implementation = function (text) {
            	// 打印参数
                console.log('md5 is called' + ', ' + 'text: ' + text);
                // 重新制作一个参数返回
                let ret = this.md5(text);
                console.log('md5 ret value is ' + ret);
                return ret;
            };
        }
    )
    """
    
    script = session.create_script(jscode_hook)
    script.on('message', on_message)
    script.load()
    sys.stdin.read()
    
    
    • 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

    4.3 运行frida的hook代码,用手机手动调用一次加密函数

    调用之后发现md5被调用多次,抓包请求,对比生成的sign发现,下面这个跟我们frida生成的sign一样,说明就是这次的参数。

    在这里插入图片描述


    5. 使用python复现代码

    5.1 找到参数多次请求之后分析

    appCurrentVersion=7.6.0app_id=220525165346815301channelPackage=proid=2379399phoneModel=google PixelplatformPublic=AndroidsystemOS=8.1.0timestamp=1660745510b80a5dfbe4f0637ae3179a06fdb5bd3c'
    
    • 1
    • app_id为固定的
    • proid为某个新闻的id
    • timestamo为10位时间戳
    • 时间戳后边跟的一个md5是一个固定值

    把整个字符串拼起来,使用python进行md5加密,发现和生成的sign一致

    5.2 代码:

    import hashlib
    import time
    
    import requests
    
    headers = {
        'User-Agent': 'okhttp/4.9.1',
    }
    my_tk = 'b80a5dfbe4f0637ae3179a06fdb5bd3c'
    timestamp = str(time.time()).split('.')[0]
    news_id = '2379310'
    before_str = f'appCurrentVersion=7.6.0app_id=220525165346815301channelPackage=proid={news_id}phoneModel=google PixelplatformPublic=AndroidsystemOS=8.1.0timestamp={timestamp}{my_tk}'
    
    
    def get_sign(sb1):
        return hashlib.md5(sb1.encode('utf-8')).hexdigest()
    
    
    sign = get_sign(before_str)
    print(sign)
    params = {
        'id': news_id,
        'app_id': '220525165346815301',
        'appCurrentVersion': '7.6.0',
        'platformPublic': 'Android',
        'phoneModel': 'google Pixel',
        'systemOS': '8.1.0',
        'timestamp': timestamp,
        'channelPackage': 'pro',
        'sign': sign,
    }
    url = ''
    response = requests.get(url=url, params=params, headers=headers)
    print(response.json())
    
    
    • 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

    在这里插入图片描述

    🎉🎉🎉

  • 相关阅读:
    python 读取pdf 将每页转成jpg
    Zemax操作40--序列模式中LD光源模拟
    02_SpingBoot 入门案例
    JavaSE---逻辑控制
    提升学生群体中的STEAM教育核心素养
    【36C++STL-常用容器----3、stack容器详解】
    若a,b满足3√a+5|b|=7,则S=2√a-3|b|的取值范围
    C# 随机给一个全部信息都未知的类类型,如何获取该类的类名、属性个数、属性名、属性的数据类型、属性值?
    串行并行数据转换
    初探Vue.js及Vue-Cli
  • 原文地址:https://blog.csdn.net/bjsyc123456/article/details/126391272