Frida-Labs
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 = 512
this["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 = 1234
Checker.num2.value = 4321
instance.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后的伪代码