WMCTF 2023 ezandroid
比赛的时候只解出username,看了官方的wp,赛后总结下
首先用jadx打开,没有加壳
关键的就这几个地方,可以看到校验的函数是native函数,使用IDA打开so
导出函数只有JNI_onload,应该是动态注册的函数,使用frida hook 下注册的地址,之前学VMP壳的时候正好有个hook的脚本就直接拿来用了,但是hook后闪退,有frida检测,之前瞟了个一把嗦的反反frida脚本,放一起
function Log(content) {
var pid = Process.getCurrentThreadId();
console.log("[" + pid + "]->" + content);
}
function readStdString(str) {
const isTiny = (str.readU8() & 1) == 0;
if (isTiny) {
return str.add(1).readUtf8String();
}
return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
}
function hooklibart() {
var libartmodule = Process.getModuleByName("libart.so");
var PrettyMethodaddr = null;
var RegisterNativeaddr = null;
libartmodule.enumerateSymbols().forEach(
function(symbol){
// if(symbol.name=='_ZN3art9JavaVMExt23FindCodeForNativeMethodEPNS_9ArtMethodE'){
// RegisterNativeaddr=symbol.address;
// Log(JSON.stringify(symbol));
// }
if (symbol.name.indexOf("PrettyMethod") != -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("art") != -1) {
Log("find PrettyMethod:" + JSON.stringify(symbol));
PrettyMethodaddr = symbol.address;
}
if (symbol.name.indexOf("RegisterNativeMethod") == -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("RegisterNative") != -1) {
Log("find RegisterNative:" + JSON.stringify(symbol));
RegisterNativeaddr = symbol.address;
}
}
);
var PrettyMethodfunc = new NativeFunction(PrettyMethodaddr, ["pointer", "pointer", "pointer"], ["pointer", "int"]);
Log("start interpreter RegisterNatives:" + RegisterNativeaddr);
Interceptor.attach(RegisterNativeaddr, {
onEnter: function (args) {
var ArtMethodptr = args[0];
this.JniFuncaddr = args[1];
var result = PrettyMethodfunc(ArtMethodptr, 1);
var stdstring = Memory.alloc(3 * Process.pointerSize);
ptr(stdstring).writePointer(result[0]);
ptr(stdstring).add(1 * Process.pointerSize).writePointer(result[1]);
ptr(stdstring).