1、hook相关 1.1、获取进程名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import fridardev = frida.get_remote_device() front_app = rdev.get_frontmost_application() print (front_app)
1.2、端口转发 1 2 3 4 import subprocesssubprocess.getoutput("adb forward tcp:27042 tcp:27042" ) subprocess.getoutput("adb forward tcp:27043 tcp:27043" )
1.3、python_hook 1.3.1、手动hook_附加的形式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import fridaimport sysrdev = frida.get_remote_device() session = rdev.attach("车智赢+" ) scr = """ Java.perform(function () { // 包.类 var SecurityUtil = Java.use("com.autohome.ahkit.utils.SecurityUtil"); SecurityUtil.encodeMD5.implementation = function(str){ console.log("明文:",str); var res = this.encodeMD5(str); console.log("md5加密结果=",res); return "305eb636-eb15-4e24-a29d-9fd60fbc91bf"; } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() sys.stdin.read()
1.3.2、自启动hook_spawn形式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import fridaimport sysrdev = frida.get_remote_device() pid = rdev.spawn(["com.hupu.shihuo" ]) session = rdev.attach(pid) scr = """ Java.perform(function () { var UpdateDialog = Java.use('com.azhon.appupdate.dialog.UpdateDialog'); UpdateDialog.show.implementation = function(ctx){ //this.show(); } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() rdev.resume(pid) sys.stdin.read()
1.4、反调试 1.4.1、Frida反调试
app运行时,都加载了哪些so文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import fridaimport sysrdev = frida.get_remote_device() pid = rdev.spawn(["com.hupu.shihuo" ]) session = rdev.attach(pid) scr = """ Java.perform(function () { var dlopen = Module.findExportByName(null, "dlopen"); var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext"); Interceptor.attach(dlopen, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen:]", path); }, onLeave: function (retval) { } }); Interceptor.attach(android_dlopen_ext, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen_ext:]", path); }, onLeave: function (retval) { } }); }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() rdev.resume(pid) sys.stdin.read()
1.4.2、strongR-frida-android反调试
有些app运行时会监测frida的相关特征,监测到之后就会直接闪退。
此时我们可以尝试使用strongR-frida-android
来绕过监测。
将此处的frida-server解压,并上传到手机的 /data/local/tmp/
目录,然后赋予可执行权限chmod 755 文件
。(过程同之前的frida-server的处理)
1.5、hook_Map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import fridaimport sysrdev = frida.get_remote_device() session = rdev.attach("识货" ) scr = """ Java.perform(function () { var TreeMap = Java.use('java.util.TreeMap'); var Map = Java.use("java.util.Map"); TreeMap.put.implementation = function (key,value) { if(key=="data"){ console.log(key,value); } var res = this.put(key,value); return res; } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() sys.stdin.read()
1.6、hook_StringBuilder 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import fridaimport sysrdev = frida.get_remote_device() session = rdev.attach("识货" ) scr = """ Java.perform(function () { var StringBuilder = Java.use("java.lang.StringBuilder"); StringBuilder.toString.implementation = function () { var res = this.toString(); console.log(res); return res; } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() sys.stdin.read()
1.7、hook拦截器 1.7.1、hook_所有注册拦截器_python版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import fridaimport sysrdev = frida.get_remote_device() session = rdev.attach("识货" ) scr = """ Java.perform(function () { var a = Java.use("cn.shihuo.modulelib.startup.core.c.a"); a.intercept.implementation = function (chain) { var req = chain.request(); var httpUrl = req.url().toString(); if( httpUrl.indexOf("https://sh-gateway.shihuo.cn/v4/services/sh-goodsapi/app_swoole_shoe/preload/single") != -1 ){ console.log('执行前',httpUrl); } var res = this.intercept(chain); return res; } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() sys.stdin.read()
1.7.2、hook_所有注册拦截器_js版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Java .perform (function ( ) { var Builder = Java .use ('okhttp3.OkHttpClient$Builder' ); Builder .addInterceptor .implementation = function (inter ) { console .log (JSON .stringify (inter) ); return this .addInterceptor (inter); }; })
1.8、hook_base64 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import fridaimport sysrdev = frida.get_remote_device() session = rdev.attach("识货" ) scr = """ Java.perform(function () { var Base64 = Java.use("android.util.Base64"); // 重载 Base64.encodeToString.overload('[B', 'int').implementation = function (bArr,val) { var res = this.encodeToString(bArr,val); console.log("加密了-->",res); return res; } }); """ script = session.create_script(scr) def on_message (message, data ): print (message, data) script.on("message" , on_message) script.load() sys.stdin.read()
1.9、调用栈输出
console.log(Java.use(“android.util.Log”).getStackTraceString(Java.use(“java.lang.Throwable”).$new()));
1.10、hook内存中的函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var addr = Module .findExportByName ("libkeyinfo.so" , "getByteHash" );console .log (addr); Interceptor .attach (addr,{ onEnter :function (args ){ this .x1 = args[2 ]; }, onLeave :function (retval ) { console .log ("--------------------" ) console .log (Memory .readCString (this .x1 )); console .log (Memory .readCString (retval)); } })
1.10.1、延迟hook 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 function do_hook ( ) { var addr = Module .findExportByName ("libkeyinfo.so" , "getByteHash" ); console .log (addr); Interceptor .attach (addr, { onEnter : function (args ) { this .x1 = args[2 ]; }, onLeave : function (retval ) { console .log ("--------------------" ) console .log (Memory .readCString (this .x1 )); console .log (Memory .readCString (retval)); } }) } function load_so_and_hook ( ) { var dlopen = Module .findExportByName (null , "dlopen" ); var android_dlopen_ext = Module .findExportByName (null , "android_dlopen_ext" ); Interceptor .attach (dlopen, { onEnter : function (args ) { var path_ptr = args[0 ]; var path = ptr (path_ptr).readCString (); this .path = path; }, onLeave : function (retval ) { if (this .path .indexOf ("libkeyinfo.so" ) !== -1 ) { console .log ("[dlopen:]" , this .path ); do_hook (); } } }); Interceptor .attach (android_dlopen_ext, { onEnter : function (args ) { var path_ptr = args[0 ]; var path = ptr (path_ptr).readCString (); this .path = path; }, onLeave : function (retval ) { if (this .path .indexOf ("libkeyinfo.so" ) !== -1 ) { console .log ("\nandroid_dlopen_ext加载:" , this .path ); do_hook (); } } }); } load_so_and_hook ();
2、加密相关 2.1、md5加密 1 2 3 4 5 6 7 import hashlibobj = hashlib.md5() obj.update("123123" .encode('utf-8' )) res = obj.hexdigest() print (res)
2.2、3DES加密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import base64from Crypto.Cipher import DES3BS = 8 pad = lambda s: s + (BS - len (s) % BS) * chr (BS - len (s) % BS) key = b'appapiche168comappapiche168comap' [0 :24 ] iv = b'appapich' plaintext = pad("xxxxxxxxx" ).encode("utf-8" ) cipher = DES3.new(key, DES3.MODE_CBC, iv) result = cipher.encrypt(plaintext) res = base64.b64encode(result) print (res)
2.3、AESEncrypt.encode+base64算法加密 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from Crypto.Cipher import AESfrom Crypto.Util.Padding import padimport base64def aes_encrypt (data_string ): key = "d245a0ba8d678a61" aes = AES.new( key=key.encode('utf-8' ), mode=AES.MODE_ECB, ) raw = pad(data_string.encode('utf-8' ), 16 ) return aes.encrypt(raw) data_string = "abFeedHuatiCard0deliveryProjectId0lastId1limit20loginTokenpage8platformandroidtimestamp1678960253053uuid0d9686a78e2aa975v5.0.6" res = aes_encrypt(data_string) value = base64.encodebytes(res) result = value.replace(b"\n" , b'' ) print (result)
3、经验之谈 3.1、抓包问题
在Charles上抓不到包解决:SocksDroid(推荐)
手机系统代理删除
基本配置 –> 图片找不到了,兄弟们自行搜索吧,很简单的
3.2、System.nanoTime()
安卓中System.nanoTime() 代表着 开机 ~ 当前时间差
1 2 3 import randomnano_time = random.randint(5136066335773 ,7136066335773 )
3.3、解决强制更新
注意:后端API没有更新的情况下。
3.4.1 Python传参 在Python中给frida的JavaScript脚本传入参数时,一般有如下几种情况:
3.4.2 JavaScript 在frida的脚本中其实就用编写JavaScript代码,所以我们对于内部的执行过程完全是使用JavaScript语法来实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import fridardev = frida.get_remote_device() session = rdev.attach("大姨妈" ) scr = """ rpc.exports = { encrypt:function(v1,v2){ console.log(v1,typeof v1, v1[0], v1[1]); console.log(v2,typeof v2, v2.name, v2.age); for(let key in v1){ console.log(key,v1[key]) } for(let key in v2){ console.log(key,v2[key]) } } } """ script = session.create_script(scr) script.load() script.exports.encrypt([11 , 22 , 33 ], {"name" : 123 , "age" : 456 })
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import fridardev = frida.get_remote_device() session = rdev.attach("大姨妈" ) scr = """ rpc.exports = { encrypt:function(bytesList){ // [11,22,33,11,22,42,13,4] // 先处理拼接好的数据(字节数组) var bArr = []; for(var i=0;i<bytesList.length;i+=2){ var item = (parseInt(bytesList[i],16) << 4) + parseInt(bytesList[i+1],16); bArr.push(item); } console.log(bArr); // 转换为java的字节数组 var bs = Java.array('byte',bArr); } } """ script = session.create_script(scr) script.load() arg_bytes = "wupeiqi" .encode('utf-8' ) byte_list = [i for i in arg_bytes] script.exports.encrypt(byte_list)
3.4.3 Frida相关 在编写frida的JavaScript脚本时,我们经常会:
调用Java中已编写的好的类、方法等功能
执行目标方法时,传入相关参数。
这种情况下,就需要使用frida相关API来完成JavaScript和Java中的调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import fridardev = frida.get_remote_device() session = rdev.attach("大姨妈" ) scr = """ rpc.exports = { encrypt:function(v1,v2,v3,v4){ // 1.整型和字符串直接用 console.log(v1,v2); // 2.字节数组 var v3_obj = Java.array('byte',v3); console.log(v3_obj, JSON.stringify(v3_obj)); // 3.TreeMap对象 obj.get("xx") var TreeMap = Java.use("java.util.TreeMap"); var v4_obj = TreeMap.$new(); for(let key in v4){ //console.log(key,v4[key]); v4_obj.put(key,v4[key]) } console.log( v4_obj ) console.log( v4_obj.get("name") ) console.log( v4_obj.get("age") ) var keyset = v4_obj.keySet(); var it = keyset.iterator(); while(it.hasNext()){ var keystr = it.next().toString(); var valuestr = v4_obj.get(keystr).toString(); console.log(keystr, valuestr); } } } """ script = session.create_script(scr) script.load() v3 = [i for i in "wupeiqi" .encode('utf-8' )] script.exports.encrypt(10 , "wupeiqi" , v3, {"name" : "root" , "age" : "18" })
3.5、脱壳
例如:arm pro、frida-dump、反射大师、BackDex32、FART、youpk
1 >pip install frida-dexdump
想要使用frida-dexdump
来进行脱壳,必须做如下两个步骤:
手机端,启动frida-server
电脑端
端口转发
执行脱壳命令
脱壳后,会生成相应的dex文件,例如:
1 >frida-dexdump -U -f com.jiuxianapk.ui
__END__