题目分析 定位到 ChallengeTwoFragment ,hook 一下 sign 函数,直接右键 -> 复制为 frida片段就行
hook代码:
1 2 3 4 5 6 7 let ChallengeTwoFragment = Java .use ("com.yuanrenxue.match2022.fragment.challenge.ChallengeTwoFragment" );ChallengeTwoFragment ["sign" ].implementation = function (str ) { console .log ('sign is called' + ', ' + 'str: ' + str); let ret = this .sign (str); console .log ('sign ret value is ' + ret); return ret; };
hook结果:
可以看出参数很简单,就是 page:时间戳
,看一下sign函数的定义:
有native关键字,说明是本地so文件 加载的,到这里有三种解题思路,一种是frida rpc的方式,一种是python调用Unidbg,一种是硬刚so文件
rpc的上一篇已经写过,没什么新意,这里介绍后面两种,也当作给自己积累经验 🤑🤑🤑
第一种 unidbg 加载 so 首先是拿到 so文件 ,这里使用 apktool 反编译
1 apktool d yuanrenxuem107.apk
找到 lib 文件夹下的so文件
使用 HEX工具判断一下so文件是32位还是64位,等会unidbg要用到
参考:https://chowdera.com/2022/04/202204200352162086.html
01 代表32位,02代表64位
所以是64位的so文件
用IDA打开so文件,可以看到函数静态注册的,可以直接调用
unidbg的环境搭建 可以参考这篇,初试 Unidbg 环境搭建
简单来说就三个步骤,拉取项目,idea打开项目安装依赖,运行测试项目
搭建 unidbg server(失败)unidbg调试好后,就需要想办法让python调用,这里有两种方案,一种是把unidbg-android 整个项目打包成 jar,然后用jpype调用,一种是本地起一个server服务,通过http的方式调用,这里我演示第二种,参考方案:
找了大半天,没有一个可以运行的方案,主要还是对java项目不熟,算了,老老实实打包成jar了 😥😥😥
unidbg项目打包成jar 参考的例子不太恰当,被卡了好久 🥶🥶🥶,自己整理一个规范的吧
首先是在 unidbg-android 下创建包,**包名
和类名
没什么讲究,随意就行,不需要和原APP保持一致**
编写Cxs.java文件,有几个注意点我已经注释了
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.yrxapp2;import com.github.unidbg.AndroidEmulator;import com.github.unidbg.Module;import com.github.unidbg.linux.android.AndroidEmulatorBuilder;import com.github.unidbg.linux.android.AndroidResolver;import com.github.unidbg.linux.android.dvm.DalvikModule;import com.github.unidbg.linux.android.dvm.DvmClass;import com.github.unidbg.linux.android.dvm.StringObject;import com.github.unidbg.linux.android.dvm.VM;import com.github.unidbg.memory.Memory;import java.io.File;import java.io.IOException;public class Cxs { private final AndroidEmulator emulator; private final VM vm; private final Module module ; private final DvmClass ChallengeTwoFragment; private final boolean logging; public Cxs (boolean logging) { this .logging = logging; emulator = AndroidEmulatorBuilder.for64Bit().setProcessName("com.yuanrenxue.match2022" ).build(); final Memory memory = emulator.getMemory(); memory.setLibraryResolver(new AndroidResolver (23 )); vm = emulator.createDalvikVM(new File ("unidbg-android/src/test/java/com/yrxapp2/yuanrenxuem107.apk" )); vm.setVerbose(logging); DalvikModule dm = vm.loadLibrary("match02" , true ); dm.callJNI_OnLoad(emulator); module = dm.getModule(); ChallengeTwoFragment = vm.resolveClass("com/yuanrenxue/match2022/fragment/challenge/ChallengeTwoFragment" ); } public void destroy () throws IOException { emulator.close(); } public static void main (String[] args) throws Exception { Cxs cxs = new Cxs (false ); System.out.println(cxs.sign("1:1652965963" )); cxs.destroy(); } public String sign (String str) { StringObject sign = ChallengeTwoFragment.newObject(null ).callJniMethodObject( emulator, "sign(Ljava/lang/String;)Ljava/lang/String;" , vm.addLocalObject(new StringObject (vm, str)) ); return sign.getValue(); } }
创建好后,运行,结果和抓包请求保持一致就说明成功了
然后就是重点了,打成jar包供python调用,在网上找了一圈资料,发现没有一个规范的教程,最后还是靠自己一点点摸索出来的 🤡
首先是 File -> Project Structure ,然后
这里有五个需要注意的点,配好后点击 ok
然后就不需要改什么东西了,直接点击 Apply -> OK
然后开始构建,在主界面依次点击 Build -> Build Artifacts -> unidbg-android.jar -> Build
稍等一会儿,在 unidbg\out\artifacts\unidbg_android_jar
目录下,你就会发现生成好的jar包
最后一个 unidbg-android.jar 就包含我们刚才编写的逻辑,
把所有生成的jar包复制到py目录,再新建一个目录,用于存放apk文件
最后只要编写py文件,调用,就终于搞定啦!🤗🤗🤗
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 import timeimport jpypeimport requestsjpype.startJVM(jpype.getDefaultJVMPath(), "-ea" , "-Djava.class.path=unidbg-android.jar" ) jclass = jpype.JPackage("com.yrxapp2" ).Cxs ChallengeTwoFragment = jclass(False ) results = [] for page in range (1 , 101 ): ts = int (time.time()) url = "https://appmatch.yuanrenxue.com/app2" data = { "page" : page, "ts" : ts, "sign" : str (ChallengeTwoFragment.sign(f"{page} :{ts} " )), } resp_json = requests.post(url, data=data).json() num_lst = [int (d["value" ].strip()) for d in resp_json["data" ]] print (f"第 {page} 页:" , num_lst) results.extend(num_lst) print ("100页面总和为:" , sum (results))
运行结果 & 挑战成功
本来想写ida调试的,发现篇幅有点大,知识点也有点多,后面再新开一篇写写吧,另外提一嘴,
这个so比较简单,没有签名校验 ,不用补环境 ,以后有遇到了可以参考这篇:
https://www.jianshu.com/p/615cff5683bb
还有第二关用frida rpc 方案也可以过,但总感觉有些胜之不武,就不介绍了 😁😁😁
net.dongliu.requests 方案 直接在java代码里面请求,就不需要用python调用了
用法:https://blog.csdn.net/dxh0823/article/details/81137400
1 2 3 4 5 import net.dongliu.requests.Requests;String url = "https://app9.scrape.center/api/movie/?offset=0&limit=10&token=" +token;String response = Requests.get(url).timeout(10000 ).send().readToText();System.out.println(response);