好友
阅读权限 40
听众
最后登录 1970-1-1
漁滒
发表于 2021-3-5 12:54
逆向之前需要准备以下一些工具
1.ApkScan-PKID(用于apk查壳)
2.jadx-gui-1.2.0(用于反编译apk)
3.IDA _Pro_v7.0(用于静态分析so文件)
4.python(运行frida注入js代码)
首先打开ApkScan-PKID,将待分析的apk拖进去,发现没有加固
那么就可以直接拉进jadx进行反编译,安装好apk后随便输入一个值,会提示【flag格式错误,请重试】
那么就在jadx中搜索这个字符串,可以找到在【cn.pojie52.cm01.MainActivity】这个类下
这里可以看到检测了输入的文本长度是否等于30,如果不是一律显示【flag格式错误,请重试】。长度是30的时候,会调用这个类下的check方法,如果返回真,则flag正确
但是这里的check方法是一个native函数,方法体在libnative-lib.so中,那么接着用ida分析这个so。ida加载so后,加载jni.h分析头文件,查看导出函数,发现是一个静态注册的方法
双击进入这个函数,然后按F5转换为伪C代码,大概浏览一下,发现有一个与处级题中相似的结构
也就是说只要拿到v11与v27,就可以知道在对比什么了。首先分析v11,网上可以看到,输入的内容经过sub_B90和sub_D90两个函数以后,就得到了v11
那么首先来hook一下这两个函数
python代码
[Python] 纯文本查看 复制代码
import frida
import sys
def message(message, data):
pass
with open('jscode.js', 'r', encoding='utf-8') as f:
jscode = f.read()
process = frida.get_remote_device().attach('cn.pojie52.cm01')
script = process.create_script(jscode)
script.on("message", message)
script.load()
sys.stdin.read()
js代码
[JavaScript] 纯文本查看 复制代码
function main() {
Java.perform(function (){
var libnative = Module.findBaseAddress("libnative-lib.so");
console.log("libnative: " + libnative);
var sub_B90 = libnative.add(0xB90);
var sub_B90arge0;
console.log("sub_B90: " + sub_B90);
Interceptor.attach(sub_B90, {
onEnter: function(args){
console.log("sub_B90 onEnter");
sub_B90arge0 = args[0];
console.log("参数1:");
console.log(Memory.readCString(args[0]));
console.log("参数2:");
console.log(args[1].toInt32());
console.log("参数3:");
console.log(Memory.readCString(args[2]));
},
onLeave: function(){
console.log("sub_B90 onLeave");
console.log("运算结果");
console.log(Memory.readByteArray(sub_B90arge0, 30));
}
});
var sub_D90 = libnative.add(0xD90);
console.log("sub_D90: " + sub_D90);
Interceptor.attach(sub_D90, {
onEnter: function(args){
console.log("sub_D90 onEnter");
console.log("参数1:");
console.log(Memory.readByteArray(args[0], 30));
console.log("参数2:");
console.log(args[1].toInt32());
},
onLeave: function(retval){
console.log("sub_D90 onLeave");
console.log("运算结果");
console.log(Memory.readCString(retval));
}
});
})
}
main();
开启hook脚本后,随意输入30位字符,例如【111112222233333444445555566666】,可以得到下面内容
可以看到sub_B90对输入的内容进行了加密,而sub_D90实际是一个base64编码。接下来看看v27,v27没有比较好的函数可以hook,那么就需要考虑hook寄存器的值
回到一开始汇编指令的图,找到进行对比前面的汇编指令
这里还需要设置显示汇编指令的地址,教程链接:https://blog.csdn.net/weixin_45780275/article/details/109600482
此时可以看到汇编指令的地址是【B34】,同时我们需要的是x9寄存器的值
js代码
[JavaScript] 纯文本查看 复制代码
function main() {
Java.perform(function (){
var libnative = Module.findBaseAddress("libnative-lib.so");
console.log("libnative: " + libnative);
//获取flag加密后的内容
var LDRB = libnative.add(0xB30);
send("LDRB: " + LDRB);
Interceptor.attach(LDRB, {
onEnter: function(args){
send("LDRB onEnter");
console.log(Memory.readCString(this.context.x9));
}
});
})
}
main();
继续输入30位字符进行hook,就可以得到进行对比的值【5Gh2/y6Poq2/WIeLJfmh6yesnK7ndnJeWREFjRx8】
也就是说,我们输入的字符串是正确的,那么经过sub_B90加密,然后base64编码,应该是要与前面的值完全一样,这时重点就来到了sub_B90函数
进入sub_B90函数,大致浏览一下,a1就是我们输入的字符串,然后a1赋值给了v4,而v4只有一个地方进行了异或变化
既然是异或,那么就好解决很多了,因为我们已经拿到了异或后的结果,如果能知道异或的内容是什么,就可以直接拿到异或前的内容了
那么就直接hook这条异或的汇编指令,可以看到汇编指令的地址是【D58】,需要的寄存器是x12
js代码
[JavaScript] 纯文本查看 复制代码
function main() {
Java.perform(function (){
var libnative = Module.findBaseAddress("libnative-lib.so");
console.log("libnative: " + libnative);
// 获取异或的字节,开了会报错,但是可以获取
var ishook = true;
var EOR = libnative.add(0xD58);
var eor = [];
var eorlen = 0;
send("EOR: " + EOR);
Interceptor.attach(EOR, {
onEnter: function(args){
if (ishook){
if (eorlen < 30){
eor.push(this.context.x12);
eorlen += 1;
}else{
ishook = false;
console.log(eor);
}
}
}
})
})
}
main();
最后一次hook,但是这次hook会闪退,原因我也不知道,但是已经拿到了需要的内容
0xd1,0x5a,0x6,0x90,0x44,0xe6,0xc7,0xe5,0xde,0x28,0xf7,0xf2,0x66,0x91,0xc8,0x85,0x42,0xdf,0xf9,0xe0,0x82,0x1,0x2b,0x3b,0x38,0x63,0x37,0xbd,0x2e,0x4d
这时可以用python进行异或还原
[Python] 纯文本查看 复制代码
import base64
xordata = [0xd1,0x5a,0x6,0x90,0x44,0xe6,0xc7,0xe5,0xde,0x28,0xf7,0xf2,0x66,0x91,0xc8,0x85,0x42,0xdf,0xf9,0xe0,0x82,0x1,0x2b,0x3b,0x38,0x63,0x37,0xbd,0x2e,0x4d]
data = base64.b64decode('5Gh2/y6Poq2/WIeLJfmh6yesnK7ndnJeWREFjRx8'.encode())
flag = bytes([xordata[i] ^ data[i] for i in range(len(xordata))]).decode()
print(flag)
得到flag【52pojieHappyChineseNewYear2021】
输入apk里面尝试一下
结果正确
免费评分
查看全部评分