Android APP渗透测试(1)-Frida

简介

Frida是一个多平台的hook框架,功能强大,不仅可以进行常规的Hook工作,还可以完成内存扫描,脱壳等工作,Frida是Python API,但是是JavaScript调试逻辑,核心是用C编写的,并将Google的V8引擎注入到目标进程中,在这些进程中,JavaScript可以完全访问内存,挂钩函数甚至调用进程内的本机函数来执行;

安装

Frida的安装非常简单,但是Python版本可能需要3.5以上:

pip install frida
pip install frida-tools

如果报错可以下载源码包安装:

  1. 下载frida-tools源码包。
  2. 修改setup.py文件,如附图2所示,将prompt-toolkit的版本要求去掉。
  3. sudo python setup.py install

查看frida的版本:
version
然后根据不同平台去下载相应frida-server,根据CPU找到相应的服务器server:
Android APP渗透测试(1)-Frida_第1张图片

基本框架

Android:

import frida
import sys
def PrintMessage(message,data):
    if(message["type"] == "send"):
        print("[*] var {0}".format(message["payload"]))
    else:
        print(message)

jscode = '''
    Java.perform(function(){
    
});
'''

p = frida.get_usb_device().attach("com.cn.packname")
script = p.create_script(jscode)
script.on('message',PrintMessage)
script.load()
sys.stdin.read()

实例

这里有一个APP,界面内容我们看看就好,但是居然要积分会员:
Android APP渗透测试(1)-Frida_第2张图片
查壳:
Android APP渗透测试(1)-Frida_第3张图片
很明显,我们需要先脱壳:Android APP渗透测试(1)-Frida_第4张图片
脱壳脚本:

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

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


# 9.0 arm:
arm9 = "_ZN3art13DexFileLoader10OpenCommonEPKhjS2_jRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPKNS_10OatDexFileEbbPS9_NS3_10unique_ptrINS_16DexFileContainerENS3_14default_deleteISH_EEEEPNS0_12VerifyResultE"
# 7.0 arm:
arm7 = "_ZN3art7DexFile10OpenMemoryEPKhjRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEjPNS_6MemMapEPKNS_10OatDexFileEPS9_"

package = sys.argv[1]
print("dex 导出目录为: /data/data/%s"%(package))
device = frida.get_usb_device()
pid = device.spawn(package)
print("pid: %d"%(pid))
session = device.attach(pid)
src = """
Java.perform(function(){
    var exports = Module.enumerateExportsSync("libart.so");
    for(var i=0;i 0) {
            }
        }
    });
});
"""%(arm7,package)

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

然后从/data/data/com.cz.babySister目录拿到dex文件进行分析
Android APP渗透测试(1)-Frida_第5张图片
通过分析我们发现逻辑在5617752.dex当中:
Android APP渗透测试(1)-Frida_第6张图片
我们找到购买积分等的支付逻辑,这里我们可以看到我们可以尝试通过修改oVar.b()的返回值,让他等于9000,看能否内购:

Java.perform(function(){
	var pay = Java.use("com.cz.babySister.alipay.o");
	pay.b.implementation = function(){
		return "9000";
	}
});

查找userinfo之类的类,看看能否修改用户信息,从而修改积分:
Android APP渗透测试(1)-Frida_第7张图片
完整Frida脚本:

import frida
import sys

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

jscode = '''
	Java.perform(function(){
	var pay = Java.use("com.cz.babySister.alipay.o");
	pay.b.implementation = function(){
		return "9000";
	}

	var jifen = Java.use("com.cz.babySister.javabean.UserInfo");
	jifen.getJifen.implementation = function(){
		return "10000";
	}
});
'''

p = frida.get_usb_device().attach("com.cz.babySister")
script = p.create_script(jscode)
script.on('message',PrintMessage)
script.load()
sys.stdin.read()

Android APP渗透测试(1)-Frida_第8张图片
但是很不幸的是,只样很容易被封号的,封号之后连同android_id会一起被拉黑,如果是模拟器可以换android_id,否则只能用脚本:

var sec = Java.use("android.provider.Settings$Secure");
sec.getString.implementation = function(arg1,arg2){
    return "5c80b60f12f73207";
}

其他脚本

Linux:
函数调用

"""
var add = new NativeFunction(ptr("%s"), 'void', ['int','int']);
add(0,1);
"""%(int(sys.argv[1],16))

函数返回值替换:

"""
    //var st = Memory.allocUtf8String(" I love you!");
    Interceptor.attach(ptr("%s"), {
    onEnter: function(args) {
        send("args[0]: " + args[0].toInt32());
        send("args[1]: " + args[1].toInt32());
    },
    onLeave: function(retval){
        send(retval.toInt32());
        retval.replace("7777");
    }
});
"""%(int(sys.argv[1],16))

Android:
so层string替换:

"""
Java.perform(function(){
   Interceptor.attach(Module.findExportByName("libfridaso.so","Java_com_example_fridasostring_fridaSoString_FridaSo"),{
        onEnter: function(args) {
            send("Hook start");
            send("args[2]=" + args[2]);
        },
        onLeave: function(retval){
            send("return:"+retval);
            var env = Java.vm.getEnv();
            var jstrings = env.newStringUtf("tamper");
            retval.replace(jstrings);
        }
    });
});
"""

so层普通替换:

"""
Java.perform(function(){
    Interceptor.attach(Module.findExportByName("libfridaso.so","Java_com_example_fridaso_FridaSoDefine_FridaSo"),{
        onEnter: function(args) {
            send("Hook start");
            send("args[2]=" + args[2]);
            send("args[3]=" + args[3]);
        },
        onLeave: function(retval){
            send("return:"+retval);
            retval.replace(1234);
        }
    });
});
"""

导入导出表:

Java.perform(function(){
    var imports = Module.enumerateImportsSync(""libhello.so"");
    for(var i = 0; i < imports.length; i++) {
        if(imports[i].name == 'strncat'){
            send(imports[i].name + "": "" + imports[i].address);
            break;
        }
    }
    var exports = Module.enumerateExportsSync(""libhello.so"");
    for(var i = 0; i < exports.length; i++) {
        if(exports[i].name.indexOf('add') != -1){
            send(exports[i].name + "": "" + exports[i].address);
            break;
        }
    }
    for(var i = 0; i < imports.length; i++) {
            send(imports[i].name + "": "" + imports[i].address);
        }
        var exports = Module.enumerateExportsSync(""libhello.so"");
        for(var i = 0; i < exports.length; i++) {
                send(exports[i].name + "": "" + exports[i].address);
    }
});

HOOK Linux API:

var pro_addr = Module.findBaseAddress('re');
var show_addr = Number(pro_addr) + Number(0x6f0);
var exports = Module.enumerateExportsSync("/lib/x86_64-linux-gnu/libc.so.6");
   for(var i=0;i<exports.length;i++){
	if(exports[i].name == "printf"){
		var printf_addr = exports[i].address;
		send("name: "+exports[i].name+"  address: "+exports[i].address);
	}
   }
send("pro_addr: " + pro_addr);
send("show_addr: 0x" + show_addr.toString(16));
send("printf: " + printf_addr);

var st1 = Memory.allocUtf8String("I_Love_You %s!");
var st2 = Memory.allocUtf8String("sir");
Interceptor.attach(ptr(printf_addr),{
   onEnter: function(args) {
   		args[0] = ptr(st1);
        args[1] = ptr(st2);
   }
});

你可能感兴趣的:(Android)