APP逆向 day25unidbg中

一.前言

昨天我们讲了unidbg的上篇,都是一些之前讲过的简单案例,末尾还单独说了一个新案例海南航空,今天我们来讲的案例都是之前讲过的,主要是和大家说补环境

二.唯品会skey

大家如果不记得了,可以去看看前面的文章,这里给出文章地址

APP逆向 day19v品会逆向 part1-CSDN博客文章浏览阅读973次,点赞41次,收藏12次。今天我们任务是破解唯品会的搜索接口,这里给出地址https://mapi.appvipshop.com/vips-mobile/rest/shopping/search/product/list/v1我们打开charles抓包分析一下(这次抓包分析比较复杂,但是我讲不了那么细,只能把关键点和大家讲一下,最后再实操一下)这个接口就是我们要的搜索数据,这个接口需要破的参数有 authorization api_key mars_cid sessionhttps://blog.csdn.net/weixin_74178589/article/details/140669859?spm=1001.2014.3001.5501

当时我们找到这里,就没有带大家往里面读,而我们是通过hook得到的,发现怎么都是固定的,而当时我没给出他so文件的名字,这里我给大家贴出来

 是libkeyinfo.so,我们今天用unidbg跑出来,是不是还是很简单,我这里和大家说一下,这里和昨天是一样的,这个只是带大家回顾一下,而需要补环境的在后面,大家可以先试试自己写

两个参数大家也看到了,一个是content对象,另一个就是字符串skey,返回值是个固定值

6692c461c3810ab150c9a980d0c275ec

 然后就c个代码啦,现在我们来编写sign里的内容

这里给出代码

public void sign(){

        // 1 找到类
        DvmClass KeyInfo = vm.resolveClass("com/vip/vcsp/KeyInfo");
        // 2 找到方法
        String method = "getNavInfo(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;";
        // 3 执行
        StringObject obj=KeyInfo.callStaticJniMethodObject(
                emulator,
                method,
                vm.resolveClass("android/content/Context").newObject(null),
                new StringObject(vm,"skey")
        );
        // 4 打印结果
        String  result = obj.getValue();
        System.out.println(result);

    }

运行结果和当时hook的一致 

三.唯品会api_sign

这个和skey是一天讲的,就不用给出链接地址了,这里给几张截图给大家回顾一下

发现最后是在gsNav方法,so和刚才是一个so文件,传的参数有四个,分别是

参数一:content对象

参数二:Map对象

参数三:字符串

参数四:布尔值

我这里给出当时hook的参数和结果

参数2:map==> {app_name=achievo_ad, app_version=7.83.3, channel=oziq7dxw:::, device=Pixel 2 XL, device_token=a9d1a2b9-2a79-36fd-a8ca-cbe24c03979d, manufacturer=Google, os_version=30, regPlat=0, regid=null, rom=Dalvik/2.1.0 (Linux; U; Android 11; Pixel 2 XL Build/RP1A.201005.004.A1), skey=6692c461c3810ab150c9a980d0c275ec, status=1, vipruid=, warehouse=null}

参数3 字符串 ==> null
参数4 布尔==> false

那我们就开始编写了,因为so文件还是一样的,所以初始化我们不需要更改,直接复制刚才的就好

3.1代码解释

这个代码发现和大家之前写的不太一样,这里我来具体解释

首先是Map new出来的是TreeMap是因为Map是一个接口,不能直接new出Map,不记得得可以去看看前面得java基础,都有说到,这个不是重点,我就不说了

然后就是比如那些类对应得jni签名大家不知道,这个时候就能借助gpt,问一下对应的全类名就好

举个栗子

然后把.换成/,前面加个L,用多了也就都记得了

接下来就是  ProxyDvmObject.createObject(vm,map)

给unidbg传参数时,需要包裹
    -之前咱们学的
        -字符串:new StringObject(vm,"")
        -布尔数字类型:直接传
        -其他自定义类型:vm.resolveClass("java/util/Map").newObject(map对象)
    -今天学到一个新的:无论对象什么类型,他能自动识别并匹配
        ProxyDvmObject.createObject(vm,对象)

而我们点开这个源码看一下

发现这个的本质就是读取传入参数的类型,然后给他new出对象,这个就十分的方便了,不需要再在里面写参数了,那我们接下来就有个问题,我们当时的content对象都给他当成是null传进去那么

vm.resolveClass("android/content/Context").newObject(null)
ProxyDvmObject.createObject(vm,null)

是不是一样的,第一个得到的是Context的对象,只是内容是空的

第二个它不是任何对象的对象,就是null,大家体会一下就知道了

只有拥有了content对象的时候,才能这么使用

而bool和数字也不能使用这个,因为他们直接传入就好,并不需要包裹

答疑完之后,我们运行一下

发现报错了

java.lang.UnsupportedOperationException: java/util/TreeMap->entrySet()Ljava/util/Set;
at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethod(AbstractJni.java:921)

3.2 补环境

遇到这个错误说明我们得要来补环境了,意思就是callObjectMethod中传入ava/util/TreeMap->entrySet()Ljava/util/Set;找不到方法嘛,我们就需要来补这个环境

-在so中调用java代码时,会需要补环境
-TreeMap在调用entrySet方法时报错
-在so中,传入c代码中map--》map在调用entrySet时,报错了--》环境中没有--咱们需要补

那我们直接输入callObjectMethod然后按照tab,自动出这么多

然后在里面写要补的方法,具体就和我这么来就行

如果不知道执行方法的类型,也可以写object,object可以代指所有的泛型,再用

return ProxyDvmObject.createObject(vm,objct);,这个前面说过可以知道里面的具体类型

