安卓逆向

0、准备工作和大纲

JAVA环境、apktool、android APK、JADX、keytool、jarsigner(最后两个为JAVASDK自带工具)

java基本知识:源代码文件为XXX.java;是编译性语言,编译后才可以运行(PYTHON是解释性语言,直接可以运行);JAVA编译后的文件是XXX.class,class文件是可执行文件;JAVA虚拟机运行可以运行XXX.class方法为java XXX.class
安卓下面的xxx.dex dex是安卓里可执行文件

安卓软件包:APK。即一个压缩文件,用zip压缩解压。

JADX:把dex文件转化为java代码。

APKTOOL:反编译apk包。

签名

adb命令使用
adb devices    安卓设备列表
adb shell    进入安卓shell
adb logcat    adb logcat -s keyword    安卓日志
adb push    把文件推送进安卓设备
adb shell dumpsys activity top    adb shell dumpsys package packagename    打印AndroidManifest.xml
adb install XXX.apk    adb uninstall XXX.apk    安装卸载apk
adb pull android-path local-path    拉取安卓文件到本地
adb push local-path android-path    推送本地文件到安卓
网易模拟器:adb connect 127.0.0.1:7555

smali语法

破解安装签名校验

APK启动加载

APP四大组件

加固后的APK包

加固原理

脱壳

java编译运行

反混淆:
混淆工具:proguard;自己混淆。
jadx jeb2 日志打印
站在程序设计的角度上思考,程序要健壮、安全、性能高。
isNetworkAvailable

APP抓包。
代理被检测如何抓包;使用xpose模块;手动该smali

Frida开发
基础开发;Hook安装签名;Hook token;Hook so文件。

IDA动态调试:
网易模拟器:adb connect 127.0.0.1:7555
IDA动态调试配置:
adb push android_x86_server(cpu型号要对应,模拟器是x86)/data/local/tmp/    把本地文件推送进手机目录
adb shell    进入手机shell
cd /data/local/tmp/    进入tmp目录
ls -l    查看文件是否存在和确定文件权限。
chomd 777 android_x86_server    修改权限需要确定有root权限
./android_x86_server    运行
adb forward tcp:23946 tcp:23946    在本地执行adb做端口转发
静态调试,动态调试,反调试

IDA手动脱壳

1、安卓基础与逆向工具

安卓项目目录结构为:
assets:资源文件(图片,网页,视频)不会被编译。
res:资源文件(静态文本,图片,关键资源)汉化,要被编译。
lib:.so库,系统库,自己打包的库。有的把加密/token生成方式放在.so文件里
META-INF:签名信息
AndroidManifest.xml:配置信息(关键),举例:修改权限
classes.dex:android dalvik虚拟机可执行文件
resources.arsc:资源索引/对应文件

APP四大组件:
Activity:一个Activity通常就是一个界面。
Service:后台服务,播放音乐,处理数据等。
Broadcase receiver:异步接收广播
Content provider:内容共享

JADX:把dex文件转化为java代码。

APKTOOL:反编译apk包。用法:apktool d test.apk。结构:
AndroidManifest.xml    APP权限配置,也是程序入口
smali文件(一种汇编代码)    .smali可以和.dex相互转换;修改apk代码通常修改smali文件(重新修改.java源代码的话重新编译的困难太大);baksmali.jar smali.jar对dex和smali文件做转换
classes.dex    源代码在classes.dex文件里,可以反编译出.java代码
过程:.smali--->.dex---->.java
利用APKTOOL漏洞的apk会反编译失败,只能等升级或者找老版本。
重新打包apk方法:apktool b 目录

签名:keytool jarsigner 工具是JAVAJDK自带的。
生成证书:keytool -genkey -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 4096 -validity 10000
用证书给apk签名:jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -signedjar com.dahuodong.veryevent_4.6.2_60_sign.apk com.dahuodong.veryevent)4.6.2_60.apk my_alias
未签名APK不能再安卓手机上安装,APP在启动时会对签名进行校验,要逆APP就要跳过校验。

2、smali基本语法,安卓加载原理,破解安装签名

smali是Dex文件逆向后的一种语法,一种反汇编语言。smali代码和.java代码对应看会比较容易。.line和.java的代码行数对应。

下面是网上找的一篇关于smali的语法的简单介绍:
文章来源:http://www.brogrammer.cn/android/smali/

安卓加载
1、Dex加载流程(安卓源代码):
Davlivk虚拟机加载dex文件
  Java层Dex加载流程:BootClassLoader ---> PathClassLoader ----> DexClassLoader
  Native层Dex加载流程:libdvm.so(重编译system.img) OpenDexFileNative
2、点击图标,APP加载流程:一个APK只有一个Application。每个Apk运行时都需要有一个Application对象。Application对象执行onCreate方法时,APP就开始运行。

