Daniel Seiller
8d92f25b8c
- Started implementing new parser for chunked data - Started documenting data formats - Started dissector for network protocol - Added AI-Graph renderer (converts .pth files to python data you can import into Blender) - Added Script to convert savefile to JSON - Added (old) parser for chunked data format - Added basic parser for LFVF data section (Vertex Data) - Added script to analyze and filter read trace generated with frida script - Added various Frida scripts
174 lines
4.5 KiB
JavaScript
174 lines
4.5 KiB
JavaScript
var pak_files = {}
|
|
var ftypes = {}
|
|
var record=false;
|
|
|
|
var current_block_id;
|
|
var filename;
|
|
var t0 = performance.now();
|
|
|
|
Interceptor.attach(ptr("0x5e3b50"), { //read_block_header
|
|
onEnter: function (args) {
|
|
filename = pak_files[this.context.ecx] || this.context.ecx;
|
|
current_block_id = args[0].readUtf8String();
|
|
},
|
|
|
|
onLeave: function(ret) {
|
|
return ret;
|
|
}
|
|
})
|
|
|
|
// Interceptor.attach(ptr("0x5e3c50"), { // read_block_id
|
|
// onEnter: function (args) {
|
|
// var filename=pak_files[this.context.ecx]||this.context.ecx;
|
|
// var id=args[1].readUtf8String();
|
|
// console.log("[+read_block("+filename+")]",id,args[1]);
|
|
// },
|
|
|
|
// // onLeave: function(ret) {
|
|
// // console.log("[-read_ini_block] Ret:",ret);
|
|
// // }
|
|
// })
|
|
|
|
Interceptor.attach(ptr("0x7B43B020"),{
|
|
onEnter: function(args) {
|
|
var info={};
|
|
info['this']=args[0];
|
|
info['Length']=args[1];
|
|
info['Usage']=args[2];
|
|
info['FVF']=args[3];
|
|
info['Pool']=args[4];
|
|
info['ppVertexBuffer']=args[4];
|
|
send({CreateVertexBuffer:info});
|
|
}
|
|
})
|
|
|
|
Interceptor.attach(ptr("0x5e3bb0"), { // read_stream_wrapper
|
|
onEnter: function (args) {
|
|
this.args = {};
|
|
this.args[0] = args[0];
|
|
this.args[1] = args[1];
|
|
this.timestamp = performance.now()-t0;
|
|
},
|
|
onLeave: function (ret) {
|
|
var data=Memory.readByteArray(this.args[0],this.args[1].toInt32());
|
|
var stack = Thread.backtrace(this.context,Backtracer.ACCURATE);
|
|
var obj={
|
|
filename,
|
|
timestamp: this.timestamp,
|
|
block_id: current_block_id,
|
|
stack
|
|
};
|
|
send(obj,data);
|
|
}
|
|
})
|
|
|
|
|
|
Interceptor.attach(ptr("0x5e3800"), { // fopen_from_pak
|
|
onEnter: function (args) {
|
|
this.filename = args[0].readUtf8String();
|
|
},
|
|
onLeave: function (ret) {
|
|
if (ret != 0) {
|
|
pak_files[ret] = this.filename;
|
|
}
|
|
}
|
|
})
|
|
|
|
// Interceptor.attach(ptr("0x5e3c50"), { // read_block_id
|
|
// onEnter: function (args) {
|
|
// console.log("[+read]",args[0],args[1]);
|
|
// },
|
|
// onLeave: function(ret) {
|
|
// console.log("[-read] Ret:",ret);
|
|
// }
|
|
// })
|
|
|
|
// Interceptor.attach(ptr("0x6665a0"), { // load_m3d_1
|
|
// onEnter: function (args) {
|
|
// console.log("[M3D_1]",args[0].readUtf8String());
|
|
// }
|
|
// })
|
|
|
|
|
|
// Interceptor.attach(ptr("0x666900"), { // load_m3d_2
|
|
// onEnter: function (args) {
|
|
// console.log("[M3D_2]",args[0].readUtf8String());
|
|
// }
|
|
// })
|
|
|
|
|
|
function dasm(addr, size) {
|
|
var size = size || 8;
|
|
var offset = 0;
|
|
var ret = [];
|
|
while (ret.length != size) {
|
|
var inst = Instruction.parse(ptr(addr).add(offset));
|
|
ret.push(("[" + inst.address + "] " + inst.mnemonic + " " + inst.opStr).trim());
|
|
offset += inst.size;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
function r(addr, options) {
|
|
var options = options || {}
|
|
var max_depth = options.max_depth || 4;
|
|
var num = options.num || 4;
|
|
var ret = {};
|
|
var vals = [
|
|
"S8",
|
|
"U8",
|
|
"S16",
|
|
"U16",
|
|
"S32",
|
|
"U32",
|
|
"Float",
|
|
"Double",
|
|
"Pointer",
|
|
"CString",
|
|
"Utf8String",
|
|
"Utf16String",
|
|
"AnsiString"
|
|
];
|
|
vals.forEach(function (k) {
|
|
try {
|
|
ret[k] = ptr(addr)['read' + k]()
|
|
} catch (e) {
|
|
ret[k] = undefined;
|
|
}
|
|
})
|
|
try {
|
|
ret["code"] = dasm(addr, 8);
|
|
} catch (e) {
|
|
ret["code"] = undefined;
|
|
}
|
|
|
|
if (max_depth > 1) {
|
|
var p = {};
|
|
var read_ptr = false;
|
|
for (var i = 0; i < num; ++i) {
|
|
if (ret["Pointer"] === undefined) {
|
|
continue;
|
|
}
|
|
p[i * Process.pointerSize] = r(ret["Pointer"].add(i * Process.pointerSize), {
|
|
max_depth: max_depth - 1,
|
|
num
|
|
});
|
|
read_ptr = true;
|
|
}
|
|
if (read_ptr) {
|
|
ret["p"] = p;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
// function test() {
|
|
// for (var p = 0; p < 4; ++p) {
|
|
// var player = ptr(0x7FE944).readPointer().add(0x288 + p * 4).readPointer();
|
|
// if (!player.isNull()) {
|
|
// console.log("Player " + (p+1) + ":", player);
|
|
// console.log(JSON.stringify(r(player),null,4));
|
|
// }
|
|
// }
|
|
// }
|