安卓逆向5,脱壳实战,模拟器安装使用,Xposed安装使用,fdex2脱壳,app抓包,找到接口参数加密的地方,逆向出来,引力播app

####

模拟器的安装和使用

1,本来是想在mac上使用mumu模拟器,但是安装Xposed一直失败,

2,我尝试使用真机来进行脱壳,但是Xposed可以安装,

电脑adb连接真机的方法:

首先真机打开开发者模式,进入设置,打开关于手机,找到版本号,一直点击版本号,在点击过程中会提示“还有×次,直到打开“开发人员选项”。并且打开usb调试开关,这样adb就能看到设备了

然后使用adb命令,在真机安装fdex2,命令,adb install fdex2.apk

然后进入真机的Xposed,这个app里面--进入模块,-点击fdex2,激活一下,

但是fdex2不支持安卓8,气人!我又不想对这个真机刷机,

3,我尝试在mac上面安装一个虚拟机,运行win10系统,在上面装一个雷电或者夜神模拟器,但是安装上之后非常的慢,根本无法使用,

4,我最后使用了genymotion

这个模拟器,适合开发者使用的一款比较快的Android模拟器,这个比那些夜神模拟器,要好,因为那些模拟器开发出来主要是为了玩游戏的,

第一步,VirtualBox的安装,Genymotion的运行需要依赖狱VirtualBox,所以需要先安装VirtualBox。

第二步,Genymotion的安装,到官网下载https://www.genymotion.com/download/,这个模拟器能再Linux-Ubuntu,mac,还有Windows,都可以安装使用,很强大,

第三步,创建Android模拟器,点击上面的加号Add,弹出一个创建模拟器的窗口。 按下图中的步骤创建一个GoogleNexus5 -6.0.0-API123模拟器。安装速度可能会有点稍慢。耐心等待下就好。

下载安装完成后就会在Genymotion主界面看到刚创建好的Android模拟器。点击start就可以运行这个模拟器了,

我下载的是Google nexus6p手机,安卓6.0版本,

5,当然如果有app开发能力,最好使用Android studio 自带的模拟器,更好

 

#####

Xposed的安装和脱壳使用

1,在genymotion安装了Xposed,

2,安装了fdex2,使用这个工具要先安装Xposed,这两个都是apk,

3,进入Xposed,这个app里面--点击左上角,进入模块,-点击fdex2,激活一下,

 

打钩说明这个fdex2,激活了,

4,使用fdex2,这个工具脱壳, 

点击这个fdex2,进入这个apk里面,里面会列出你安装的所有app,

 

 然后点击其中一个你要脱壳的app,提示了dex的输出目录,还有就是需要再次打开app,

 

5,再次打开app,使用adb,进入dex输出目录,看看是否是脱壳出来了,

adb devices,查看一下模拟器目录,如果没有看到尝试adb kill-server ,adb start-server,重新启动一下adb,

adb shell,进入这个模拟器里面,

cd /data/user/0/com.iCitySuzhou.suzhou001,进入这个目录就可以看到dex文件,如果没有就卸载app,安装app,但是不要打开这个app,再重新脱壳一次试试,

adb pull /data/user/0/com.iCitySuzhou.suzhou001 /Users/liqian/Desktop  把这个从模拟器里面pull出来到电脑桌面,

把apk脱壳之后,就会有导出的dex文件,会有好几个dex文件,

然后使用jadx,打开就是源代码了,怎么确定是哪一个dex文件,每一个都打开,搜索MyApplication,看看有没有这个文件, 有就对了

 

因为这个myapplication是不能被混淆的,要用这个名字做事情的,

 

大部分都可以使用这个工具脱壳,

使用,jadx-gui,打开这个jadx工具,打开脱壳的dex文件, 看到源码,

 

至此,整个的脱壳就完成了,

下一步就是开始分析这个脱壳之后的源码了,我们可以看到代码是被混淆的,下一步更重要的是看懂代码,

是不是很简单,那意义在哪里?方法虽然简单,但是你要知道这种方法并不是100%能把一个app脱壳出来,还需要其他更高级的脱壳手段,