现在就不报刚才的那个错误了,我们接着补,我这里带大家补几个,发现这个还是在刚才的方法里面,直接再写个if判断

按照这个来嘛,我们再运行

 发现现在报callBooleanMethod这个错误,那我们写这个然后按tab

选择这个带signature的

 

我们再次运行

 

又回到刚才的位置写个if判断,这里我就

 

 

运行报这个错,我们再写if判断咯

 

 

运行报错,再写个if判断

 

运行结果

 

这就已经出值了,这就已经ok了,发现这个都是在补java的环境,这里我给出所有的补环境代码供大家学习


    @Override
    public DvmObject<?> callObjectMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {


        if(signature.equals("java/util/TreeMap->entrySet()Ljava/util/Set;")){
            // 1 拿到map对象
            //从dvmObject中拿到TreeMap的对象,通过getValue,返回的类型需要做强制类型转换
            TreeMap map=(TreeMap)dvmObject.getValue();

            // 2 调用map对象的 entrySet ,没有参数,返回值是Set类型
            // 报错可以知道 返回值:Ljava/util/Set;

            Set set=map.entrySet();
            // 3 包裹,返回给unidbg
            // return vm.resolveClass("java/util/Set").newObject(set);
            return ProxyDvmObject.createObject(vm,set);

        }

        else if(signature.equals("java/util/Set->iterator()Ljava/util/Iterator;")){
            // 获取对象,强制类型转换
            Set set=(Set) dvmObject.getValue();
            //执行方法 iterator
            Iterator it=set.iterator();
            //包裹返回
            return ProxyDvmObject.createObject(vm,it);
        }

        else if(signature.equals("java/util/Iterator->next()Ljava/lang/Object;")){
            Iterator it=(Iterator) dvmObject.getValue();
            Object obj=it.next();
            return ProxyDvmObject.createObject(vm,obj);
        }

        else if(signature.equals("java/util/Map$Entry->getKey()Ljava/lang/Object;")){
            Map.Entry me=(Map.Entry) dvmObject.getValue();
            Object obj=me.getKey();
            return ProxyDvmObject.createObject(vm,obj);
        }
        else if(signature.equals("java/util/Map$Entry->getValue()Ljava/lang/Object;")){
            Map.Entry me=(Map.Entry) dvmObject.getValue();
            Object obj=me.getValue();
            return ProxyDvmObject.createObject(vm,obj);
        }

        return super.callObjectMethod(vm, dvmObject, signature, varArg);
    }

    @Override
    public boolean callBooleanMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {

        if(signature.equals("java/util/Iterator->hasNext()Z")){
            Iterator it =(Iterator) dvmObject.getValue();
            boolean z=it.hasNext();

            //流程还是之前那样,只是bool类型不需要包裹返回,是不是感觉写sign还是很像
            return z;
        }

        return super.callBooleanMethod(vm, dvmObject, signature, varArg);
    }

四.识货案例

这个案例和我们之前讲的案例不太一样,这个主要是和大奖讲补环境方法,这个是识货的老接口,当时搜索的数据都是加密的,我们这次来破这个,大家不知道其实也没关系,主要是学习补环境

我们把写好sign之后,可能很多人要问我,为什么要把字符串拼接这么多次,不麻烦吗,当然很麻烦啦,但是java有字符串限制,不能一下创建很长的字符串,所以要把字符串一个个添加进去,那我们现在来运行一下

4.1补安卓环境

那我们接着补

 

这个是安卓中的方法,拿不到,直接按照这个补空返回,如果后期这个还报错,就接着补

报错这个,我们接着补

 还是和刚才一样,我们接着运行接着补

 

运行

 这就出结果了,说明校验不严格 

4.2 系统对象

在补环境时候,会有java和安卓的对象
    -java的对象--》jdk提供了--》unidbg中会自带--》entrySet--》jdk自带的
    -安卓的对象--》安卓的sdk提供--》unidbg中没有--》我们统一都返回空对象
    -后期还会遇到--》app中自己写的类的对象--》把人家的类copy出来--》放到unidbg中
    
安卓的一个对象[context,Application,ActivityThread]--->其实很难伪造出来--》安卓中独有的
    -我们没有安卓的sdk,造不出来的,它的源码极为复杂
    -我们统一都返回 vm.resolveClass("android/app/ActivityThread").newObject(null);
    -context。。本质都是为了:拿蓝牙信息,设备id号,sdk版本,包名。。。。
    -补到最后,写死即可

4.3 安卓sdk

常见对象,如果不知道,就是搜索
ActivityThread: 
安卓程序的主线程或UI线程,ActivityThread的main方法是整个APP的入口

Application:
当前应用对象(本质是context),一般获取手机信息(蓝牙,网络),应用信息(包名,权限),数据传递,数据共享 ,数据缓存等

PackageManager:
    1、安装,卸载应用 
    2、查询permission相关信息 
    3、查询Application相关信息(application,activity,receiver,service,provider及相应属性等) 
    4、查询已安装应用 
    5、增加,删除permission 
    6、清除用户数据、缓存,代码段等 
                        
4 注意
以后遇到安卓系统的常见对象,我们先搜索,它作用是什么,先设置为null(vm.resolveClass("android/content/pm/PackageManager").newObject(null)),后续需要什么,通过hook或者写死再补环境 

 

五.总结 

这一期的案例写了我很久,主要是摆烂去了,星露谷物语太好玩了,沉迷其中,不过只有几节课就完结了,争取先完结再去玩吧,明天和大家讲一下unidbg的下期,我会和大奖讲补环境稍微难的了,案例大家拭目以待吧

 补充

有不懂的地方可以主页咨询我,有求必应

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往日情怀酿做酒 V1763929638

往日情怀酿作酒 感谢你的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值