破解安装签名:修改smali文件;hook技术
用apktool反编译apk,得到AndroidManifests.xml,找到程序入口Application,对比java代码(使用jadx打开apk,查找程序入口对应的Application名),然后找Sig,sign等签名相关内容,最后在smali文件中找到对应的Application文件,将Java 代码中执行检查操作的代码的行数对应的smali代码删掉/改掉,让他不执行,之后用apktool打包。

3、加固脱壳,破解app请求token

加固apk的特征(各家.so文件名特征,需使用软件检测)(腾讯乐加固,360,梆梆,爱加密等);三方加固/自己加固(一般在哪家应用市场发布就要用哪家的加固方案);为什么要加固(一定程度保护源代码);加固方式(.dex/.so加固)
不同厂商对APP的加固特征:
爱加密:libexec.so, libexecmain.so, ijiami.dat
梆梆:libsecexe.so, libsecmain.so, libDexHelper.so
360:libprotectClass.so, libjiagu.so, libjiagu_art.so, libjiagu_x86.so
百度:libbaiduprotect.so
腾讯:libshellx-2.10.6.0.so, libBugly.so, libtup.so, libexec.so, libshell.so
网易易盾:libnesec.so

加固原理:源APK加密后+脱壳Dex = 新的Dex = 新的Apk
新APK运行:先加载壳APP--->壳APP读Dex文件末尾的源APKD大小--->在内存中壳APP解密出源APP--->运行源APP
壳APK有自己的Application对象,源APK由自己的Application对象,壳APK启动时,在AndroidManifest.xml里找源APK的Application执行它的onCreate方法,启动源APK。

脱壳:
脱壳原理:在壳APK解密源APK后,源APK被加载前,拦截这个过程中的系统函数,把内存中Dex,dump出来

方法:Hook:先取得要Hook函数/方法的控制权,这样不用破坏程序;动态调试:反编译,汇编,计算内存地址。
Hook技术(系统进程注入):在系统每调用函数前,通过HOOK技术,先得到该函数的控制权,实现该函数的逻辑改写,要Hook java层系统函数,要Hook应用对象方法(先知道应用对象源代码)

