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后的偽代碼


浙公網安備 33010602011771號