安卓逆向6,frida逆向框架介绍,基础开发hook java层,进阶开发hook native层,hook 加密类

####

hook技术

1,hook,java层,这个相对简单,都是java代码,

2,hook,native层,so库,这个难度大,里面都是汇编,

 

 

####

frida框架介绍:

 

frida是一个逆向框架,

 

目前逆向框架比较知名的有两个,Xposed,frida

Xposed,是java开发的,要会java

frida,是python和js,开发的,这个比较适合我,frida是一个js注入技术,python主要是一个架子,主要还是用js注入,

 

两个工具对比,

frida比Xposed的适用性更广一些,Xposed只能hook安卓,java层,

而frida可以hook,安卓,ios,windows,还可以hook,安卓的native层,

 

 

###

frida中python只是调用,主要是写js,做js注入,

###

使用frida开发的前提是设备要root

###

使用frida开发hook 的前提条件,

你首先要知道hook哪一个方法,所以你要先解决脱壳的问题,获取到源代码,

###

frida组成部分,

1,frida-server,这个是一个包,需要放到手机设备上,

2,frida,python模块

3,frida-tools,提供cli命令,和frida-server做交互,

第二个和第三个是可以只用一个的,你可以用python,直接调用js,也可以用客户端cli命令,调用js,

 

###

有空经常去看官方文档,

很多时候,有很多问题,你解决不了,你去百度不到的,必须要养成看官方文档的习惯,

对于这些先进的东西,生态还不是很丰富的,你必须要要看官方文档,

###

Frida安装配置

 

第一步:电脑安装frida和frida-tools

pip install frida
pip install frida-tools

--注意:这两个我安装到了python虚拟环境里面了,所以要先进入python虚拟环境,然后再执行

 

mac安装本来是两个命令的事情,但是安装的时候总是报错,

sudo pip install --upgrade certifi
open /Applications/Python\ 3.7/Install\ Certificates.command

如果是证书问题,就执行这两句,然后重新启动电脑,我的就是这样好的,

####

第二步,手机执行frida server


frida server 放在手机上执行 要注意手机CPU型号
https://github.com/frida/frida/releases

 

下载的时候,注意是x86,还是x86_64,还是arm,

手机基本都是arm

模拟器一般都是x86的,而且是32位的,但是这不是绝对的,需要查看一下,

adb shell getprop ro.product.cpu.abi

使用这个命令来查看,

 

####

在手机上执行:

首先下载的frida-server解压,

推入手机里,adb push frida-server-15.0.18-android-x86_64 /data/local/temp/frida-server

adb shell
cd /data/local/temp
确定手机当前用户是root用户或拥有root权限
chmod 777 frida-server   --变成可读可写可执行,
./frida-server  

执行完毕后为运行状态。

保留此窗口 shell,以保证服务运行,关闭该shell 或者停止ctrl+c 则服务关闭。接下来的操作可另起shell 或该步骤命令另起 shell 执行。

###

第三步,端口转发:

adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
27042 用于与frida-server通信的默认端口号,之后的每个端口对应每个注入的进程,检查27042端口可检测 Frida 是否存在。

你想要在python里面做开发,还要做端口转发,

不然,你python做开发,是会报错,告诉你没有连接上,

####

第四步,检查是否成功

电脑上运行

先进入python虚拟环境,里面安装了frida tools

frida-ps -U 电脑上运行 android.process.acore 字样表示成功

这个命令是验证一下,在手机端的frida-server是否运行起来了,

注意这一句要进入你安装frida的虚拟环境里面执行,

 

### 

经过上面的配置,你就可以做frida开发了,

 

###

frida基础开发示例:

###

 

frida开发的固定套路:三段论

第一段:有一个打印的python函数,用来打印日志,不使用这个,使用console.log("version: "+v)也可以,只是自己写可以加一些标志,

第二段:有一段js脚本,

第三段:下面有一段python代码,

