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:
frida_sever

基本框架

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,界面內容我們看看就好,但是居然要積分會員:
積分
查殼:
殼
很明顯,我們需要先脫殼:脫殼
脫殼腳本:

#-*- 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<exports.length;i++){
        if(exports[i].name == "%s"){
            var openMemory = new NativePointer(exports[i].address);
            }
     }

    Interceptor.attach(openMemory, {
        onEnter: function (args) {
        
            var begin = args[1]
            
            send("magic : " + Memory.readUtf8String(begin))
        
            var address = parseInt(begin,16) + 0x20

            var dex_size = Memory.readInt(ptr(address))

            send("dex_size :" + dex_size)
        
            var file = new File("/data/data/%s/" + dex_size + ".dex", "wb")
            file.write(Memory.readByteArray(begin, dex_size))
            file.flush()
            file.close()

            var send_data = {}
            send_data.base = parseInt(begin,16)
            send_data.size = dex_size
            send(send_data)
        },
        onLeave: function (retval) {
            if (retval.toInt32() > 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文件進行分析
pwd
通過分析我們發現邏輯在5617752.dex當中:
支付
我們找到購買積分等的支付邏輯,這裏我們可以看到我們可以嘗試通過修改oVar.b()的返回值,讓他等於9000,看能否內購:

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

查找userinfo之類的類,看看能否修改用戶信息,從而修改積分:
userinfo
完整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()

vip
但是很不幸的是,只樣很容易被封號的,封號之後連同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);
    }
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章