秀动APP逆向

2022/6/25 23:20:40

本文主要是介绍秀动APP逆向,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

app下载地址:aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzY2MjI2Mjg=

一:App抓包:这不是重点,直接略过,查看抓包内容

点击查看代码
{
	"appid": "app",
	"aru": "*************",
	"data": "PhPsJe1Ruo/ZZQDg3fJsxdzb+M6mZWXlRt0/AkOCemKy4uMMQGZ8HlyukRvcI96ekwkwTEP4QnYO0/8bhmHwkgVE08BLdPMQ1En7KgIxYSoiB65zh0Uyv2pkXUIT/oHdsyFIBD3Nqu8UVTV8/MVk7p5wdRiA4E14zondKWzZ7yvcOtbw6hXEIlrQvi89ua+8",
	"sign": "5f4637d358d7d93630389e6a46c62097",
	"terminal": "android",
	"version": "5.0.1"
}

抓包多次,由抓包内容可以得出,加密参数为:data和sign,其他的参数都为固定值,不需要分析。此篇只分析首页信息的获取,不涉及详情页。

二:参数点查找
jadx打开apk,此时你会发现app被加固了(360加固),如图展示这样

然后从AndroidMainifest.xml中获取到加密后的入口为android.intent.action.MAIN,废话不多说了,直接Fedx脱壳,步骤略。
说说查找脱壳后的怎么分析哪个dex文件是解密的,简单的查找方式:grep -ril "android.intent.action.MAIN" ./ 能很大程度缩小搜索范围,当然一个一个dex文件分析也可以

根据搜索出来的内容进行重点查找,最后找到


可以看到所有的参数都在这里

三:参数解密
简单分析下sign和data的生成,
d为data,k为sign String d = l.d(str3, str2); String k = g0.k(str2);
由代码可知,重点是参数str2,str3只和data的生成有关,直接frida hook一下

点击查看代码
# -*- coding:utf-8 -*-
  import frida, sys
  hook_params_info = """

  //打印堆栈(固定不会变的)
  function printstack(){
      send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
  }


  Java.perform(
      function(){
          //data的加密  l.d(str3, str2)
          var l = Java.use('f.v.a.j.l');
          l.d.overload('java.lang.String', 'java.lang.String').implementation = function(v1, v2){
              send("this is join!");
              send(v1);
              send(v2);
              var data = l.d(v1, v2);
              send(data);
              return data;
          }
      }
  )


  //打印堆栈(固定不会变的)
  function showStacks() {
          Java.perform(function () {
              send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
          });
      }

  """

  def on_message(message, data):
      if message['type'] == 'send':
          print("[*] {0}".format(message['payload']))
      else:
          print(message)

  process = frida.get_usb_device().attach('com.showstartfans.activity')
  script = process.create_script(hook_params_info)
  script.on('message', on_message)
  script.load()
  sys.stdin.read()

![](https://www.www.weizhi.cc/i/l/?n=22&i=blog/1725755/202206/1725755-20220625172710196-61427278.png) 由图中可以看到打印了两次。是因为计算aru调用了一次,不影响。再次调用一次发现str3为固定值:hiyrLAoWR1k4wwee,同时str2的值也就一个值在变化
点击查看代码
  {"action":"/app/home/front","deviceName":"Nexus 6P","qtime":1656148360681,"query":{"city":"10"},"ranstr":"RJ3GMWID","sysVersion":"6.0.1"}
str的组成更简单,只需要随机生成一个8位的随机值ranstr和时间戳就完成。本文中直接hook代码生成

四:结果展示



点击查看代码

```

# -*- coding:utf-8 -*-

import frida, sys
import time
import requests
import json

rpc_hook_code = """
    rpc.exports = {
        getsign:function(timestamp, activity_id){
            var sig = "";

            Java.perform(
                function(){
                    send("this is join in!");
                    var g0 = Java.use('f.v.a.j.g0');
                    var l = Java.use('f.v.a.j.l');

                    // 获取随机的8位字符串
                    var randomStr = g0.r(8);

                    var str2 = '{"action":"/app/home/front","deviceName":"Nexus 6P","qtime":' 
                        +timestamp+ ',"query":{"city":"10"},"ranstr":"' 
                        +randomStr+ '","sysVersion":"6.0.1"}';
                    //首页为
                    var str3 = 'hiyrLAoWR1k4wwee';

                    //data参数
                    var data = l.d(str3, str2);

                    //sign参数
                    var sign = g0.k(str2);
                    send('data:'+data);
                    send('sign:'+sign);
                    sig = data +'&'+ sign;
                }
            )
            return sig;
        }
    }


    //通用:字符串转为字节数组
    function getBytes(s) {
            var bytes = [];
                for (var i = 0; i < s.length; i++) {
                    bytes.push(s.charCodeAt(i));
                }
            return bytes;
    }
"""


def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


def get_parmas(script):
    timestamp = int(time.time() * 1000)
    activity_id = 172699
    infos = script.exports.getsign(timestamp, activity_id).split('&')
    params = {
        "appid": "app",
        "aru": "axcHZeQPfJz8guxJHFDgkOVRwBM/ZuWdwcRy0yHO0b0=",
        "data": infos[0],
        "sign": infos[1],
        "terminal": "android",
        "version": "5.0.1"
    }
    return params


def get_activity_ids(params):
    """
    获取activity_id
    :return:
    """
    url = "https://pro2-api.showstart.com/app/000000000000"
    headers = {
        'Host': 'pro2-api.showstart.com',
        'user-agent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MTC20L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
        'cterminal': 'android',
        # 'cusystime': '1656134089524',
        'cuuserref': 'b3aeb6664c498e43df6e30f48999989c',
        'cusut': '',
        'content-type': 'application/json;charset=UTF-8'
    }
    activity_infos = requests.post(url, headers=headers, data=json.dumps(params)).json()
    print(activity_infos)
# rpc
process = frida.get_usb_device().attach('com.showstartfans.activity')
script = process.create_script(rpc_hook_code)
script.on('message', on_message)
script.load()
params = get_parmas(script)
print(params)
get_activity_ids(params)

```
</details>


这篇关于秀动APP逆向的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程