主要是做了,获取设备,获取设备里面的app包名,执行js脚本,注入到app里面取,调用第一段的打印方法,最后一句是不要让程序断掉,

第一段和第二段,基本不用动,主要是动中间的js脚本,

python主要是一个架子,主要还是用js注入,

####

要先在模拟器把app运行起来然后再hook

运行这个py文件,可以打印出来安卓系统的版本,打印所有调用的方法

###

frida提供了什么方法,可以看官方文档,

https://www.frida.re/docs/javascript-api

具体的js脚本的api,看这个官方文档,

逆向开发很少有很详细的教程,

所以如果你遇到解决不了的问题,你要常常看官方文档,静下来心看文档,这是你进阶的必经之路,

###

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

###

python代码:

import frida
import sys


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


jscode = """
// 获取安卓版本
var v = Java.androidVersion;
send("version: "+v)

//获取该应用的加载的类
var classnames = Java.enumerateLoadedClassesSync();

// for循环
for(var i = 0; i<classnames.length; i++){
     send("class name :" + classnames[i]);
}
 """


process = frida.get_usb_device().attach("自毁程序密码")
script = process.create_script(jscode)
script.on("message",on_message)
print("[*] running CIF")
script.load()
sys.stdin.read()

 

#####

 

 

#####

 frida进阶开发:

 

 

###

 

###

作为一个开发已经要了解一个分层的思想,

看上面这个图,一开始就只有系统层的AIP,也就是so层,这一层的API可以让程序员调用,

但是你使用这一层,对程序员很不友好,所以封装出来了应用层API,安卓层,这一层对程序员比较友好,开发效率也会提升,

###

一般的程序员是有有流水线的培训的,所以在市面上有很多培训机构,

系统层,so层,这个对程序员的要求很高,对技术的深度和广度都有要求,没有办法批量培训,

系统层的问题都比较复杂,所以现在很多分层了之后,系统层的问题你就不用管了,只需要去考虑应用层,去调用接口去开发app,关注业务逻辑,

应用层对程序员比较友好,

###

另外主要最上层的app,不是只能调用安卓层,还能直接掉SO层,这是可以的,

因为及时你调用的是安卓层,最终也会传导到系统层,然后执行,

###

理解了上面的分层,

你就会知道,为什么你有时候hook应用层的时候不生效,

比如打开文件,你hook应用层不生效,这个时候你就要考虑是不是要hook系统层,os层,

因为我知道不管你怎么打开文件,一定会经过系统层,那我就直接hook系统层的打开文件的函数,就一定能hook到,

有时候你会发现,直接hook系统SO层,还会更方便,

###

简单了解so库,---ida工具

如何看到SO库文件里面的内容,就要使用到一个神器,IDA工具,

使用ida工具,需要安装一下软件,

这个工具的使用就是调试代码的,

目前最优秀的静态反编译软件之一,这款mac安全工具它不仅可以应用在反编译和动态调试等强大的逆向工程领域,还支持对多种处理器不同类型的可执行模块进行反汇编处理,软件具有方便直观的操作界面,在为用户呈现出简洁清晰源代码的同时,也完美的减少了反汇编工作的难度,极大的提升了用户在反编译工作中的使用体验。

可以使用这个工具看到so库里面的内容,都是一个一个的函数,供app调用,

###

具体软件使用要自己学习了,

###

怎么hook这个so库呢?

下面介绍几个操作so库的frida的API使用

hello.so

  printhello()

假设你要hook一个so库,hello.so,

里面有一个方法printhello()

 

 

 

 

第一步:使用module模块,都是操作内存地址,

module.findBaseAddress(name)

使用memory模块,这个是操作内存,

可以把内存的内存拿出来,转成字符串,

使用intercept模块,监听模块

可以把方法监听到,拿到函数的操作权,就靠这个模块了,

 

 

 

####

怎么hook,app启动阶段的方法?

 

#####

有很多时候我们需要在APP的打开之前做hook,完全打开之后就hook不到了,

