生成证书

keytool -genkey -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 4096 -validity 10000

签名

jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -signedjar com.yaotong_sign.apk com.yaotong.apk my_alias

frida

安装

github下载,github.com/frida/frida/releases

Frida api接口

frida.re/docs/javascript-api
然后

Frida使用

add push (解压后得到的文件,单文件,重命名为frida-server)frida-server /data/local/tmp

add shell

cd /data/local/tmp

chmod 777 frida-server

开启服务./frida-server

frida-ps -U验证是否成功

adb forward tcp:27043 tcp:27043
adb forward tcp:27042 tcp:27042

python + Javascript
Python代码是控制,写法固定,负责跟frida-server通信,把JS代码传递给fridaserver

Javascript代码进行Hook操作

5307端口占用解决

问题:adb server is out of date. killing...

1. netstat -ano | findstr "5037"

2. tasklist | findstr "10760"

3. taskkill /f /pid 10760

开发接口

import frida, sys

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

jscode = """

"""
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 so库

Module模块

Module.findExportByName(moduleName|null, exportName)
    moduleName:lib名字
    exportName:函数名字
    返回exportName的地址
Module.findBaseAddress(moduleName)
    moduleName:lib名字
    返回lib的基地址

Process模块

Process.findModuleByAddress(address)
    address:lib的指针地址
    返回一个Module对象

Momery模块

Memory.readCString(pointer)
    pointer:指针地址
    把pointer还原成字符串
Memory.readUtf8String(pointer);
Memory.readAnsiString(pointer)

Interceptor模块:监听

.attach(target, callbacks)
    target:指针地址
    callbacks:回调函数
        onEnter
        onLeave

Hook的系统so

libc.so常调用的函数:

void * dlopen(const char *filename, int flag)加载动态链接库

如何Hook App启动阶段的方法:

jscode= """
Java.perform(
    function(){
        var TestSig = Java.use('com.yaotong.crackme.MainActivity');
        TestSig.onCreate.overload('android.os.Bundle').implementation = function(){
            send('i am here')
            return true;
        }
    }
)

"""
device = frida.get_usb_device()
# 先hook住
pid = device.spawn(['com.yaotong.crackme'])
process = device.attach(pid)

script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
# 然后重启
device.resume(pid)
sys.stdin.read()

Hook打印堆栈信息

Hook常见加密类

如何Hook重载的方法

Hook SSL

Hook 常用安卓

//打印基地址
var base_address = Module.findBaseAddress('libc.so')
send('base_address:'+base_address)
//打印dlopen地址
var mod_address = Module.findExportByName('libc.so', 'dlopen');
send('mod_address:'+ mod_address);
//打印module地址
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)
    }
})
function printstack(){
    send(Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new()))
}
function array2string(array){
    //因为这里面的array是`byte`数组
    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('orig:' + array2string(bytesarray))
            printstack()

            this.update(bytesarray)
        },
        MessageDigest.update.overload('byte').implementation = function(bytesarray){
            send('i am here 1')
            send('orig:' + array2string(bytesarray))
            printstack()
            this.update(bytesarray)
        },
        MessageDigest.update.overload('java.nio.ByteBuffer').implementation = function(bytesarray){
            send('i am here 2')
            send('orig:' + array2string(bytesarray))
            printstack()
            this.update(bytesarray)
        },
        MessageDigest.update.overload('[B', 'int', 'int').implementation = function(bytesarray){
            send('i am here 3')
            send('orig:' + array2string(bytesarray))
            printstack()
            this.update(bytesarray)
        },
        MessageDigest.getInstance.overloads[0].implementation = function(algorithm){
            send('i am here 4');
            send('call ->getInstance for:' + algorithm)
            return this.getInstance.overloads[0].apply(this, arguments)
        }
    }
)

this.update(bytesarray)是调用程序中本来的update方法,让程序继续执行。

Frida hook JAVA api

访问成员变量

this.成员变量名.value

hook匿名类写法:

 Java.use('类$类') smali文件里找

从匿名类/内部类访问外部类的属性写法:

 this.this$0.value.外部类的属性名.value


先解包,

从smali包里找这个路径

下面的是外部类,上面带的是匿名内部类,可以用文本编辑器打开,然后发现只有带的才有匿名内部类的方法

var mainClass = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity$1')
mainClass.run.implementation = function(){

}

hook静态方法

类.方法()

var ee = Java.use("com.pp.asss")
console.log(ee.a(5))

hook成员方法


必须new

var se = Java.use("java.security.SecureRandom").new()
var sb = Java.use("java.lang.StringBuffer").new()

新建一个对象 new

 这块markdown显示有问题,是有个英文的dollar符号new
 类.方法名.$new(参数)

重载写法

 类.方法名.overload(arg1,arg2.......).implementation

hook 构造方法

 类.$init().implementation

类型转换

var Map = Java.use(‘java.util.Map’)
var NewP = Java.cast(P, Map)
把P 转成 Map类型

方法一:
 1.先确认object是什么类型(比如要打印p) 先console.log(p.$className) 查看p是什么
数据类型
 2.Java.cast 把p强转为对应类型
 3.调用该类对应的输出方法。通常有一个toString()方法


 方法二:
 使用js里的JSON类
 尝试 console.log(JSON.stringify(p))
 可能打印不出来字符串,一般能打印出p的字节数组。(可以用着你的数据和真实数
据的对比)
 bytes array 是object
 String 和 bytes array可以相互转化
 String.getBytes() 字符串转bytes array
new String(bytes) bytes转成字符串。PS:本身如果是不可打印字符串,打印是乱码
分类: app逆向

1 条评论

smart contract auditor · 2023-04-22 17:16

I was astonished Ƅү their knowledge off the subject.

评论已关闭。

浙公网安备33011302000604

辽ICP备20003309号