安卓逆向-Frida联合IDA | Token破解(在静态调试页面前多按几次F5等待加载完全 | MD5多点几次嵌套进去)

通过JADX打开酷安Coolapk.apk,发现无加固特征,能直接搜索到目标参数的键值对

在这里插入图片描述
在这里插入图片描述

用apktool反编译后用IDA静态打开libnative.so文件
搜索getAS方法发现没有解决,很有可能是开发者在JNI_OnLoad中做了处理
在JNI_OnLoad用y键还原一些寄存器后如图

在这里插入图片描述

因为原函数名是getAS,基本上在这里可以确认被改了名字,这里可以先不追下去,先盲猜一下,在左栏函数名那里进行搜索getA,可以看到getAuthString十分可疑,getAS就像是它的简写,这里对getAuthString进行分析

在这里插入图片描述

因为getAS是有返回值的,所以可以先从return入手

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

C语言中的NewStringUTF()在这里插入图片描述
// 所以可以理解成JNI的v55赋值给result
result = ((*v4)->NewStringUTF)(v4, v55)
所以开始找v55的生成方式,发现v55的值可能是v85或者v83

在这里插入图片描述

这里要开始找v84和v82的初始值来获得一些线索,可以发现v84是0空值,result也就是token不可能是个空值,所以result正常情况下一定走的v82,于是要去看v82的生成方式

在这里插入图片描述

先去找v82初始化也就是被定义的地方(可以从下图的地方开始)

在这里插入图片描述

v82被遍历和赋值0

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

v43的追溯

在这里插入图片描述

v85的追溯

在这里插入图片描述

v61的追溯(md5那里需要点进嵌套才能显示完全…是个大坑!!)

在这里插入图片描述

v58的追溯

在这里插入图片描述
在这里插入图片描述

v51的追溯

在这里插入图片描述

v49的追溯(通过Frida的Hook)

在这里插入图片描述
在这里插入图片描述

但是没有被export的函数没办法被hook到,所以这里可以分两种情况分析,一种是需要hook的函数在export里,另一种情况则是需要hook的函数不在export里。
首先分析要hook的函数不在export里的情况
  1. 方法一我们用IDA动态调试,通过so文件的基地址+函数的偏移量来获得函数在内存中的绝对地址来hook
  • 函数的偏移量如何获得 (可以直接在左栏搜索得到 or 可以通过点进函数可以看到)
    在这里插入图片描述
    在这里插入图片描述
  • so文件的基地址怎么得到(用IDA动态调试)
  1. 方法二通过so文件内任意一个能hook得到的函数的绝对地址-该函数的偏移量=这个so文件的基地址。然后拿这个基地址+要hook函数的偏移量从而得到函数在内存的绝对地址
下面我们通过getAuthString来操作方法二。(这个函数是能被java调用的,所以他一定是在export里面,能被hook到)

在这里插入图片描述

# -*- coding:utf-8 -*-
# coding=utf-8
import frida
import sys

package = "com.coolapk.market"
# package = "com.iCitySuzhou.suzhou001"
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)
        
device = frida.get_remote_device()
print(device,'device++')

# pid = device.spawn(package)
session = device.attach(package)
print(session,'session++')
src = """
    // getAuthString的内存地址
    var getAuthString_address = Module.getExportByName('libnative-lib.so','getAuthString');
    // getAuthString的内存地址 - getAuthString的偏移量 = so文件的内存基地址
    var ji_address = parseInt(getAuthString_address) - parseInt('0x66500');
    send('ji_address:'+ptr(ji_address));

    // b64_encode的内存地址 = so文件的基地址 + b64_encode的偏移量
    var b64_encode_address = ptr((ji_address+parseInt('0x31DB8')).toString())

    send('b64_encode_address:'+b64_encode_address)
    Interceptor.attach(b64_encode_address,
        {
            onEnter: function (args) {
                send("b64_encode_arg[0]"+Memory.readUtf8String(args[0]));
            }
        })
"""

script = session.create_script(src)
script.on("message", on_message)
script.load()
# device.resume(session)
sys.stdin.read()

hook的函数在export里的情况

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# -*- coding:utf-8 -*-
# coding=utf-8
import frida
import sys

package = "com.coolapk.market"
# package = "com.iCitySuzhou.suzhou001"
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

device = frida.get_remote_device()
print(device,'device++')

# pid = device.spawn(package)
session = device.attach(package)
print(session,'session++')
src = """
    var b64_encode_address = Module.getExportByName('libnative-lib.so','_Z10b64_encodePKhj');
    send('b64_encode_address:'+b64_encode_address)
    Interceptor.attach(b64_encode_address,
        {
            onEnter: function (args) {
                send("b64_encode_arg[0]"+Memory.readUtf8String(args[0]));
            }
        })
"""

script = session.create_script(src)
script.on("message", on_message)
script.load()
# device.resume(session)
sys.stdin.read()
下面再继续追溯v49的组成,所以v49的组成和v62相关

在这里插入图片描述

v62的追溯

在这里插入图片描述

在这里插入图片描述

v45的追溯

在这里插入图片描述

但是这里会遇到一点问题,赋值给v45的都是空值,所以可能是反编译出来的代码出现了错误。我们通过frida来hook这个append函数来分析分析
# -*- coding:utf-8 -*-
# coding=utf-8
import frida
import sys

package = "com.coolapk.market"
# package = "com.iCitySuzhou.suzhou001"
def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

device = frida.get_remote_device()
print(device,'device++')
# pid = device.spawn(package)
session = device.attach(package)
print(session,'session++')
src = """
    // append的内存地址
    var append_address = Module.getExportByName('libnative-lib.so','_ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKcj')

    send('append_address:'+append_address)
    send("-------------------------------------");
    Interceptor.attach(append_address,
        {   onEnter: function (args) {
                send("append_address_arg[0]:"+args[0]);
                send("append_address_arg[1]:"+Memory.readUtf8String(args[1]));
                send("append_address_arg[2]:"+args[2]);
                send("append_address_arg[3]:"+args[3]);

            },
            onLeave: function (retval) {
                send("result:"+retval);
            }
        }),

"""

script = session.create_script(src)
script.on("message", on_message)
script.load()
# device.resume(session)
sys.stdin.read()

输出结果分析

在这里插入图片描述

然后可以看到继续往上看可以看到一个MD5加密方法,那么等下我们同时hook住MD5加密的输出结果和传进append方法的MD5加密字符串,如果匹配,那么上面这个MD5加密方法加密后会将结果传入这个append中

在这里插入图片描述

未完待续…

C语言中的->

在这里插入图片描述
在这里插入图片描述

C语言的&和*

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_50685012/article/details/114729583