0x1
获取了100以内的随机数
只需要确保输入的数为随机数的2倍+4即可
hook该方法,返回值随意,只要自己输入符合对该值的要求即可
Java.perform(function () {let MainActivity = Java.use("com.ad2001.frida0x1.MainActivity");MainActivity["get_random"].implementation = function () {this["get_random"]();console.log('get_random() return 0');return 0;};
})
返回0,输入4即可
0x2
很显然,需要主动调用get_flag方法,将显示的textview修改掉
Java.perform(function () {Java.choose('com.ad2001.frida0x2.MainActivity',{onMatch: function(instance){instance.get_flag(4919)},onComplete: function(){}})
})
采用attach方式进行hook,避免找到实例时,值修改后又被该回去
或者spawn的话用下面的脚本(因为get_flag是静态方法)
Java.perform(function () {let MainActivity = Java.use("com.ad2001.frida0x2.MainActivity");MainActivity["onCreate"].implementation = function (savedInstanceState) {this["onCreate"](savedInstanceState);MainActivity.get_flag(4919)}
0x3
需要修改Checker的code属性的值为512
Java.perform(function () {let MainActivity = Java.use("com.ad2001.frida0x3.MainActivity$1");MainActivity["onClick"].implementation = function (view) {let Checker = Java.use("com.ad2001.frida0x3.Checker")Checker.code.value = 512this["onClick"](view);};
})
在onclick下面hookCheck类,可以最大程度上避免其他类或方法对其产生干扰
0x4
这里应该是考察主动调用,新建一个Check类的实例,调用get_flag,并把值送给textview
Java.perform(function () {let MainActivity = Java.use("com.ad2001.frida0x4.MainActivity");MainActivity["onCreate"].implementation = function (savedInstanceState) {this["onCreate"](savedInstanceState);let Check = Java.use("com.ad2001.frida0x4.Check").$new()let c = Check.get_flag(1337)console.log(c)};
})
直接打印结果即可(我想试着修改textview,结果出现了不知名错误=-=)
0x5
与0x2不同的是,这里的方法不再是静态方法
Java.perform(function () {Java.choose('com.ad2001.frida0x5.MainActivity',{onMatch: function(instance){instance.flag(1337)},onComplete: function(){}})
})
还是attach
0x6
在0x5的基础上,构造Checker即可
Java.perform(function () {Java.choose('com.ad2001.frida0x6.MainActivity',{onMatch: function(instance){let Checker = Java.use('com.ad2001.frida0x6.Checker').$new()Checker.num1.value = 1234Checker.num2.value = 4321instance.get_flag(Checker)},onComplete: function(){}})
})
依旧是attach
0x7
hookChecker的构造方法即可
Java.perform(function () {let Checker = Java.use("com.ad2001.frida0x7.Checker");Checker["$init"].implementation = function (a, b) {console.log('hook $init()')this["$init"](520,520);};
})
0x8
这里就要去看so了,直接hook返回值肯定拿不到正确的flag
每位的ascii码减一就是flag了,但是这里用到了strcmp进行比较
直接hook strcmp
同时看到有打印日志,因此也可以hook日志
0x9
修改native的返回值即可
Java.perform(function () {let MainActivity = Java.use("com.ad2001.a0x9.MainActivity");MainActivity["check_flag"].implementation = function () {this["check_flag"]();console.log(`hook check_flag() return 1337`);return 1337;};
})
0xA
这里就是正常的调用
但是在so里,存在一个导出函数get_flag
可以一眼看出如何解密,但是还是采用hook的方式来做
主动调用一下get_flag,同时还要注意其真正的导出名,不然找不到地址,解密后通过日志输出了
Java.perform(function () {var addr = Module.findExportByName("libfrida0xa.so", "_Z8get_flagii");console.log(addr)let get_flag_pointer = new NativePointer(addr)let get_flag = new NativeFunction(get_flag_pointer,'int',['int','int'])get_flag(1,2)
})
0xB
在so中,由于永假的判断,导致代码不执行,所以可以把jnz给nop掉,一共6个字节
Java.perform(function () {var funAddr = Module.findExportByName("libfrida0xb.so", "Java_com_ad2001_frida0xb_MainActivity_getFlag");var opAddr = funAddr.add(0x1E)console.log(opAddr)var writer = new X86Writer(opAddr)Memory.protect(opAddr,0x1000,'rwx')try{writer.putNop()writer.putNop()writer.putNop()writer.putNop()writer.putNop()writer.putNop()writer.flush()}finally{writer.dispose()}
})
或者是将jnz改成jz,我这里64位的模拟器,jnz的字节码是0f85d2000000,85改成84就是jz
Java.perform(function () {var funAddr = Module.findExportByName("libfrida0xb.so", "Java_com_ad2001_frida0xb_MainActivity_getFlag");var opAddr = funAddr.add(0x1E)console.log(opAddr)var writer = new X86Writer(opAddr)Memory.protect(opAddr,0x1000,'rwx')try{writer.putU8(0x0f)writer.putU8(0x84)writer.putU8(0xd2)writer.putU8(0x0)writer.putU8(0x0)writer.putU8(0x0)writer.flush()}finally{writer.dispose()}
})
这里附上在ida中将jnz改为jz后的伪代码