所以要在启动阶段hook,

有哪些是app页面在完全打开之前做的:

比如oncreate方法,

###

用之前的hook方法是不行的,这次要换一个,

 

 

 上面是之前的写法,下面是新的写法,

获取到pid,然后resume重启这个进程,就可以hook到app启动阶段的函数调用了,

注意,这种方法,也要把APP处于启动阶段,中间的重启app是自动进行的,

###

启动的代码不动,只改动一下,下面的几行,和jscode的几行,就可以打印出来i am here

对应的jscode:

所以你看到有一个细节,就是进行了方法重写,

这样我们只是增加了一个oncreate方法的打印,其他的都没有动,

 

###

怎么hook系统层的so文件?

####

 

这个是经验得来的,

这是打开文件的库,

hook这个,就知道打开了什么库了,

####

jscode:

 

###

frida进阶开发:hook加密类--使用引力播app

怎么hook,java的加密类,首先你要知道java里面有那些加密类,比如md5

我们能这样不看代码就去hook加密的前提,是因为加密算法一般公司会使用现成的,而不是自己去发明一套,这样我们就知道去找找java里面的加密类去hook一下

尝试一下就知道这个app是否使用了这个加密算法,

这个方法比较笨,因为这个你要知道java里面所有的加密算法,

 

  

这就是hook重写的技巧,很重要,

这样的写法不会破坏原有的原理,但是又可以增加我们想要的代码,

如果没有返回值,就是不需要return ,

如果有返回值,就可以使用变量来接收,

具体有没有返回值,需要在api里面来判断,

 

代码解释:

第一点,为什么hook,update方法,因为这个加密算法,有多个update方法,所以我们把四个update都hook一下,具体可以看下这个加密类的API

 

我们知道了这个加密类之后,还不能盲目去hook,还需要查一下这个类的api,下面是查api的结果,

 

如果你使用overlord,会报错的,

了解安卓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

 

 

 

###

第二点:有一个地方传入的字节,我们要把他转行成为字符串,下面是转换的js代码:

 

###

第三点:为什么要打印参数,因为既然你加密是用的这个算法类,那肯定要把待加密的字符串拿到,

 

 

 

 这就是加密之前的字符串,我们就hook到了

有三段,是设备号,时间戳,第三段是固定的(多运行几次就知道了)

 ###

第四点,我们把getinstance方法,也打印出来了,这个需要传递是什么类型的加密,就是使用的md5加密

###

第五点:我们拿到这个加密,但是还能加密之后做了位运算,

所以我们要hook这个加密函数的调用栈,我们可以找到加密的地方,

怎么打印调用栈呢?

下面的写法是固定的,直接哪来用就可以了,

 

 

 

 我们拿到了堆栈之后,才之后,是这个a调用的加密,否则混淆过的代码,我们根本不知道这个是哪里调用的,

通过这个方式,我们没有使用jadx进行搜索,但是我们通过hook加密类,就得到了这个加密的代码位置,

这样我们就可以直接去找这个函数,看看怎么加密的,

下一步使用jadx打开这个app,这个icity是要脱壳的,

 

完整的python代码

import frida
import sys


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