这个工具还是要掌握的,因为这个工具可以把大部分的app都脱壳,

 

#####

实战:我们把引力播app,里面的新闻抓取下来,

安卓逆向第一步:app抓包

首先是要抓包,

使用Charles,进行app抓包,具体的抓包设置网络上都有,

主要的一步是在手机的wifi上面进行设置代理ip和端口,https://www.cnblogs.com/andy0816/p/15146008.html

 

抓包之后,我们可以发现这个接口里面有一个signature是变化的,

这个字段就是访问api的加密字段,

有的app,接口调用的时候,有一个参数sign,要携带上请求接口才行,这个是变动的,你不知道,所以就不能调用通接口,

可以通过重放来确定这个参数是不是动态的,

 下一步就是找到这个signature,然后看他怎么加密的,然后携带上这个signature,才可以请求这个api,

 

 

安卓逆向第二步:找到接口参数加密的地方,逆向出来

我们多抓几次包,就会发现这个signature是每次变化的,另外就是每一个接口都有这个signature,

所以我们判断这个是一个公共的部分定义了这个signature,

怎么办?

你需要找到app里面哪里生成的这个sign,是怎么生成的,然后你自己用python写出来,然后携带请求接口就行了, 

怎么着这个生成的地方?

我们发现每一个接口都有这个signature,所以应该是一个功能的地方生成的,

 

第一步,先用jadx打开dex文件,先搜索试试

在源代码里面搜索这个关键词signature,找到对应的代码,可能会有很多的结果,耐心找找

 

这里面有很多,需要你去分辨,左右是对应的,可以打开文件看,

每一个都看一下,就会给你更多的启发,

 

 

 这一行就会给我们启发,因为我们请求接口的时候,也有这个字段,

 

我们双击进入,看就是这个文件,

 

 

找到之后可能是混淆过的,可以用工具做反混淆,使用的是jadx-工具里面的一个反混淆,

 

 

这样反混淆之后再去查看源代码,这个反混淆不是彻底的,只是把一个名字变成唯一的, 否则你搜索一个a,b,c,会有几千个出来,

 

 

 找到一个方法实现的地方,可以右键

 

 

###

你找到了加密生成的代码之后,你还需要看懂,所以你还是需要java的功底的

 

这就是生成signature的地方,

 

但是你看不懂怎么办,可以打包成为一个java文件,让python调用,具体怎么实现呢?

 

####

安卓逆向第三步:怎么把java代码打包,让python调用?

第一点,你要安装java环境,

第二点,制作java文件,

这个是java加密参数的源码:

####

网上有在线的java执行工具,可以把这段java代码拿出来,然后去执行一下,方便调试java代码,https://tool.lu/coderunner/

import java.security.MessageDigest;

/* renamed from: com.hualong.framework.b.a */
public class MySig {
    /* renamed from: a */
    public static String get_sig(String str) {
        if (str == null) {
            return null;
        }
        StringBuffer stringBuffer = new StringBuffer();
        try {
            MessageDigest instance = MessageDigest.getInstance("MD5");
            instance.update(str.getBytes());
            byte[] digest = instance.digest();
            for (byte b : digest) {
                stringBuffer.append(Integer.toString((b >>> 4) & 15, 16)).append(Integer.toString(b & 15, 16));
            }
        } catch (Exception e) {
        }
        return stringBuffer.toString();
    }

//     public static void main(String args[]){
//         System.out.println("hello world");
//     }

}

把文件编译成为class文件,通过命令,javac xxx.java,

###

第三步,把class文件打包成jar包,通过命令,jar cvf xxx.jar

第四步,通过jpype 这个python的第三方库,调用这个jar,就可以实现python调java了,

这个jpype需要安装一下这个包,pip install jpype1,

###

import jpype
import requests
import time

uuid = "IMEI867686023834169-IMSI460NNNNNNNNNNNN"

time = str(int(time.time()))

ori_sig = uuid + "&&" + time + "&&" + "f1190aca-d08e-4041-8666-29931cd89dde"

