Frida 学习(Frida-Labs) 不能当Ai高手,还得学学
练习项目地址:DERE-ad2001/Frida-Labs: The repo contains a series of challenges for learning Frida for Android Exploitation.
Frida 0x1 i是random出来的,我们要向输出可以重新调用check
1 2 3 4 5 6 7 Java .perform (function ( ){ let MainActivity = Java .use ("com.ad2001.frida0x1.MainActivity" ); MainActivity ["check" ].implementation = function (i, i2 ) { console .log ('check is called' + ', ' + 'i: ' + i + ', ' + 'i2: ' + i2); this .check (1 , 6 ); }; })
1 2 3 4 5 6 7 Java .perform (function ( ){ let MainActivity = Java .use ("com.ad2001.frida0x1.MainActivity" ); MainActivity .check .implementation = function (i, i2 ) { console .log ('check is called' + ', ' + 'i: ' + i + ', ' + 'i2: ' + i2); this .check (1 , 6 ); }; })
都行
1 frida -U -F -l .\frida0x1.js
或
1 frida -U -f com.ad2001.frida0x2 -l frida1.js
Frida 0x2
未被调用,需要主动调用
1 2 3 4 function frida_2 ( ) { let MainActivity = Java .use ("com.ad2001.frida0x2.MainActivity" ); MainActivity .get_flag (4919 ); }
Frida 0x3
需要hook checker.code
1 2 3 4 Java .perform (function ( ) { var a = Java .use ("com.ad2001.frida0x3.Checker" ); a.code .value = 0x200 ; });
Frida 0x4
没有对类实例化
1 2 3 4 5 6 function frida_5 ( ) { var a = Java .use ("com.ad2001.frida0x4.Check" ); var check = a.$new(); var flag = check.get_flag (0x539 ); console .log ("flag: " ,flag); }
Frida 0x5 与上题不同,已经初始化了这个实例
1 2 3 4 5 6 7 8 9 function frida_5 ( ) { Java .choose ('com.ad2001.frida0x5.MainActivity' ,{ onMatch : function (instance ){ instance.flag (1337 ) }, onComplete : function ( ){ } }) }
Frida 0x6 接受一个对象实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function frida_6 ( ) { Java .choose ('com.ad2001.frida0x6.MainActivity' ,{ onMatch : function (instance ){ var checker = Java .use ("com.ad2001.frida0x6.Checker" ); var C_New = checker.$new(); C_New.num1 .value = 0x4D2 ; C_New.num2 .value = 0x10E1 ; instance.get_flag (C_New); }, onComplete : function ( ){ } }) }
Frida 0x7 与上题不同的是
法一,同上题,无非是多了个构造函数,我们按构造函数传参即可
1 2 3 4 5 6 7 8 9 10 11 12 function frida_7 ( ) { Java .choose ('com.ad2001.frida0x7.MainActivity' ,{ onMatch : function (instance ){ var checker = Java .use ("com.ad2001.frida0x7.Checker" ); var C_New = checker.$new(0x201 ,0x201 ); instance.flag (C_New); }, onComplete : function ( ){ } }) }
法2:hook构造函数
1 2 3 4 5 6 function frida_7_5 ( ) { var a = Java .use ("com.ad2001.frida0x7.Checker" ); a.$init .implementation = function (param ){ this .$init(0x201 ,0x201 ); } }
Frida 0x8 cmpstr来自so层
可以看到Java_com_ad2001_frida0x8_MainActivity_cmpstr中获取了我们的输入,并将这段输入使用strcmp函数与一段密文s2进行比较,当它们相等时,将会返回0
所以我们可以直接hook strcmp函数,输出他的两个参数,第二个参数就是密文了
需要输入Closure
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 function frida_1 ( ) { let MainActivity = Java .use ("com.ad2001.frida0x1.MainActivity" ); MainActivity .check .implementation = function (i, i2 ) { console .log ('check is called' + ', ' + 'i: ' + i + ', ' + 'i2: ' + i2); this .check (1 , 6 ); }; } function frida_2 ( ) { let MainActivity = Java .use ("com.ad2001.frida0x2.MainActivity" ); MainActivity .get_flag (4919 ); } function frida_3 ( ) { let Checker = Java .use ("com.ad2001.frida0x3.Checker" ); Checker .code .value = 0x200 ; } function frida_4 ( ) { var a = Java .use ("com.ad2001.frida0x4.Check" ); var check = a.$new(); var flag = check.get_flag (0x539 ); console .log ("flag: " ,flag); } function frida_5 ( ) { Java .choose ('com.ad2001.frida0x5.MainActivity' ,{ onMatch : function (instance ){ instance.flag (1337 ) }, onComplete : function ( ){ } }) } function frida_6 ( ) { Java .choose ('com.ad2001.frida0x6.MainActivity' ,{ onMatch : function (instance ){ var checker = Java .use ("com.ad2001.frida0x6.Checker" ); var C_New = checker.$new(); C_New.num1 .value = 0x4D2 ; C_New.num2 .value = 0x10E1 ; instance.get_flag (C_New); }, onComplete : function ( ){ } }) } function frida_7 ( ) { Java .choose ('com.ad2001.frida0x7.MainActivity' ,{ onMatch : function (instance ){ var checker = Java .use ("com.ad2001.frida0x7.Checker" ); var C_New = checker.$new(0x201 ,0x201 ); instance.flag (C_New); }, onComplete : function ( ){ } }) } function frida_7_5 ( ) { var a = Java .use ("com.ad2001.frida0x7.Checker" ); a.$init .implementation = function (param ){ this .$init(0x201 ,0x201 ); } } function frida_8 ( ) { var all_0x8_exp = Module .enumerateExports ("libfrida0x8.so" ); console .log ("libfrida0x8.so 所有导出函数:\n" ,JSON .stringify (all_0x8_exp, null , 2 )); var cmpstr_addr = Module .getExportByName ("libfrida0x8.so" ,"Java_com_ad2001_frida0x8_MainActivity_cmpstr" ) var strcmp_addr = Module .getExportByName ("libc.so" , "strcmp" ) var strcmp_null_addr = Module .getExportByName (null , "strcmp" ) console .log ("\ncmpstr_addr:" ,cmpstr_addr); console .log ("strcmp_addr:" ,strcmp_addr); console .log ("strcmp_null_addr:" ,strcmp_null_addr); var Closure _addr = Module .findExportByName ("libfrida0x8.so" ,"Closure" ) console .log ("Closure_addr:" ,Closure _addr); var libc_base = Module .getBaseAddress ("libfrida0x8.so" ) console .log ("libc_base:" ,libc_base); var libc_base_add_cmpstr = Module .getBaseAddress ("libfrida0x8.so" ).add (0x8c0 ) console .log ("libc_base_add_cmpstr:" ,libc_base_add_cmpstr); var all_0x8_imp = Module .enumerateImports ("libfrida0x8.so" ) console .log ("libfrida0x8.so 所有导入函数:\n" ,JSON .stringify (all_0x8_imp, null , 2 )); var strcmp_addr = Module .findExportByName ("libc.so" , "strcmp" ); var out_put; Interceptor .attach (strcmp_addr, { onEnter : function (args ) { var arg0 = Memory .readUtf8String (args[0 ]); var flag = Memory .readUtf8String (args[1 ]); out_put = arg0; if (arg0.includes ("Closure" )) { console .log ("args[0]: " ,arg0); console .log ("args[1]: " ,flag); } }, onLeave : function (retval ) { if (out_put.includes ("Closure" )) { retval.replace (0 ); } } }); } Java .perform (function ( ){ frida_8 (); });
Frida 0x9
checkflag返回1
1 2 3 4 5 6 7 8 9 10 11 function frida_9 ( ) { var flag_addr = Module .findExportByName ("liba0x9.so" , "Java_com_ad2001_a0x9_MainActivity_check_1flag" ); Interceptor .attach (flag_addr, { onEnter : function (args ) { }, onLeave : function (retval ) { retval.replace (0x539 ); } }); }
Frida 0xA
没有什么,但是so层有个get_flag需要主动调用才能输出flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function frida_A ( ) { var get_flag_addr = Module .findExportByName ("libfrida0xa.so" ,"get_flag" ) console .log ("get_flag_addr:" ,get_flag_addr); var get_flag_addr = Module .findBaseAddress ("libfrida0xa.so" ).add (0x206B0 ) console .log ("get_flag_addr:" ,get_flag_addr); var get_flag_ptr = new NativePointer (get_flag_addr); const get_flag = new NativeFunction (get_flag_ptr, 'void' , ['int' , 'int' ]); get_flag (1 ,2 ); } Java .perform (function ( ){ frida_A (); });
Frida 0xB 程序加载了frida0xb库,引用getFlag函数,点击按钮将调用getFlag函数:
定位到getflag
能看到在汇编中对比了0xDEADBEEF和0x539,这当然是不相等的
程序将会直接返回,我们需要让getFlag执行关于flag的相关代码,将JNZ改为JMP或者修改0xDEADBEEF为0x539,或者nop掉相关校验逻辑
nop完为
我这是Arm架构的使用Arm64Writer(真机)
x86_64可以看通过Frida-Labs入门Frida | Closure
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 function frida_B ( ) { var soName = "libfrida0xb.so" ; var base = Module .getBaseAddress (soName); console .log ("arch:" , Process .arch ); console .log ("base:" , base); var offset = 0x15248 ; var target = base.add (offset); console .log ("patch addr:" , target); var orig = Instruction .parse (target); console .log ("before:" , orig.toString ()); var orig2 = Instruction .parse (base.add (0x000000000001524C )); console .log ("before2:" , orig2.toString ()); Memory .patchCode (target, 1 , function (code ) { var cw = new Arm64Writer (code, { pc : target }); cw.putNop (); cw.flush (); }); var now = Instruction .parse (target); console .log ("after:" , now.toString ()); var now2 = Instruction .parse (base.add (0x000000000001524C )); console .log ("after2:" , now2.toString ()); } Java .perform (function ( ) { frida_B (); });