安卓逆向_24 ( 二 ) --- frida 学习记录
?
轉載:看雪論壇 堂前燕 :https://bbs.pediy.com/thread-252319.htm
apk 和 Python腳本?鏈接:https://pan.baidu.com/s/1KX1fY16NgaYB1FnCrpu0lQ? ? 提取碼:t38k?
?
上次記錄了下xposed hook java層的學習,這次記錄下frida
例子是在上次寫的apk上稍加改動,添加幾個簡單的native方法;
?
?
MainActivity
?
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button bt=(Button)findViewById(R.id.bt1);bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {HookGoal h=new HookGoal(0);h.editnum(1);Log.i("jni str",h.strtest("abcdefg"));DiyClass[] array={new DiyClass(1),new DiyClass(2)};Log.i("jni array","jni調用前 參數數組 成員0: "+array[0].getData()+" 成員1: "+array[1].getData());DiyClass[] myarray=h.arraytest(array);Log.i("jni array","jni調用后 返回新數組 成員0: "+myarray[0].getData()+" 成員1: "+myarray[1].getData());h.show();TextView t=(TextView)findViewById(R.id.sample_text);//t.setText("ooo");t.setText(h.sayhello());//Log.i("jni ","");Toast.makeText(MainActivity.this,"HOOKGOAL",Toast.LENGTH_LONG).show();}});} }?
?
類文件
?
abstract class person {public int age = 0;public void eat(String food) {} }public class HookGoal {static {System.loadLibrary("native-lib");}private static String TAG = "HookGoal:";private int hookGoalNumber;public HookGoal(int number) {hookGoalNumber = number;Log.i(TAG, "HookGoal hookGoalNumber:" + hookGoalNumber);}public void func0() {Log.i(TAG, "welcome");}private void func1() {new person() {@Overridepublic void eat(String food) {Log.i(TAG, "eat " + food);}}.eat("apple");}private static void func2(String s) {Log.i(TAG, "func2 " + s);}private void func3(DiyClass[] arry) {for (int i = 0; i < arry.length; i++)Log.i(TAG, "DiyClass[" + i + "].getData:" + arry[i].getData());}private class InnerClass {private int innerNumber;public InnerClass(String s) {innerNumber = 0;Log.i(TAG, "InnerClass 構造函數 " + s);Log.i(TAG, "InnerClass innerNumber:" + innerNumber);}private void innerFunc(String s) {Log.i(TAG, "InnerClass innerFunc " + s);}}public native String sayhello();public native String strtest(String s);public native DiyClass[] arraytest(DiyClass[] array);public native void editnum(int n);public void show() {Log.i(TAG,"hookGoalNumber:"+hookGoalNumber);func1();func2("私有靜態方法");DiyClass[] arry = {new DiyClass(0), new DiyClass(0), new DiyClass(0)};func3(arry);InnerClass inner = new InnerClass("私有內部類");inner.innerFunc("內部類方法調用");}}public class DiyClass{private int data;public DiyClass(int data){this.data=data;}public int getData() {return data;}public void setData(int data) {this.data = data;} }?
?
native方法,動態注冊
?
int add(int a,int b){return a+b; }static jstring say(JNIEnv *env, jobject) {LOGI("native 函數say()返回字符串my jni hhh");string hello = "my jni hhh";return env->NewStringUTF(hello.c_str()); } static jstring mystr(JNIEnv *env, jobject,jstring s) {char buf[256];env->GetStringUTFRegion(s,0,env->GetStringLength(s),buf);LOGI("GetStringUTFRegion 截取jstring保存到本地buf中:%s",buf);const char* ptr_c=env->GetStringUTFChars(s,NULL);LOGI("GetStringUTFChars 返回const char* 類型:%s",ptr_c);env->ReleaseStringUTFChars(s,ptr_c);const jchar *wc=env->GetStringChars(s, NULL);LOGI("GetStringChars 返回const jchar* 類型");env->ReleaseStringChars(s,wc);jstring js=env->NewStringUTF(buf); /* jstring NewStringUTF(const char* bytes) 返回jstring類型訪問java.lang.String對應的JNI類型jstring時,不能像訪問基本數據類型一樣直接使用,因為它在Java是一個引用類型,所以在本地代碼中只能通過GetStringUTFChars這樣的JNI函數來訪問字符串的內容*/LOGI("NewStringUTF(buf) 返回jstring類型:%s",env->GetStringUTFChars(js,NULL));return env->NewString(wc,env->GetStringLength(s)); } static void edit(JNIEnv *env, jobject obj,jint n) {jint x=add(n,n);LOGI("edit()內調用了add(),原參數:%d",n);jclass clazz=env->GetObjectClass(obj);jfieldID numberid=env->GetFieldID(clazz,"hookGoalNumber","I");env->SetIntField(obj,numberid,x);LOGI("edit()內設置hookGoalNumber字段為:%d",x);} static jobjectArray myarray(JNIEnv *env, jobject obj,jobjectArray array){jclass diyclass=env->FindClass("com/example/goal/DiyClass");jmethodID initid=env->GetMethodID(diyclass,"<init>","(I)V");jmethodID getdataid=env->GetMethodID(diyclass,"getData","()I");jobject a=env->GetObjectArrayElement(array,0);jobject a1=env->GetObjectArrayElement(array,1);jint d=env->CallIntMethod(a,getdataid);jint d1=env->CallIntMethod(a1,getdataid);jobject diy=env->NewObject(diyclass,initid,d);jobject diy2=env->NewObject(diyclass,initid,d1);jobjectArray myarray=env->NewObjectArray(2,diyclass,0);env->SetObjectArrayElement(myarray,0,diy2);env->SetObjectArrayElement(myarray,1,diy);LOGI("myarray()使用array參數,返回交換元素位置的新數組");return myarray; // return env->NewObjectArray(2,diyclass,diy2);}static const char *className = "com/example/goal/HookGoal";static JNINativeMethod gJni_Methods_table[] = {{"editnum", "(I)V", (void*)edit},{"sayhello", "()Ljava/lang/String;",(void*)say},{"strtest", "(Ljava/lang/String;)Ljava/lang/String;",(void*)mystr},{"arraytest","([Lcom/example/goal/DiyClass;)[Lcom/example/goal/DiyClass;",(void*)myarray}};static int jniRegisterNativeMethods(JNIEnv* env, const char* className,const JNINativeMethod* gMethods, int numMethods) {jclass clazz;clazz = (env)->FindClass( className);if (clazz == NULL) {return -1;}int result = 0;if ((env)->RegisterNatives(clazz, gJni_Methods_table, numMethods) < 0) {result = -1;}(env)->DeleteLocalRef(clazz);return result; }jint JNI_OnLoad(JavaVM* vm, void* reserved){JNIEnv* env = NULL;jint result = -1;if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {return result;}jniRegisterNativeMethods(env, className, gJni_Methods_table, sizeof(gJni_Methods_table) / sizeof(JNINativeMethod));return JNI_VERSION_1_4; }?
?
開始 frida hook
?
首先是 java 層 hook
setImmediate(function () {Java.perform(function () {console.log("start");//java層hookvar hookgoal = Java.use("com.example.goal.HookGoal");var clazz = Java.use("java.lang.Class");var obj = Java.use("java.lang.Object");var Exception = Java.use("java.lang.Exception");var str = Java.use("java.lang.String");//hook 構造方法hookgoal.$init.overload("int").implementation = function (number) {send("HookGoal構造函數的參數number:" + number);send("HookGoal構造函數的參數修改為666");return this.$init(666);};//hook 靜態變量TAGvar reflectField = Java.cast(hookgoal.class, clazz).getDeclaredField("TAG");reflectField.setAccessible(true);reflectField.set("java.lang.String", "frida hooking");send("修改HookGoal的靜態變量TAG為:frida hooking");//實例化對象way1var newhg = hookgoal.$new(0);send("new HookGoal instance newhg: " + newhg);// 實例化對象way2var newhg1 = hookgoal.$new.overload("int").call(hookgoal, 0);send("new HookGoal instance newhg1: " + newhg1);//hook匿名內部類,修改參數var nminner = Java.use("com.example.goal.HookGoal$1");nminner.eat.overload("java.lang.String").implementation = function (s) {var arg = arguments[0];send("eat參數獲取 way1:" + arg);send("eat參數獲取 way2:" + s);//修改參數return this.eat("is hooking");};var diy = Java.use("com.example.goal.DiyClass");hookgoal.func2.implementation = function (s) {//func2為靜態方法var arg = arguments[0];send("func2()參數獲取:" + s);//調用成員方法func0()在靜態方法內只能通過創建的實例訪問newhg.func0();send("func2()內調用func0() 通過創建實例newhg調用");newhg1.func0();send("func2()內調用func0() 通過創建實例newhg1調用");//修改實例的hookGoalNumber值,前面hook構造函數時已經將值改為666//修改字段值 通過反射得到字段,//var num1 = Java.cast(newhg1.getClass(), clazz).getDeclaredField("hookGoalNumber");var num1 = Java.cast(hookgoal.class, clazz).getDeclaredField("hookGoalNumber");num1.setAccessible(true);send("實例newhg1的hookGoalNumber:" + num1.get(newhg1));num1.setInt(newhg1, 777);send("修改實例newhg1的hookGoalNumber:" + num1.get(newhg1));send("實例newhg的hookGoalNumber:" + num1.get(newhg));// 反射調用方法var func = hookgoal.class.getDeclaredMethod("func0", null);send("func0:" + func);//var funcs = hookgoal.class.getDeclaredMethods();//for(var i=0;i<funcs.length;i++)// send(""+i+" "+funcs[i]);//invoke(instance,args)調用成員方法func.invoke(newhg1, null);send("func2()內調用func0() way2 通過反射調用");//調用DiyClass內的getData()var d = diy.$new(666);var x = d.getData();send("func2()內調用DiyClass下的getData() 通過創建實例d調用 返回:" + x);//修改func2的參數return this.func2("is hooking");};//修改func3參數hookgoal.func3.implementation = function (array) {//在成員方法func3內調用func0()this.func0();send("func3()內調用func0() way2 成員方法中直接調用其他成員方法");//修改數組參數send("func3參數:" + array);var a = Java.array("com.example.goal.DiyClass", [diy.$new(111), diy.$new(222), diy.$new(333)]);send("func3參數修改:" + a);return this.func3(a);};var inner = Java.use("com.example.goal.HookGoal$InnerClass");//hook內部類inner.$init.overload("com.example.goal.HookGoal", "java.lang.String").implementation = function (clas, arg) {send("innerClass構造函數的參數:" + arg);return this.$init(clas, "frida is hooking");};//hook 內部類方法inner.innerFunc.implementation = function (s) {send("frida hook 前innerFunc()的參數:" + arguments[0]);var num = inner.class.getDeclaredField("innerNumber");num.setAccessible(true);//內部類成員方法中修改成員屬性,way1 通過this.xxx.value 訪問、修改send("通過this.innerNumber.value獲取值:" + this.innerNumber.value);this.innerNumber.value = 1;send("通過this.innerNumber.value設置值后:" + this.innerNumber.value);//way2 先通過反射得到字段,send("反射方式 innerNumber修改前:" + num.get(this));num.setInt(this, 2);send("反射方式 innerNumber修改后:" + num.get(this));return this.innerFunc("frida is hooking");};?
?
native 層 hook
//so層hook//導出函數//var exports = Module.enumerateExportsSync("libnative-lib.so");//for(var i=0;i<exports.length;i++){// send("name:"+exports[i].name+" address:"+exports[i].address);// }//遍歷模塊找基址Process.enumerateModules({onMatch: function (exp) {if (exp.name == 'libnative-lib.so') {send('enumerateModules find');send(exp.name + "|" + exp.base + "|" + exp.size + "|" + exp.path);send(exp);return 'stop';}},onComplete: function () {send('enumerateModules stop');}});//通過模塊名直接查找基址var soAddr = Module.findBaseAddress("libnative-lib.so");send("soAddr:" + soAddr);// hook導出函數 通過函數名send("findExportByName add():" + Module.findExportByName("libnative-lib.so", "_Z3addii"));//send("findExportByName edit():"+Module.findExportByName("libnative-lib.so", "_ZL4editP7_JNIEnvP8_jobjecti"))// Interceptor.attach(Module.findExportByName("xxx.so", "xxxx"), {// onEnter: function (args) {// send("open(" + Memory.readCString(args[0]) + "," + args[1] + ")");// },// onLeave: function (retval) {//// }// });//say(JNIEnv *env, jobject)//edit(JNIEnv *env, jobject,int)//mystr(JNIEnv *env, jobject,jstring s)//myarray(JNIEnv *env, jobject obj, jobjectArray array)// arm64-v8a 下地址//var fadd = 0xED7C;//var fsay=0xF12C;//var fedit=0xF04C;//var fmystr=0xF328;//var fmyarray=0xF4DC;//下面為x86模擬器中地址偏移 arm真機下thumb指令下地址+1var fadd = 0x8AD0;var fsay = 0x8FA0;var fedit = 0x8E70;var fmystr = 0x9200;var fmyarray = 0x9420;//armeabi-v7a//var fadd = 0x839C;var faddptr = new NativePointer(soAddr).add(fadd);//得到內存地址send("函數add() faddptr:" + faddptr);//調用add(5,6)var funadd = new NativeFunction(faddptr, "int", ['int', 'int']);var t = funadd(5, 6);send("調用native 方法fun():" + t);Interceptor.attach(faddptr, {onEnter: function (args) {send("onEnter add()");x = args[0];y = args[1];args[0] = ptr(x * 2);args[1] = ptr(y * 2);send("hook add()修改參數為原來的兩倍 args[0]:" + args[0].toInt32() + " args[1]:" + args[1].toInt32());},onLeave: function (retval) {send("onLeave add()");//retval.replace(678);//send("add()修改返回值為:"+retval.toInt32())}});var fsayptr = new NativePointer(soAddr).add(fsay);Interceptor.attach(fsayptr, {onEnter: function (args) {send("onEnter say()");},onLeave: function (retval) {send("onLeave say()");//jstring類型無法直接輸出顯示,可以類型轉換到java.lang.Stringvar s = Java.cast(retval, str);send("say() 原返回值:" + s);//調用env下的方法,構造jstring類型var env = Java.vm.getEnv();var jstring = env.newStringUtf("frida hook native");retval.replace(ptr(jstring));send("修改say()返回值:" + Java.cast(jstring, str));}});var feditptr = new NativePointer(soAddr).add(fedit);Interceptor.attach(feditptr, {onEnter: function (args) {send("onEnter edit()");send("edit() env:" + args[0] + " jobject:" + args[1] + " jint:" + args[2].toInt32());//參數修改使用new NativePointer(s) 簡寫ptr(s)args[2] = ptr(4);send("hook edit() 修改后的參數jint:" + args[2]);},onLeave: function (retval) {send("onLeave edit()");}});var fmystrptr = new NativePointer(soAddr).add(fmystr);send("fmystrptr:" + fmystrptr);Interceptor.attach(fmystrptr, {onEnter: function (args) {send("onEnter mystr()");send("mystr() env:" + args[0] + " jobject:" + args[1] + " jstring:" + args[2]);var s = Java.cast(args[2], str);send("mystr() jstring參數:" + s);//send("mystr:"+Memory.readUtf16String(args[2],7));//send("mystr:"+Memory.readUtf8String(args[2],7));},onLeave: function (retval) {send("onLeave mystr()");var env = Java.vm.getEnv();var jstring = env.newStringUtf("frida hook native");send("修改返回值jstring:" + jstring);retval.replace(ptr(jstring));}});// Java.choose("com.example.goal.DiyClass",{// onMatch:function(instance){// send("DiyClass instance:"+instance);// },// onComplete:function(){//// }//// });var fmyarrayptr = ptr(soAddr).add(fmyarray);//var fmyarrayptr = new NativePointer(soAddr).add(fmyarray);send("fmyarrayptr:" + fmyarrayptr);//var argptr;Interceptor.attach(fmyarrayptr, {onEnter: function (args) {send("onEnter myarray()");send("mystr() env:" + args[0] + " jobject:" + args[1] + " jobjectArray:" + args[2]);send("jobjectArray參數:" + args[2].toString());//可以在onEnter中通過this.xxx保存變量 在onLeave中通過this.xxx讀取this.argptr = args[2]//jstring 不同于wchar_t* (jchar*) 與 char*//send("mystr:"+Memory.readUtf16String(args[2],7));//send("mystr:"+Memory.readUtf8String(args[2],7));},onLeave: function (retval) {send("onLeave myarray()");send("argptr:" + this.argptr);var env = Java.vm.getEnv();var cla = env.findClass("com/example/goal/DiyClass");send("clazz:" + cla);var initid = env.getMethodId(cla, "<init>", "(I)V");send("initid:" + initid);var setid = env.getMethodId(cla, "setData", "(I)V");send("setid:" + setid);var getid = env.getMethodId(cla, "getData", "()I");send("getid:" + getid);//frida 中env 方法參考frida-java/lib/env.js 本人能力有限,有些方法確實搞不懂//調用env中的allocObject()方法創建對象,未初始化,var obj1 = env.allocObject(cla);send("obj1:" + obj1);var obj2 = env.allocObject(cla);send("obj2:" + obj2);var rtarray = env.newObjectArray(2, cla, ptr(0));send("env.newObjectArray:" + rtarray);//獲取DiyClass類中public void setData(int data)方法var nvmethod = env.nonvirtualVaMethod("void", ["int"]);//NativeType CallNonvirtual<type>Method(JNIEnv *env, jobject obj,jclass clazz, jmethodID methodID, ...);//設置obj1中data值nvmethod(env, obj1, cla, setid, 11);//設置obj2中data值nvmethod(env, obj2, cla, setid, 22);send("env.nonvirtualVaMethod(JNIEnv,jobject,jclass,jmethodid,args):" + nvmethod);//設置數組中的元素env.setObjectArrayElement(rtarray, 0, obj1);env.setObjectArrayElement(rtarray, 1, obj2);send("env.newObjectArray:" + rtarray);send("原retval:" + retval);retval.replace(ptr(rtarray));send("修改后retval:" + retval);// //堆中分配空間// var memo=Memory.alloc(4);// //寫入數據// Memory.writeInt(memo,0x40302010);// // 讀取數據// console.log(hexdump(memo, {// offset: 0,// length: 64,// header: true,// ansi: true// }));}});}); });?
?
寫好的 js 放到 python 執行
import frida, sysdef on_message(message, data):if message['type'] == 'send':print("[*] {0}".format(message['payload']))else:print(message)jscode = """ <js代碼放到這里>""" # 啟動時hook //在測試時出現了問題 # devices=frida.get_usb_device() # pid=devices.spawn(['com.example.goal']) #以掛起方式創建進程 真機報錯frida.PermissionDeniedError: unable to access process #找到原因了,我的是Android8.0 使用了Magisk,默認開啟了Magisk Hide選項與zygote64沖突。 #解決方法:Magisk -->設置-->Magisk下 去掉勾選Magisk Hide #模擬器報錯Failed to spawn: the connection is closed # session=devices.attach(pid) # devices.resume(pid) #創建完腳本, 恢復進程運行 # script=session.create_script(jscode)# 命令行frida -U -f com.example.goal --no-pause -l <hook.js># 運行中hook process = frida.get_usb_device().attach('com.example.goal') script = process.create_script(jscode) script.on('message', on_message) print('[*] Running test') script.load() sys.stdin.read()也可以使用 frida 命令行 打開 .js? (打印使用 console.log() )
frida -U <進程名或pid> -l <js文件>
?
代碼中涉及到的一些點大部分給出了注釋,當然你只能這里看到一丟丟的 frida 方法的使用,更多的方法還要請參考官方文檔、源代碼···
例如native層會用到大量frida JavaScript API 的Memory 操作,
frida中的env方法與jni開發中的方法并不完全相同,請參考源碼frida-java/lib/env.js,
代碼中涉及到的地址偏移請根據實際情況修改
?
?
hook 前 log 輸出
4513-4513/com.example.goal I/frida hooking: HookGoal hookGoalNumber:0 4513-4513/com.example.goal I/jni test: edit()內調用了add(),原參數:1 4513-4513/com.example.goal I/jni test: edit()內設置hookGoalNumber字段為:2 4513-4513/com.example.goal I/jni test: GetStringUTFRegion 截取jstring保存到本地buf中:abcdefg 4513-4513/com.example.goal I/jni test: GetStringUTFChars 返回const char* 類型:abcdefg 4513-4513/com.example.goal I/jni test: GetStringChars 返回const jchar* 類型 4513-4513/com.example.goal I/jni str: abcdefg 4513-4513/com.example.goal I/jni array: jni調用前 參數數組 成員0: 1 成員1: 2 4513-4513/com.example.goal I/jni test: myarray()使用array參數,返回交換元素位置的新數組 4513-4513/com.example.goal I/jni array: jni調用后 返回新數組 成員0: 2 成員1: 1 4513-4513/com.example.goal I/frida hooking: hookGoalNumber:2 4513-4513/com.example.goal I/frida hooking: eat apple 4513-4513/com.example.goal I/frida hooking: func2 私有靜態方法 4513-4513/com.example.goal I/frida hooking: DiyClass[0].getData:0 4513-4513/com.example.goal I/frida hooking: DiyClass[1].getData:0 4513-4513/com.example.goal I/frida hooking: DiyClass[2].getData:0 4513-4513/com.example.goal I/frida hooking: InnerClass 構造函數 私有內部類 4513-4513/com.example.goal I/frida hooking: InnerClass innerNumber:0 4513-4513/com.example.goal I/frida hooking: InnerClass innerFunc 內部類方法調用 4513-4513/com.example.goal I/jni test: native 函數say()返回字符串my jni hhh?
hoo k后 log 輸出
4513-4513/com.example.goal I/frida hooking: HookGoal hookGoalNumber:666 4513-4513/com.example.goal I/jni test: edit()內調用了add(),原參數:4 4513-4513/com.example.goal I/jni test: edit()內設置hookGoalNumber字段為:16 4513-4513/com.example.goal I/jni test: GetStringUTFRegion 截取jstring保存到本地buf中:abcdefg 4513-4513/com.example.goal I/jni test: GetStringUTFChars 返回const char* 類型:abcdefg 4513-4513/com.example.goal I/jni test: GetStringChars 返回const jchar* 類型 4513-4513/com.example.goal I/jni str: frida hook native 4513-4513/com.example.goal I/jni array: jni調用前 參數數組 成員0: 1 成員1: 2 4513-4513/com.example.goal I/jni test: myarray()使用array參數,返回交換元素位置的新數組 4513-4513/com.example.goal I/jni array: jni調用后 返回新數組 成員0: 11 成員1: 22 4513-4513/com.example.goal I/frida hooking: hookGoalNumber:16 4513-4513/com.example.goal I/frida hooking: eat is hooking 4513-4513/com.example.goal I/frida hooking: welcome 4513-4513/com.example.goal I/frida hooking: welcome 4513-4513/com.example.goal I/frida hooking: welcome 4513-4513/com.example.goal I/frida hooking: func2 is hooking 4513-4513/com.example.goal I/frida hooking: welcome 4513-4513/com.example.goal I/frida hooking: DiyClass[0].getData:111 4513-4513/com.example.goal I/frida hooking: DiyClass[1].getData:222 4513-4513/com.example.goal I/frida hooking: DiyClass[2].getData:333 4513-4513/com.example.goal I/frida hooking: InnerClass 構造函數 frida is hooking 4513-4513/com.example.goal I/frida hooking: InnerClass innerNumber:0 4513-4513/com.example.goal I/frida hooking: InnerClass innerFunc frida is hooking 4513-4513/com.example.goal I/jni test: native 函數say()返回字符串my jni hhh?
?
hook 腳本的輸出
[*] Running test start [*] 修改HookGoal的靜態變量TAG為:frida hooking [*] HookGoal構造函數的參數number:0 [*] HookGoal構造函數的參數修改為666 [*] new HookGoal instance newhg: com.example.goal.HookGoal@4a854cb4 [*] HookGoal構造函數的參數number:0 [*] HookGoal構造函數的參數修改為666 [*] new HookGoal instance newhg1: com.example.goal.HookGoal@4a854f70 [*] enumerateModules find [*] libnative-lib.so|0x7d0b0000|221184|/data/app-lib/com.example.goal-1/libnative-lib.so [*] {'name': 'libnative-lib.so', 'base': '0x7d0b0000', 'size': 221184, 'path': '/data/app-lib/com.example.goal-1/libnative-lib.so'} [*] enumerateModules stop [*] soAddr:0x7d0b0000 [*] 函數add() nativeptr:0x7d0b8ad0 [*] 調用native 方法fun():11 [*] findExportByName add():0x7d0b8ad0 [*] fmystrptr:0x7d0b9200 [*] fmyarrayptr:0x7d0b9420 [*] HookGoal構造函數的參數number:0 [*] HookGoal構造函數的參數修改為666 [*] onEnter edit() [*] edit() env:0xb83a6e50 jobject:0xf7c00025 jint:1 [*] hook edit() 修改后的參數jint:0x4 [*] onEnter add() [*] hook add()修改參數為原來的兩倍 args[0]:8 args[1]:8 [*] onLeave add() [*] onLeave edit() [*] onEnter mystr() [*] mystr() env:0xb83a6e50 jobject:0xf7d00025 jstring:0x3d300029 [*] mystr() jstring參數:abcdefg [*] onLeave mystr() [*] 修改返回值jstring:0xc5b00035 [*] onEnter myarray() [*] mystr() env:0xb83a6e50 jobject:0xf8000025 jobjectArray:0x3d600029 [*] jobjectArray參數:0x3d600029 [*] onLeave myarray() [*] argptr:0x3d600029 [*] clazz:0x26800045 [*] initid:0x881d1ea8 [*] setid:0x881d1f20 [*] getid:0x881d1ee8 [*] obj1:0x1e000049 [*] obj2:0x1e00004d [*] env.newObjectArray:0x1dc00051 [*] env.nonvirtualVaMethod(JNIEnv,jobject,jclass,jmethodid,args):0xb4d88bb0 [*] env.newObjectArray:0x1dc00051 [*] 原retval:0x2f900041 [*] 修改后retval:0x1dc00051 [*] eat參數獲取 way1:apple [*] eat參數獲取 way2:apple [*] func2()參數獲取:私有靜態方法 [*] func2()內調用func0() 通過創建實例newhg調用 [*] func2()內調用func0() 通過創建實例newhg1調用 [*] 實例newhg1的hookGoalNumber:666 [*] 修改實例newhg1的hookGoalNumber:777 [*] 實例newhg的hookGoalNumber:666 [*] func0:public void com.example.goal.HookGoal.func0() [*] func2()內調用func0() way2 通過反射調用 [*] func2()內調用DiyClass下的getData() 通過創建實例d調用 返回:666 [*] func3()內調用func0() way2 成員方法中直接調用其他成員方法 [*] func3參數:com.example.goal.DiyClass@4a8596b4,com.example.goal.DiyClass@4a8596bc,com.example.goal.DiyClass@4a8596c4 [*] func3參數修改:com.example.goal.DiyClass@4a859a08,com.example.goal.DiyClass@4a859a78,com.example.goal.DiyClass@4a859ae8 [*] innerClass構造函數的參數:私有內部類 [*] frida hook 前innerFunc()的參數:內部類方法調用 [*] 通過this.innerNumber.value獲取值:0 [*] 通過this.innerNumber.value設置值后:1 [*] 反射方式 innerNumber修改前:1 [*] 反射方式 innerNumber修改后:2 [*] onEnter say() [*] onLeave say() [*] say() 原返回值:my jni hhh [*] 修改say()返回值:frida hook nativefrida功能十分強大,在這里我作為初學者簡單的記錄了下學習經歷,當然這僅僅是一些常規操作,是基礎,日后的學習應該是在實戰中,實踐出真知。
合抱之木,生于毫末;九層之臺,起于累土;千里之行,始于足下
我在學習的過程之中也遇到了各種各樣的坑,困惑過,苦惱過。解決問題絕對是一種很棒的學習方式,
希望各位能夠提出自己的問題,大家一起交流,共同成長!
同時文中難免會有錯誤,歡迎各位壇友指出,不勝感激!
(打好基礎,改日實戰一番!)
?
?
?
?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的安卓逆向_24 ( 二 ) --- frida 学习记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第1章 Hello MFC
- 下一篇: Java Web开发技术详解~MIME类