implement some more functions

This commit is contained in:
DavidVentura
2024-01-18 17:17:16 +01:00
parent a4a0119f97
commit 8d1abd2266
2 changed files with 231 additions and 108 deletions
+32 -84
View File
@@ -1,14 +1,14 @@
import { replaceFunctions } from "./func_replacements.js"; import { replaceFunctions } from "./func_replacements.js";
function hook_fn(name_in_elf, enter, leave) { const hook_fn = (name_in_elf, enter, leave) => {
var symbol_addr = DebugSymbol.fromName(name_in_elf).address; var symbol_addr = DebugSymbol.fromName(name_in_elf).address;
console.log(`${name_in_elf} addr is: ${symbol_addr}`); console.log(`${name_in_elf} addr is: ${symbol_addr}, this is ${this}`);
Interceptor.attach(symbol_addr, { Interceptor.attach(symbol_addr, {
onEnter: enter, onEnter: enter,
onLeave: leave, onLeave: leave,
}); });
console.log(`Hooked ${name_in_elf}`); console.log(`Hooked ${name_in_elf}`);
} };
function hook_export_fn(name_in_elf, enter, leave) { function hook_export_fn(name_in_elf, enter, leave) {
var symbol_addr = Module.findExportByName("libvdp.so", name_in_elf); var symbol_addr = Module.findExportByName("libvdp.so", name_in_elf);
@@ -39,58 +39,13 @@ const hook_p2p_read = () => {
); );
}; };
const hook_pack_ClntPkt = () => {
let sym = "pack_ClntPkt";
hook_fn(
sym,
(args) => {
console.log(`onEnter ${sym}`);
/*
* onEnter pack_ClntPkt
2 0x7b5ef9c640
onExit pack_ClntPkt, ret=24
0 1 2 3 4 5 6 7 8 9 A B C D E F
0123456789ABCDEF 00000000 f1 67 00 14 42 41 54 43 00 00 00 00 00 09 4c
fb .g..BATC......L. 00000010 45 58 4c 56 53 00 00 00 EXLVS...
*/
// f1 30 00 00 heartbeat?
// int pack_ClntPkt(int m_type_or_len,ushort *pkt_buf,long
// something_out)
let m_ptype = args[0].toInt32();
// type = 2 == LanSearch, LanSearchExt, ServerReq, Hello, DevQuery
// 2 = P2P?
// let m_buf = args[1].readByteArray(m_ptype); // len??
let m_out = args[2];
this.outBuf = args[2];
this.inBuf = args[1];
var trace = Thread.backtrace(this.context, Backtracer.ACCURATE).map(
DebugSymbol.fromAddress,
);
for (var j in trace) {
console.log(trace[j]);
}
console.log(m_ptype);
},
(retval) => {
console.log(`onExit ${sym}, ret=${retval.toInt32()}`);
console.log("out\n", this.outBuf.readByteArray(retval.toInt32()));
console.log("in\n", this.inBuf.readByteArray(retval.toInt32()));
console.log(
"############################################################",
);
},
);
};
const hook___android_log_print = () => { const hook___android_log_print = () => {
const sym = "__android_log_print"; const sym = "__android_log_print";
hook_fn( hook_fn(
sym, sym,
(args) => { (args) => {
// (ushort *param_1,int param_2,undefined4 *param_3,undefined8 param_4 // let _prio = args[0].toInt32();
let _prio = args[0].toInt32(); // let _tag = args[1].readCString();
let _tag = args[1].readCString();
let fmt = args[2].readCString(); let fmt = args[2].readCString();
// console.log(fmt); // debug if crashes due to missing placeholder // console.log(fmt); // debug if crashes due to missing placeholder
const types = placeholderTypes(fmt); // ['s', 'd', ..]` const types = placeholderTypes(fmt); // ['s', 'd', ..]`
@@ -99,6 +54,8 @@ const hook___android_log_print = () => {
s: (x) => x.readCString(), s: (x) => x.readCString(),
d: (x) => x.toInt32(), d: (x) => x.toInt32(),
u: (x) => x.toInt32(), u: (x) => x.toInt32(),
z: (x) => x.toInt64(),
l: (x) => x.toInt64(),
x: (x) => x.toInt32().toString(16), x: (x) => x.toInt32().toString(16),
f: (x) => x.toFloat(), f: (x) => x.toFloat(),
}; };
@@ -110,54 +67,36 @@ const hook___android_log_print = () => {
() => {}, () => {},
); );
}; };
const hook_pack_P2pId = () => {
var sym = "pack_P2pId";
sym = "pack_P2pHdr";
sym = "Send_Pkt";
hook_fn(
sym,
(args) => {
console.log(`onEnter ${sym}`);
// (ushort *param_1,int param_2,undefined4 *param_3,undefined8 param_4
let m_ptype = args[1].toInt32();
let m_data = args[0].readByteArray(m_ptype); // len??
let m_sock = args[2];
let m_p4 = args[3];
console.log(m_data, m_ptype, m_sock, m_p4);
},
() => {},
);
};
const hook_create_P2pRdy = () => { const hook_in_out_buf = (sym, insize, outsize) => {
var sym = "create_P2pRdy"; let obj = {};
hook_fn( hook_fn(
sym, sym,
(args) => { (args) => {
console.log(`onEnter ${sym}`); console.log(`onEnter ${sym} ${this}`);
// (ushort *param_1,int param_2,undefined4 *param_3,undefined8 param_4 obj.outbuf = args[0];
this.out = args[0]; // u16 ptr obj.inbuf = args[1];
let _in = args[1].readByteArray(2);
console.log("in", _in);
}, },
(retval) => { (retval) => {
console.log(`onExit ${sym}, retval ${retval}`); console.log(`${sym} done, dumping`);
console.log(this.out.readByteArray(0x18)); // _g_p2prdy_size = 0x14, retruns +4 console.log("in");
console.log(obj.inbuf.readByteArray(insize));
console.log("out");
console.log(obj.outbuf.readByteArray(outsize));
console.log("retval", retval);
}, },
); );
}; };
let indent = 0; let indent = 0;
function doHooks() {
var libnative_addr = Module.findBaseAddress("libvdp.so"); function doReplaceFunctions() {
// const prefixes = ["Send_Pkt*", "P2P*", "*RcvTh*", "parse_*"]; // "XQP2P*", // const prefixes = ["Send_Pkt*", "P2P*", "*RcvTh*", "parse_*"]; // "XQP2P*",
// const prefixes = ["parse_*", "pack_*", "Send_Pkt*", "create_*"]; // const prefixes = ["parse_*", "pack_*", "Send_Pkt*", "create_*"];
const prefixes = ["create_*"]; const prefixes = ["create_*"];
const spam = ["XQP2P_Check_Buffer", "P2P_ChannelBufferCheck"]; const spam = ["XQP2P_Check_Buffer", "P2P_ChannelBufferCheck"];
if (libnative_addr) {
hook___android_log_print();
hook_create_P2pRdy;
const replaced = replaceFunctions(); const replaced = replaceFunctions();
console.log(replaced);
prefixes prefixes
.map((prefix) => DebugSymbol.findFunctionsMatching(prefix)) .map((prefix) => DebugSymbol.findFunctionsMatching(prefix))
.flat() .flat()
@@ -167,7 +106,7 @@ function doHooks() {
Interceptor.attach(dbg.address, { Interceptor.attach(dbg.address, {
onEnter: (args) => { onEnter: (args) => {
indent = indent + 1; indent = indent + 1;
let flag = replaced.includes(dbg.name) ? "[REPLACED] " : ""; let flag = !replaced.includes(dbg.name) ? "[NOT REPLACED] " : "";
console.log(" ".repeat(indent) + flag + dbg.name); console.log(" ".repeat(indent) + flag + dbg.name);
}, },
onLeave: (retval) => { onLeave: (retval) => {
@@ -176,6 +115,15 @@ function doHooks() {
}); });
console.log(`Hooked ${dbg.name}`); console.log(`Hooked ${dbg.name}`);
}); });
}
function doHooks() {
var libnative_addr = Module.findBaseAddress("libvdp.so");
if (libnative_addr) {
hook___android_log_print();
// hook_create_P2pRdy();
// hook_in_out_buf("create_LstReq", 0x1c, 0x1c);
hook_in_out_buf("create_P2pRdy", 0x1c, 0x1c);
doReplaceFunctions();
// hook_p2p_read(); // hook_p2p_read();
// hook_pack_P2pId(); // hook_pack_P2pId();
+181 -6
View File
@@ -6,6 +6,16 @@ const pack_P2pHdr = (in_buf, out_buf) => {
return 4; return 4;
}; };
const create_Close = (buf) => {
buf.writeByteArray([0xf1, 0xf0, 0x00, 0x00]);
return 4;
};
const create_LanSearchExt = (buf) => {
buf.writeByteArray([0xf1, 0x32, 0x00, 0x00]);
return 4;
};
const create_LanSearch = (buf) => { const create_LanSearch = (buf) => {
buf.writeByteArray([0xf1, 0x30, 0x00, 0x00]); buf.writeByteArray([0xf1, 0x30, 0x00, 0x00]);
return 4; return 4;
@@ -21,21 +31,166 @@ const create_P2pAlive = (buf) => {
}; };
const create_Hello = (buf) => { const create_Hello = (buf) => {
buf.writeU16(0xf1); buf.writeByteArray([0xf1, 0x0, 0x0, 0x0]);
buf.add(2).writeU16(0x0); return 4;
}; };
export const replace_func = (stub, ret, args) => { const create_P2pRdy = (outbuf, inbuf) => {
const name_in_elf = stub.name; // TODO: this is literlly the same as create_LstReq, just different command
/*
* in
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 42 41 54 43 00 00 00 00 00 09 4c fb 45 58 4c 56 BATC......L.EXLV
00000010 53 00 00 00 S...
out
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 f1 42 00 14 00 00 00 00 42 41 54 43 00 00 00 00 .B......BATC....
00000010 00 09 4c fb 45 58 4c 56 53 00 00 00 ..L.EXLVS...
retval 0x18
*/
const P2PRDY_SIZE = 0x14;
outbuf.writeU16(0x42f1);
outbuf.add(2).writeU16(P2PRDY_SIZE << 8);
outbuf.add(8).writeU64(inbuf.readU64());
outbuf.add(16).writeU64(inbuf.add(8).readU64());
outbuf.add(2 * 0xc).writeU32(inbuf.add(16).readU32());
return P2PRDY_SIZE + 4;
};
const create_P2pReq = (outbuf, inbuf, m_s_addr, addr_fam) => {
const P2PREQ_SIZE = 0x24;
console.log("new p2preq");
/*
P2P req addr_fam 2 m_s_addr
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 02 00 00 00 c0 a8 01 64 00 00 00 00 00 00 00 00 .......d........
at byte 4 is c0 a8 01 64 which is 192 168 1 100
in
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 42 41 54 43 00 00 00 00 00 09 4c fb 45 58 4c 56 BATC......L.EXLV
mine
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 f1 20 00 24 00 00 00 00 42 41 54 43 00 00 00 00 . .$....BATC....
00000010 00 09 4c fb 45 58 4c 56 53 00 00 00 00 00 00 00 ..L.EXLVS.......
00000020 00 00 00 00 00 00 00 00 ........
original
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 f1 20 00 24 00 00 00 00 42 41 54 43 00 00 00 00 . .$....BATC....
00000010 00 09 4c fb 45 58 4c 56 53 00 00 00 00 02 00 00 ..L.EXLVS.......
00000020 64 01 a8 c0 00 00 00 00 d.......
*/
//let new_outbuf = Memory.alloc(0x2c);
outbuf.writeU16(0x20f1);
outbuf.add(2).writeU16(P2PREQ_SIZE << 8);
outbuf.add(8).writeU64(inbuf.readU64());
outbuf.add(16).writeU64(inbuf.add(8).readU64());
outbuf.add(2 * 0xc).writeU32(inbuf.add(16).readU32());
outbuf.add(2 * 0xe).writeByteArray(swap_endianness_u16(m_s_addr));
outbuf.add(2 * 0xf).writeByteArray(swap_endianness_u16(m_s_addr.add(2)));
outbuf.add(2 * 0x12).writeU64(0);
outbuf.add(2 * 0x10).writeByteArray(swap_endianness_u32(m_s_addr.add(4))); // ip address
//og_func(outbuf, inbuf, m_s_addr, addr_fam);
//console.log("in");
//console.log(inbuf.readByteArray(0x10));
//console.log("mine");
//console.log(new_outbuf.readByteArray(0x28));
//console.log("original");
//console.log(outbuf.readByteArray(0x28));
return P2PREQ_SIZE + 4;
};
const dbg_create_P2pReq = (og_func) => {
return create_P2pReq;
};
const swap_endianness_u16 = (ptr) => {
const bytes = ptr.readU16();
const swapped = [(bytes & 0xff00) >> 8, bytes & 0x00ff];
return swapped;
};
const swap_endianness_u32 = (ptr) => {
const bytes = ptr.readU32();
const swapped = [
(bytes & 0xff000000) >> 24,
(bytes & 0x00ff0000) >> 16,
(bytes & 0x0000ff00) >> 8,
bytes & 0x000000ff,
];
return swapped;
};
const create_LstReq = (outbuf, inbuf) => {
/* original
in
0 1 2 3 4 5 6 7 8 9 A B C D E F
0123456789ABCDEF 00000000 42 41 54 43 00 00 00 00 00 09 4c fb 45 58 4c 56
BATC......L.EXLV 00000010 53 00 00 00 00 00 00 00 00 00 00 00 S...........
out
0 1 2 3 4 5 6 7 8 9 A B C D E F
0123456789ABCDEF 00000000 f1 67 00 14 00 00 00 00 42 41 54 43 00 00 00 00
.g......BATC.... 00000010 00 09 4c fb 45 58 4c 56 53 00 00 00 ..L.EXLVS...
retval 0x18
*/
const LISTREQ_SIZE = 0x14;
outbuf.writeU16(0x67f1);
outbuf.add(2).writeU16(LISTREQ_SIZE << 8);
// 4 * sizeof(short)
outbuf.add(8).writeU64(inbuf.readU64());
// 8 * sizeof(short)
outbuf.add(16).writeU64(inbuf.add(8).readU64());
// 8 * sizeof(short)
outbuf.add(2 * 0xc).writeU32(inbuf.add(0x10).readU32());
/*
let new_outbuf = Memory.alloc(0x1c);
og_func(new_outbuf, inbuf);
console.log("mine");
console.log(outbuf.readByteArray(0x1c));
console.log("original");
console.log(new_outbuf.readByteArray(0x1c));
*/
return LISTREQ_SIZE + 4; // this is actually wrong (and unused) in the code -- it is 0x1c
};
export const replace_func = (stub, ret, args, pass_orig) => {
const name_in_elf = stub.name.replace("dbg_", ""); // UGH FIXME
const symbol_addr = DebugSymbol.fromName(name_in_elf).address; const symbol_addr = DebugSymbol.fromName(name_in_elf).address;
if (symbol_addr == 0) { if (symbol_addr == 0) {
console.error(`Could not find ${name_in_elf}`); console.error(`Could not find ${name_in_elf}`);
return; return;
} }
const orig_func = new NativeFunction(symbol_addr, ret, args);
let replacement_func;
if (pass_orig) {
replacement_func = stub(orig_func);
} else {
replacement_func = stub;
}
console.log( console.log(
`Replacing ${name_in_elf}, signature "${ret} ${name_in_elf}(${args})"`, `Replacing ${name_in_elf}, signature "${ret} ${name_in_elf}(${args})"`,
); );
Interceptor.replace(symbol_addr, new NativeCallback(stub, ret, args));
Interceptor.replace(
symbol_addr,
new NativeCallback(replacement_func, ret, args),
);
}; };
/* Send_Pkt_LanSearch = /* Send_Pkt_LanSearch =
@@ -52,14 +207,34 @@ export const replace_func = (stub, ret, args) => {
/* pack_ClntPkt = /* pack_ClntPkt =
* pack_P2pHdr * pack_P2pHdr
* pack_ * pack_
* RSLgnEx, RlyReq4, RlyPortAck, RlyPortExAck, RlyReqEx, Drw, HelloToAck, DrwAck, DevLgn4, LanSearchExtAck, P2pReq4, RSLGn * RSLgnEx, RlyReq4, RlyPortAck, RlyPortExAck, RlyReqEx, Drw, HelloToAck,
* DrwAck, DevLgn4, LanSearchExtAck, P2pReq4, RSLGn
*/
/*
hard
[NOT REPLACED] create_Drw
[NOT REPLACED] create_DrwAck
[NOT REPLACED] create_P2pReq
*/ */
export const replaceFunctions = () => { export const replaceFunctions = () => {
const replacements = [ const replacements = [
[create_P2pAlive, "uchar", ["pointer"]], [create_P2pAlive, "uchar", ["pointer"]],
[create_P2pAliveAck, "uchar", ["pointer"]], [create_P2pAliveAck, "uchar", ["pointer"]],
[create_LanSearch, "uchar", ["pointer"]], [create_LanSearch, "uchar", ["pointer"]],
[create_LanSearchExt, "uchar", ["pointer"]],
[create_Hello, "uchar", ["pointer"]], [create_Hello, "uchar", ["pointer"]],
[create_Close, "uchar", ["pointer"]],
/*
[
dbg_create_P2pReq,
"uchar",
["pointer", "pointer", "pointer", "uint"],
true,
],
*/
[create_P2pReq, "uchar", ["pointer", "pointer", "pointer", "uint"]],
[create_LstReq, "uchar", ["pointer", "pointer"]],
[create_P2pRdy, "uchar", ["pointer", "pointer"]],
[pack_P2pHdr, "uchar", ["pointer", "pointer"]], [pack_P2pHdr, "uchar", ["pointer", "pointer"]],
]; ];