jscode = """
Java.perform(function(){
        var Testsig=Java.use('com.yaotong.crackme.MainActivity')
        Testsig.onCreate.overload('android.os.Bundle').implementation=function(v){
            send('I am here');
            this.onCreate();
        return true ;
        }
})
"""
# 打印输出基础地址
jscode1="""
        
        var base_address = Module.findBaseAddress('libc.so');
        send('base_address:'+base_address);
        
        var mod_address=Module.findExportByName('libc.so','dlopen');
        send('mod_address:'+mod_address);
        
        var lib_module=Process.findModuleByAddress(base_address);
        send('lib_module_name:'+lib_module.name);
        
        Interceptor.attach(mod_address,{
        onEnter: function(args){
            send("open("+Memory.readUtf8String(args[0])+","+args[1]+")");   
        },
        onLeave: function(retval){
            send('retval:'+retval);
        }
        })
        

"""
#hook md5加密
jscode2="""
    //打印调用堆栈
    function printstact(){     
        send(Java.use('android.util.log').getStackTraceString(Java.use('java.lang.Exception').$new()));
    }
    //array 转成 string
    function array2string(array){
            var buffer=Java.array('byte',array);
            var result='';
            for (var i = 0;i<buffer.length;i++){
            result +=(String.fromCharCode(buffer[i]))
            }
            return result;
    }
    Java.perform(function(){ 
        var MessageDigest=Java.use('java.security.MessageDigest');     
        MessageDigest.update.overload('[B').implementation= function (bytesarray) {
        send ('I am here 0');  
        send('ori:'+ array2string(bytesarray));
        printstact() ;
        send('md5:'+this.update('bytesarray'));
        },           
        MessageDigest.update.overload('byte').implementation=function(bytesarray){
        send ('I am here 1'); 
        send('ori:'+array2string(bytesarray));
        printstact();
        send('md5:'+this.update('bytesarray'));
        },   
        MessageDigest.update.overload('java.nio.ByteBuffer').implementation=function(bytesarray){
        send ('I am here 2');
        send('ori:'+array2string(bytesarray));
        printstact();
        send('md5:'+this.update('bytesarray'));
        },   
        MessageDigest.update.overload('[B','int','int').implementation=function(bytesarray){
        send ('I am here 3');
        send('ori:'+array2string(bytesarray));
        printstact();
        send('md5:'+this.update('bytesarray'));
        },
        
        MessageDigest.getInstance.overloads[0].implementation=function(algorithm){
        send('call->getInstance for ' + algorithm);
        return this.getInstance.overloads[0].apply(this,arguments);
        };
            
    }
    );
    """
deveice = frida.get_usb_device()

pid = deveice.spawn(['cn.soulapp.android'])

process = deveice.attach(pid)

# 创建运行脚本
script = process.create_script(jscode2)
# 输入打印,写死
script.on('message', on_message)
print('[*] Running CTF')
# 写死
script.load()
# 重启程序
deveice.resume(pid)
# 写死
sys.stdin.read()
最后打印结果,看出加密方式

 

 

###

注意,执行的时候,运行一下app,否则打印不出内容,

###

通过这个方法还是找到加密的入口函数,

不再使用jadx搜索的方式来找加密入口了,

之前是怎么找这个入口的,是关键词搜索的方式,这一步通常很难,因为代码反混淆之后,你看不懂他的代码,搜索不到,这是一步一步的从上到下分析,

###

我们hook的目的,不是要完全的破解,而是要破解加密的token,还有加密的参数,能去调用接口,

这个过程我们会遇到很多困难,

如果是加固了,我们要脱壳,

如果混淆了,我们这个时候直接拿到加密参数的字段去搜索就搜不到,否则我们可以试试搜索一下,看看是否可以看到,

既然混淆了,我们就要有手段,可以让我们的分析更加有效一点,

上面的这个加密算法的hook,就是基于这个目的,就是为了解密参数,

###

使用上面这种盲狙的方法,怎么提升成功率,就是扩大加密类的覆盖,覆盖的多,就可以大概率的能打印出来,

###

同样一个app,引力播,

第一次,我们通过脱壳,然后搜索signature来找到加密的地方,

第二次,我们脱壳之后,hook,加密类,打印调用堆栈,然后来找到加密的地方,

 

很多地方都可以用这种方法, 

这次是hook加密类,这是我们要解决参数加密的问题,

我们还可以hook,网络请求库,因为我们要解决抓包的问题, 同样的思路,

 

 

###

但是这种思路,主要还是要hook的面范围大,才可以覆盖大,

 

 

 

###

前期使用frida工具,能hook到类,方法,并且打印出参数,打印出日志,打印出堆栈就可以了,

后续会有更加复杂的操作, 

 

 

 

 

 

 

####

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