手动脱壳:通过动态调试,跟踪计算Dex源文件的内存偏移地址,从内存中Dump中Dex文件。此法难度大,要了解寄存器、汇编、反调试、反读写,利用IDA调试工具
工具脱壳:HOOK技术/内存特征寻找;简单易操作。DexExtractor Fdex2(重写libdvm.so dexFileParse函数 Hook ClassLoader) ZjDroid
  基础工具:xposed(java编译,Fdex2通用脱壳,dumpDex(https://github.com/WrBug/dumpDex))frida(python javascript代码注入)主要系统函数都已HOOK/基于xposed frida开发脱壳工具/有大神已开发上层应用模块。
  开发工具要了解APP启动加载过程的原理和细节。路径有两个:一是沿着APP加载启动过程,HOOK关键系统函数;二是Dalivk虚拟机层,需要刷system.image或改写系统.so文件,改写虚拟机层解析。
Dex文件的函数:使用已有工具,技术晚半代至一代。脱老版本的APP。
HookClassLoader的loadClass方法,反射调用getDex方法取得Dex(com.android.dex.Dex类对象),再将里面的dex写出。
  重写底层函数:DexExtractor(重写libdvm.so dexFileParse函数,用于梆梆、爱加密)
在线执行脱壳:http://www.dooccn.com/java

破解app的token:
先抓包,然后找到想要的数据的请求,接着确定要破解的token名称,使用jadx打开apk,搜索token名称,找到形似的地方,开始分析(可以使用jadx的反混淆,将变量名等做一个唯一化处理),找到生成方式后可使用python的jpype库调用jar包运行得到结果。
javajdk环境:sudo apt install default-jdk
编译:javac XXX.java
将class做成jar包:jar cvf XXX.jar *    java -cp XXX.jar XXX    此文件内需要有main函数
jpype调用jar包:from jpype import *    jvmpath = getDefaultJVMPath()    jarpath = 'jar包路径'    startJVM(jvmpath, "-ea", "-Djava.class.path=%s" %(jarpath + "jar包名称"))    JDClass = JClass("class名")    jd = JDClass()    res = jd.方法名(参数)    shutdownJVM()

4、frida逆向开发,hook——java层

Hook:改变程序执行流程的一种技术,在函数/方法被调用前,通过Hook技术,先得到该函数/方法的控制权,实现函数/方法的逻辑改写。

Hook的框架:
    xposed:Java语言开发的,只能hook应用层,开发经常需要重启设备,开发效率低,与安卓无缝对接。
    frida:C语言开发的,能Hook 安卓 IOS windows 应用层 native层,可以使你用JS和python代码完成Hook,不需要重启设备,编译,开发效率高,与安卓的数据类型转换比较麻烦。需要设备root权限

Hook的先决条件:要知道Hook哪个方法,哪个函数,要有源代码(方法定义原型)
Frida组成部分:Frida-server运行在设备上;Frida,python模块;Frida-tool提供cli工具命令,跟Frida-server交互。
官方文档:https://www.frida.re/docs/javascript-api
查看APP加载了那些so文件:cat /proc/[pid]/maps

常用模块API:
Java模块:Hook Java层的类、方法相关
Process模块:处理当前线程
Interceptor模块:操作指针相关,多用来Hook Native相关
Memory模块:内存操作相关
Module模块:处理so相关

Java.perform(function(){})方法
Java.use('类名')方法,用于劫持类包,将返回一个类实例对象。类实例对象.要更改的函数名.implentation = function (){};重写函数。

python需要安装frida和frida-tools。还需要下载server文件放到手机上执行(下载地址:https://github.com/frida/frida/releases)。
下载好之后需要解压。
操作步骤:adb push frida-server-12.6.8-android-x86 /data/loca/tmp/
    adb shell
    cd /data/local/tmp
    chmod 777 frida-server-12.6.8-android-x86
    ./frida-server-12.6.8-android-x86
在电脑上运行frida -ps -U。如果弹出一堆包,则表示成功。
转发端口到PC:
adb forward tcp:27043 tcp:27043
adb forward tcp:27042 tcp:27042

Hook通用思路
基础开发:
    Frida开发接口
    固定模式:
        python+js:python负责和frida-server通信,把js传给frida-server,起控制作用,写法固定;js负责hook操作

import sys, fridadef on_message(message, data):if message['type'] == 'send':print("[*] {0}".format(message['payload']))else:print(message)jscode = """
Java.perform(function () {
// Function to hook is defined here
varMainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');// Whenever button is clicked
MainActivity.onClick.implementation = function (v) {
// Show a message to know that the function got called
send('onClick');// Call the original on Click handler
this.m.value = 0;
this.n.value = 1;
this.cnt.value = 999;// Log to the console that it's done, and we should have the flag!
// console.log('Done:' + JSON.stringify(this.cnt));
};
});
"""process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()

应用要处于打开状态/已加载状态才能Hook。

Hook流程:
遇到需要Hook的情况;
使用jadx打开apk;
脱壳(如果需要);
反编译apk得到AndroidManifest.xml,找到入口类;
对应到jadx中的java代码,根据遇到的情况不同使用不同的方式进行分析处理(可以直接删除对应代码(smali代码),但需要考虑签名、重打包等问题;也可以通过js注入修改对应函数逻辑;查找所需密码)。

5、hook——native层

需要hook native层标识:方法/函数前使用native修饰。

API调用示例:
各种app应用由应用层API(安卓层)封装,安卓层由系统层API(SO层)封装得到。
如何Hook应用软件Java层。

简单了解.so库  libcrackme.so    IDA(软件)静态方法调试so
如何Hook so库:
    Module模块:
        .findExportByName(moduleName|null, exportName);    lib名称,函数名称。返回值是exportName的地址。
        .findBaseAddress(moduleName);    lib名称。返回lib的基地址
    Process模块:
        .findModuleByAddress(address);  lib的指针地址。返回一个Module对象
    Momery模块:
        .readCString(pointer);  指针地址。吧pointer还原成字符串。
        .readUtf8String(pointer);  
        .readAnsiString(pointer);
    Interceptor模块:监听
        .attach(target, callbacks);  指针地址,回调函数(onEnter, onLeave)。
        .replace(target, replacement);  
常用Hook的系统so库
    libc.so长调用函数:void * dlopen(const char *filename, int flag);    加载动态链接库。

如何Hook APP启动阶段的方法/函数:
Hook 打印堆栈信息:追踪方法的调用关系。
    send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
Hook 常见加密类:要知道java中有哪些常见的加密类。HookMD5 RSA之类的,要得到加密的源字符串需要得到加密的调用地方。
如何Hook重载的方法:在implementation之前使用.overload('[B')来声明其是重载(参数有:byte    byte[]    byte[] int int    ByteBuffer四种)。
Hook SSl
Hook 常用安卓: icity signature

Hook系统Java层
Hook系统so文件
Hook动态加载so
    https://www.breakyizhan.com/java/4982.html
    java.lang.Runtime:每个Java应用程序都有一个Runtime类实例,Runtime.getRuntime().loadLibrary()加载lib。

6、frida——hook——md5

了解安卓API/Java API:
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
https://developer.android.google.cn/reference/packages
https://www.android-doc.com/reference/android/content/pm/PackageInfo.html

java md5常用加密类:

java.security.MessageDigest
常用方法为:.getInstance 有三个重载。  .update() 有四个重载。需要全部hook

正常的分析手段:
抓包分析头信息的组成
拆解哪些头信息可以直接组装(app-version, device-id)
分析不能组装的数据的格式。(token    signature)
    正常分析token的逻辑
        反编译APP(先脱壳)
        通过关键字,或者其他手段,定位到token加密的地方
        分析是如何加密的

耍赖手段:
    思维习惯:不管token如何变化,如何加密,token有多复杂,总要调用一种或多种加密算法(md5 base64 rsa sha)来对源token进行处理,这种算法通常是调用第三方库或者java/android自带的库来做加密。所以直接hook常用的加密类,在加密的方法里面直接做打印,就可以得到源token;在加密的方法里调用堆栈打印,就可以知道是哪个方法在做加密操作,就可以找到这个方法。
    称为盲狙。要想成功率达需要大范围搞事。要覆盖常用的md5/base64/rsa/sha等常用方法。
    还有一种叫抓包耍赖:
    用fiddler抓包 APP有检测代理抓包,经常抓不到包。于是Hook网络请求库,得到URL、头信息、返回的数据格式。
    req = Java.use('requests')
    req.get.implementation = function(){
        send(url);
        var r = this.get(str);
        send(r.code);
        send(r.text);
    }

Hook 操作:
    不要改写方法的内部逻辑,要用它原来逻辑正常执行。
    Java.use('A')
    A.get_sig[.overload(参数类型)].implementation = function(str){
        send(str);
        var ss = this.get_sig(str);
        return ss;
    }

7、网络抓包

TCP/IP协议分七层,每一层都可以抓包(应用层-表示层-会话层-传输层-网络层-数据链路层-物理层)。
TCP/IP协议栈:由一系列网络协议组成,是网络通信的核心,所有设备的网络通信都依赖TCP/IP协议。电脑/手机/路由器/物联网设备。

抓包方式:
一、代理抓包模式(中间人攻击) Fiddler Charles VPN 192.168.0.5
    能抓Http/Https/WebSocket,属于应用层。优点是配置简单/抓取解析SSL方便;缺点是APP对代理抓包的检测屏蔽越来越强。
    原理:在客户端和服务端之间添加一层代理,并在代理处进行一些操作。
    HTTPS:HTTP是明文传播,容易被拦截,容易被修改,比如网页弹广告;HTTPS在HTTP的基础上加了安全层(SSL或TSL)
        特点:数据加密,不再使用明文传播;使用数字证书(CA)做身份校验,防止数据被截获,只有合法证书持有者才能读取数据;数据完整性强,防止数据被篡改,对数据做签名。
        HTTP OVER SSL传输数据前要SSL加密处理
        SSL握手协议:先商量好加密方式,交换证书,用证书加密,开始发送数据(用证书来给数据加密)
        Client Hello发给服务端:一串随机数和客户端支持哪些加密算法,一般是RSA加密
        Server Hello发给客户端:一串随机数和确定使用哪种加密算法
        Certificate:服务端把公钥证书发给客户端
        Client key Exchange:客户端把自己的证书发给服务端
        Session Ticket:开始传输数据/用key 给http数据加密,传输给服务端。
代理抓不到包的几种原因:
    1、请求没有走代理(可以设置走自己的代理,安卓系统会有先走APP设定的代理。http.route.default-proxy)
        判断依据:设置wifi代理后关闭fiddler,如果APP还能正常访问就是没走代理。
        解决方法:ProxyDroid APP 全局代理,强制把IP转发到指定端口上。原理是使用iptable命令实现端口转发,mumu虚拟起iptable会报错。
    2、ssl pining(ssl证书验证)目前大部分是这种导致抓不到包
        APP对服务端证书做校验,校验服务器的证书和域名(也叫单向认证),Fiddler/Charles的证书肯定是校验不过的。
        判断依据:在抓包工具中,请求方式为CONNECT,状态为Failed。
        解决办法:使用Hook手段将APP段网络请求库对ssl证书的判断方法hook掉(借助xposed的justtrustme。https://github.com/Fuzion24/JustTrustMe;或者frida的DroidSSLUnpinning https://github.com/WooyunDota/DroidSSLUnpinning);逆向APP扣除里面的证书放到charles里,让charles使用真实的证书做代理。
        部分sslpinning失效原因:
            Hook失败,APP的网络请求库被混淆,或者大厂自己实现了一套网络请求库。
            解决办法:逆向APP,找到证书验证的地方,修改xposed的justtrustme或者frida的DroidSSLUnpinning代码。
    3、双向认证(少用,会影响服务器性能):客户端对服务端发来的证书做校验;真实的服务端也对客户端证书做校验
        判断依据:soul app 做了ssl unpinning后报400的错误。
        解决办法:客户端校验依然适用SSL UNPinning方法;服务端校验要把APP里的证书导入到代理软件中,让代理抓包工具使用真实的APP证书。charles比较方便。
    4、socket通信:是IP层,fiddler/charles抓不到,使用wireshark抓包。解析soket通信数据比较麻烦,需要分析APP协议解析部分。
    5、似有协议:wireshark能抓到,不知道协议细节,解不了包,需要分析APP协议解析部分。
如何找到APP里的证书:
    反编译APP在assert文件夹中有.p12 .pem之类的文件 cer ssl
    反编译后,在源代码里大量搜索
    Hook 监听Assert文件夹,知道读了哪些文件
    可能有密码,Hook java.security.KeyStore查看密码
二、网卡混杂模式(wireshark HTTPS):wireshark 不需要对客户端做改变,是对网卡抓包,作用在传输层/网络层,抓TCP包。
如何抓手机上的数据:电脑上开wifi热点,手机连电脑的热点,公用一个网卡(虚拟机可以直接抓包,不用热点)
特点:抓https需要吧ssl证书倒入到wireshark,不过难操作。tcp以上的数据都能抓,http/https/socket。
过滤方式:
    根据目的IP抓包:ip.dst == 192.168.0.1    ip.addr == 192.168.0.1
    按端口过滤:tcp.port == 80
    按协议过滤:ssl
    关联过滤:ssl and ip.addr
三、路由器抓包(网络组网方式):有访问追踪功能的路由器可以使用。设置路由器抓发到本机的fiddler上,也需要配置ssl证书,难度较大。
四、Hook 域名 把https 改成 http:让app强行发http,请求可能会失败,抓不到response,但能抓到请求包。通用性差
五、Hook网络请求库: urlib urllib3 aiohttp requests:请求钱打印处请求参数,响应后打印出返回数据。通用性差。

PS:
   
安卓7.0及以后安卓系统不再信任用户安装的证书。解决方案是:1、root手机,把代理证书放到系统证书目录下。缺点在于有些手机的分区只能读取,不能写入。2、hook系统方法,强行让系统信任用户证书。
    所以:优先使用安卓系统低版本抓包(4.0 5.0 6.0);优先使用APP低版本抓包(历史版本https://wap.ppcn/apkpure.com);工具准备充分(包括但不限于fiddler/charles/wirseshark/模拟器4.0 5.0 6.0/root的安卓/苹果)

8、frida脱壳

function_address = Module.findExportByName(libname, function);
Interceptor.attach(address, func);
Interceptor.attach(address, onEnter:function(args){}, onLeave:function(retval){})// File 模块 写文件流程new File(filepath, mode)write(data)flush()close()file = new File("xxx.dex", "wb")
// data是字符串或者arrayBuffer //readByteArray() 返回的是arrayBuffer
file.write(data)
file.flush()
file.close()// 把内存里的值转换为字符串
Memory.readUtf8String()// 把内存里的值转换为整型
Memory.readInt()// 以begin为起始位置,从内存中读length长度的数据出来。返回ArrayBuffer类型
Memory.readByteArray(begin, length)// 把地址转换成NativePointer类型,frida里操作内存地址需要NativePointer类型
ptr()// JS api
parseInt(num, radix) // 把其他禁止转换成10进制

dex文件格式:
不同的文件格式都有自己的格式定义(.txt .xml .xls)
文件的每个字节都有固定含义,存放固定内容(https://www.jianshu.com/p/f7f0a712ddfe
由:
    Header    dex文件头部,记录整个dex文件的相关属性
    String_ids    字符串数据索引,记录了每个字符串在数据区的偏移量
    Type_ids    类似数据索引,记录了每个类型字符串的索引
    Proto_ids    原型数据索引,记录了方法声明的字符串,返回类型字符串,参数列表
    Fields    字段数据索引,记录了所属类,类型以及方法名
    Methods    类方法索引,记录方法所属雷鸣,方法声明以及方法名等信息
    Classes    类定义数据索引,记录指定类各类信息,包括接口,超类,类数据偏移量
    Data    数据区,保存了各个类的真实数据
    link_data    链接数据区
组成,会精确到规定每个字节的含义。

dexheader每个字节的含义:

脱壳原理:源dex文件最终会加载进内存。Hook加载Dex的函数,把Dex从内存中dump出来。Hook DexFile::OpenMemory()    DexFile::OpenMemory(const uint8_t* base, size_t size, const std::string& location, uint32_t location_checksum, MemMap* mem_map, const OatDexFile* oat_dex_file, std::string* error_msg)
如何找到Hook的点:熟悉安卓原理,熟悉代码层级;借助工具 查阅资料,摸清安坐加载dex代码级流程。
脱壳关键:熟悉安卓虚拟机加载dex文件的流程:https://www.jianshu.com/p/f81242ad8cb7

JNI动态注册:hook coolpai;分析代码的方法;关键字搜索法/片段关键字搜索;系统函数搜索法;分着交互流程,分析代码流程

Java的动态加载:在Java中声明函数原型,在.so中国呢具体实现
代码特征:
    public static native String getAS(Context context, String str);
    static {
        System.loadLibrary("native-lib");
    }
    libnative-lib.so

9、ida静态调试

NDK开发:Android NDK:是一套允许使用C和C++等语言,以原声带吗实现部分应用的工具机。用来做Native开发。
    https://developer.android.com/ndk
Java调用so库里的方法/函数:
    JNI:Java Native Interface。用java调用so库就叫JNI。方法如下:
        public static native String securityCheck(Context context, String str);    // 在java中申明一个Native方法
        static {    System.loadLibrary("native-lib");}    //使用System.loadLibrary()加载so库,全称是libnative-lib.so
        .so文件里对应的securityCheck名称是:Java_com_yaotong_crackme_MainActivity_securityCheck()    (即Java_类名_方法名())
        .so文件里对应的函数名称不一致:手动注册native方法。函数对应的名称是在JNI_ONLoad()函数里注册。

######手动注册native方法。

System.loadLibrary()加载so文件流程:
    先读取so文件的.init_array段;
    再执行JNI_OnLoad函数;
    JNI_ONLoad是.so文件的初始函数;
    然后调用具体的native方法。

IDA静态调试:
    点击New按钮,选择一个so文件打开。
    面板功能介绍
    静态调试技巧:
       
面板左侧函数列表可以查看每个函数的偏移量(相较于.so文件头的偏移量);
        F5(windows fn+f5)把汇编代码转成C代码
        shift+f12查看so文件中所有常量字符串的值,有的密码可能就在里面
        ctrl+s查看so文件段信息
        JNI函数方法名还原:选中v3,按y键(作用是类型还原)。v3 + 676 前面是一个指针,比如*(_DWORD *)v3 + 676表示v3是JNIEnv *类型。形如*(_DWORD *)vX + YYY皆是。
            可选中v3按y键进行类型替换,替换为JNIEnv *
        变量重命名,代码家住姐。

10、ida动态调试

将server文件推送至手机,更改其权限为777,运行服务器,在本地做端口转发(端口号为23946)
本地打开IDA,选中Go。
选择Debugger--->Attach--->Remote ARMLinux/Android debugger(真机);Remote Linux debugger(模拟器)
弹出窗口中输入IP+Port,点击OK
弹出Choose process to attach to窗口,选择要调试的进程/APP
等待加载,ctrl+s找到要调试的so文件,选择用X字样(可执行的)。
按键盘的G键,输入绝对地址,跳转到要调试的函数处。(绝对地址 = so文件的基地址 + 该函数的偏移量)(基地址:ctrl+s打开Choose segment to jump窗口,Start列是so文件基地址。)(函数偏移量:静态方式打开so文件,函数列表中。)
跳转至目标函数后,设置断点(F2或fn+F2),然后点击左上角开始(▶️)按钮运行。等待APP运行到断点处即可开始调试。
F7单步调试,要进入函数。F8单步调试,不进入函数。

so反调试:
IDA调试原理是利用Linux系统ptrace来实现。当应用被调试时,应用内存里的TracePid字段就不为0.
进入设备查看ptrace字段:
    adb shell
    ps | grep 包名
    cat /proc/pid/status
        打印内容中TracerPid为0代表没有被调试,不为0代表正在被调试
    反调试即检测TracerPid是否被占用。
so文件反调试的手段就是:新建一个线程,不停的检测TracePid这个字段是否不为0,不为0立即退出程序。
linux创建进程的函数:pthread_create()

反反调试:
动态调试,找到检测TracerPid的代码,选择不执行此代码。
方法:此检查代码一般在.init_array和JNI_OnLoad两处;在JNI_OnLoad函数处大断电调试,找到检测TracerPid的代码,不执行此代码。
    IDA调试反调试小经验——如何找到反调试代码:结合IDA静态时的代码,观察程序逻辑,指令一般会整个执行完,直到函数末尾。多次IDA中,如果指令在中途某个地方退出了,说明该处就是反调试指令。
    IDA调试反调试小经验——如何在JNI_OnLoad函数打断点:so文件在加载阶段会执行JNI_OnLoad,此后不再执行,要在so文件加载阶段才能给JNI_OnLoad打断点。
        一:修改APP AndroidMenifest.xml文件,APP加上可调式权限(android:debuggable="true"),重新打包app,签名,安装。
        二:检查flags中是否有应许debug项(adb shell dumpsys package com.yaotong.crackme)输出内容中的flags列表。
        三:以调试模式启动APP,APP此时会挂住(adb shell am start -D -n 包名/.类名)如:
            adb shell am start -D -n com.yaotong.crackme/.MainActivity
        四:.DebuggerOptions里勾选Suspend on thread start/exit Suspend on library load/unload。JNI_OnLoad函数是lib刚加载时就会执行,必须要在lib载入时就让程序停下来,才能调试JNI_OnLoad
        五:点击运行按钮
        六:在设备里查看APP的进程ID。要adb shell先进入设备运行如下命令,过滤出该应用信息:ps | grep 应用包名
        七:使用JDB命令让APP恢复运行:adb forward tcp:8700 jdwp:873(app的PID)    jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
        八:在so文件被加载时,IDA会停止住,使用ctrl+s查看目标so文件是否加载。若加载点选目标so文件,计算JNI_OnLoad的绝对地址,按G键跳转到JNI_OnLoad处设置断点,恢复APP执行,找到反调试代码处。(找反调试代码:关键地方可以F5转成C语言辅助;反复按F8单步执行,程序退出处(前面),极为反调试处)(不让反调试代码执行:让该指令变为空指令,即NOP。NOP指令的16禁止是00 00 00 00。记住反调试处的汇编指令,同时以静态方式再打开一个IDA(也叫双开)打开so文件在静态ida里找到此汇编指令,鼠标选中后面寄存器,然后切换到Hex View,会现实该指令的16进制。复制该16进制,在用文本工具打开so文件,找到该16进制处,替换成空指令。保存so文件,重新打包,签名,安装。)

动态调试libcrackme拿到密码:
    分析出密码判断的函数是哪个;IDA静态分析此函数,理清脉络;在此函数处下断点调试;单步调试,观察指令执行流程;密码不对事,指令会跨越执行,不再顺序执行;动态调试在关键指令处F5,转C代码辅助分析;动态调试时把鼠标移动到寄存器上,会显示该寄存器里的值;将指令转换为C代码,把鼠标移动到C代码的变量上,也会现实该变量的值。

补充:
C语言字符串操作
IDA动态调试按源码调试

11、ida——frida联合开发

so逆向总结:
逆向APK,找到加载的是哪个so文件,以及调用的是哪个native方法:System.loadLibrary()里是so文件名。声明的方法前有native关键字代表native方法
用ida以静态方式打开so文件
对函数里的JNIEnv *方法还原,让函数更容易理解
先看函数里的return break while等逻辑控制语句和有字面意义的函数调用,大治理清楚函数逻辑,对变量重命令让程序更容易看。
再用IDA动态调试,查看关键变量的值;或者使用frida找到hook点打印出关键变量的值。

12、小程序抓取流程

    小程序抓包:使用低版本安卓(4.4)和低版本微信(6.7),使用fiddler配置代理抓包。

小程序组成部分:
        微信小程序是一种基于微信的前端开发框架,跟网页前端的组成部分相似。
        微信小程序前端组成:.wxml(控制页面结构).wxss(控制页面样式).js(控制交互).json(配置数据)
        小程序官方开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/quickstart/
        小程序的组成:https://developers.weixin.qq.com/miniprogram/dev/framework/structure.html
            根目录下由app.js  app.json  app.wxss组成。小程序页面由四个文件组成(js, wxml[, json][, wxss])。在pages目录中,小程序页面有多少,其子目录就有多少。
            pkg_XXX 子包。小程序由大小限制,把小程序拆分成多个子包,按需要加载,提高运行效率。
            分包介绍:https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
    解包.wxapkg
    在微信中点击小程序时,改小程序的前端代码会下载到手机里。下载到手机上的时被编译后的小程序包XXXXXX.wxapkg。
    解包流程:从手机上的/data/data/com.tencent.mm/MicroMsg/微信号id文件夹/appbrand/pkg/到处目标小程序的wxapkg文件。
        安装node.js并下载解包程序。https://nodejs.org/en/    https://github.com/qwerty472123/wxappUnpacker    
        改进版解包程序:https://enterprise.gitee.com/_being/wxappUnpacker/blob/master/README.md#
        安装依赖包:esprima  css-tree  cssbeautify  vm2  uglify-es  js-beautify  escodegen
        运行解包程序node wuWxapkg.js xxxxxwx.apkg(解包要先解主包)
    解分包:node wuWxapkg.js 分包.wxapkg -s=主包目录
    成功标识:根目录下生成:app.js  app.json  app.wxss

调试小程序:
申请小程序开发者账号;下载开发者工具;登陆开发者工具,导入解包小程序;调试方式和chrome一致,要在详情里选中,不校验https证书。

抓取难点:
必须微信登陆的小程序,需要由大量微信账号的登陆token。

小程序登陆流程:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html

逆向学习(二) 安卓逆向相关推荐

  1. apk逆向思路_安卓逆向和手游辅助学习路线

    一.安卓逆向基础(建议1周) 1. 学习安卓逆向第一步必须先把环境搭建好,这是你学习安卓逆向的开始,环境搭建好后表示正式迈入安卓逆向.在环境安装的工程中会遇到很多细节上的问题. 2. 第二步就是要了解 ...

  2. c++ vector 一部分_C++逆向学习(二) vector

    此文为原创文章 作者:ret2nullptr@先知社区 恭喜作者获得 价值100元的天猫超市享淘卡一张 欢迎更多优质原创.翻译作者加入 ASRC文章奖励计划 欢迎多多投稿到先知社区 每天一篇优质技术好 ...

  3. 切水果安卓APP逆向过程报告----安卓逆向入门

    一.准备工作 下载切水果大战原版.apk. 链接:https://pan.baidu.com/s/18N_Lg8C4O5D1J7cbt99W6Q?pwd=p625 提取码:p625 开始游戏 找找有什 ...

  4. 爬虫逆向学习(二):那些年遇到的花式字体反爬

    常见字体反爬破解策略 CSS偏移反爬虫 案例场景 破解策略 SVG字体反爬 案例场景 破解策略 自定义字体反爬 案例场景 破解策略 CSS偏移反爬虫 案例场景 css偏移反爬虫是通过样式left偏移覆 ...

  5. 安卓逆向学习及APK抓包(二)--Google Pixel一代手机的ROOT刷入面具

    注意:本文仅作参考勿跟操作,root需谨慎,本次测试用的N手Pixel,因参考本文将真机刷成板砖造成的损失与本人无关 1 Google Pixel介绍 1.1手机 google Pixel 在手机选择 ...

  6. 跟我一起从零学习安卓逆向分析

    随着国家对信息安全的重视,兴起了各大CTF的赛事,其中逆向板块的安卓平台题目不断涌现.在这个互联网+的时代,移动互联网的APP犹如滚雪球一般的增长,随之而来的则是移动业务安全如风险控制.反外挂.安全合 ...

  7. 安卓逆向学习笔记:native层开发、分析和调试基础

    安卓逆向学习笔记:native层开发.分析和调试基础 本笔记主要是自己看,所以如果有看不懂的地方也请多多包涵,这一篇的笔记主要是<Android应用安全防护和逆向分析>的部分内容. 一 A ...

  8. 安卓逆向系列教程(二)APK 和 DEX

    安卓逆向系列教程(二)APK 和 DEX 作者:飞龙 APK APK 是 Android 软件包的分发格式,它本身是个 Zip 压缩包.APK 根目录下可能出现的目录和文件有: 名称 用途 META- ...

  9. 安卓逆向(Android)之二__《全民捕鱼》游戏内购破解

    安卓逆向之二__<全民捕鱼>游戏内购破解 环境简介 系统:Android 4.4 工具:Windows 10 64bit 夜神模拟器         Android Killer Java ...

最新文章

  1. 开始使用Nuxt.js
  2. 基于ncat的简易web服务器
  3. SHADER效果收集
  4. CodeForces - 1350C Orac and LCM(数论)
  5. R语言观察日志(part12)--关于.Rprofile文件
  6. ASP.NET MVC的过滤器笔记
  7. 牛客题霸 [滑动窗口的最大值] C++题解/答案
  8. [css] 你有使用过字体图标吗?它有什么好处?
  9. C# 读取app.config配置文件 节点键值,提示 配置系统未能初始化 错误的解决方案...
  10. rdd数据存内存 数据量_大数据开发-Spark调优常用手段
  11. 计算机考试的基础知识高考,计算机考试基础知识试题..doc
  12. Socket IO多路复用: epoll原理图解
  13. 机器视觉——鱼眼相机成像模型
  14. 视频|光学3D测量技术原理及应用
  15. 机器学习--逐步回归算法,线性回归的特征选择算法
  16. 操作系统经典书籍推荐
  17. 【论文翻译】 Residual Networks Behave Like Ensembles of Relatively Shallow Networks
  18. 无监督降维 效果评价 trustworthiness measure
  19. 复旦大学数学学院 17 级本科生对每周一题的评价
  20. raspberry pi设置静态IP地址

热门文章

  1. linux用用户默认密码是多少,useradd新建的用户默认密码是什么
  2. 清华大学视频课件:面向对象程序设计(C++)(自主模式)
  3. 微软亚洲研究院机器学习组的首席研究员刘铁岩谈AI
  4. 现代电气控制系统安装与调试装置
  5. 全面了解Windows系统鲜为人知的宝藏
  6. 用MyQR 制作动态二维码
  7. linux如何清除系统日志,如何清除Linux系统日志
  8. VoLTE的前世今生...说清楚VoIP、VoLTE、CSFB、VoWiFi、SIP、IMS那些事
  9. TQ2440开发板学习纪实(0.1)--- GNU Freestanding(Naked)C ARM交叉开发环境创建与测试
  10. VS Code的HTML代码模板