# ①、使用jpype开启虚拟机(在开启jvm之前要加载类路径)

# 加载刚才打包的jar文件
jarpath = "/Users/liqian/PycharmProjects/spider/java/MySig.jar"

# 获取jvm.dll 的文件路径
jvmPath = jpype.getDefaultJVMPath()

# 开启jvm
jpype.startJVM(jvmPath, "-ea", "-Djava.class.path=%s" % (jarpath))

# ②、加载java类(参数是java的长类名)
javaClass = jpype.JClass("MySig")

# 实例化java对象
javaInstance = javaClass()

encry_sig = javaInstance.get_sig(ori_sig)
# java.lang.System.out.println(encry_sig)

print(encry_sig)

# ③、调用java方法,由于我写的是静态方法,直接使用类名就可以调用方法
# javaClass.show()

# ④、关闭jvm
jpype.shutdownJVM()

 

 

###

从jvmpath就是jpype库的用法了,

startJVM 是开启一个Java虚拟机,

JClass("MySig"),这是调用一个java方法,

我们可以看到是要传递一个字符串进入,这个字符串的格式就是uuid设备id,时间戳,还有一串固定字符串,三部分通过&&组成的,

 

 

最终python代码:

import jpype
import requests
import time
import urllib3
urllib3.disable_warnings()

udid = "IMEI867686023834169-IMSI460NNNNNNNNNNNN"

time = str(int(time.time()))

ori_sig = udid + "&&" + time + "&&" + "f1190aca-d08e-4041-8666-29931cd89dde"

# ①、使用jpype开启虚拟机(在开启jvm之前要加载类路径)

# 加载刚才打包的jar文件
jarpath = "/Users/liqian/PycharmProjects/spider/java/MySig.jar"

# 获取jvm.dll 的文件路径
jvmPath = jpype.getDefaultJVMPath()

# 开启jvm
jpype.startJVM(jvmPath, "-ea", "-Djava.class.path=%s" % (jarpath))

# ②、加载java类(参数是java的长类名)
javaClass = jpype.JClass("MySig")

# 实例化java对象
javaInstance = javaClass()

encry_sig = javaInstance.get_sig(ori_sig)
# java.lang.System.out.println(encry_sig)

print(encry_sig)

# ③、调用java方法,由于我写的是静态方法,直接使用类名就可以调用方法
# javaClass.show()


url = "https://app.suzhou-news.cn/api/v1/appNews/getBannerNewsList7?page=1&bannerID=11"

headers = {

    "sys": "Android",
    "sysversion": "8.1.0",
    "appversion": "8.2",
    "appversioncode": "54",
    "udid": udid,
    "clienttype": "android",
    "timestamp": "1632747791",
    "signature": "850196b383f11879ebb2c232d04d3b47",
    "accept-encoding": "gzip",
    "user-agent": "okhttp/3.9.0",
    "Accept": "*/*",
    "Postman-Token": "3c95da01-208f-4d15-895d-3a3230654863",
    "Host": "app.suzhou-news.cn",
    "Connection": "keep-alive",

}

# resp = requests.get(url, verify=False) # {"code":3,"message":"请求失败,缺少必要参数"}
resp = requests.get(url, headers=headers,verify=False)
print(resp.text)


# ④、关闭jvm
jpype.shutdownJVM()

 

这样用这个python代码,就可以成功通过接口获取到数据了,

 

###

但是这种把java拿过来直接python调用的方法,

不是任何时候都适用的,

因为有时候,这段java代码可能是有很多的依赖的包,你运行的时候,就会缺少很多的包,

这样就很麻烦,所以用python调用java的情况,这段代码最好不要有太多的依赖,

 如果加密的程序,依赖别的文件比较少,可以使用这种方法,但是如果太复杂,依赖比较多,这个还是需要自己使用python实现,这个就是比较难的地方,

 

###

 

 

 

 

####

posted @ 2021-08-23 19:09  技术改变命运Andy  阅读(2596)  评论(0编辑  收藏  举报