idk stuff
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
max_line_length = 130
|
||||||
@@ -5,3 +5,22 @@ Reversing a camera
|
|||||||
|
|
||||||
|
|
||||||
Per [pictures](https://github.com/DavidVentura/cam-reverse/blob/master/pics/pcb.jpg?raw=true) the main chip is TXW817 ([chinese](https://www.taixin-semi.com/Product/ProductDetail?productId=306), [eng, google translate](https://www-taixin--semi-com.translate.goog/Product/ProductDetail?productId=306&_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp))
|
Per [pictures](https://github.com/DavidVentura/cam-reverse/blob/master/pics/pcb.jpg?raw=true) the main chip is TXW817 ([chinese](https://www.taixin-semi.com/Product/ProductDetail?productId=306), [eng, google translate](https://www-taixin--semi-com.translate.goog/Product/ProductDetail?productId=306&_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp))
|
||||||
|
|
||||||
|
The interesting implementation is in `libvdp.so`, part of the apk bundle. This repo uses Frida for live analysis of the .so file.
|
||||||
|
|
||||||
|
|
||||||
|
### Take APK from emulator/sacrificial device
|
||||||
|
```
|
||||||
|
adb shell pm list packages | grep ysx
|
||||||
|
adb shell pm path com.ysxlite.cam
|
||||||
|
adb shell pm path com.ysxlite.cam | while read -r line ; do adb pull $(echo $line | cut -d: -f2-) ; done
|
||||||
|
```
|
||||||
|
### Push to sacrificial device
|
||||||
|
```
|
||||||
|
adb install-multiple *apk
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frida install Android
|
||||||
|
|
||||||
|
[docs](https://frida.re/docs/android/)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
function hook_fn(name_in_elf, enter, leave) {
|
||||||
|
var symbol_addr = DebugSymbol.fromName(name_in_elf).address;
|
||||||
|
console.log(`${name_in_elf} addr is: ${symbol_addr}`);
|
||||||
|
Interceptor.attach(symbol_addr, {
|
||||||
|
onEnter: enter,
|
||||||
|
onLeave: leave,
|
||||||
|
});
|
||||||
|
console.log(`Hooked ${name_in_elf}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hook_export_fn(name_in_elf, enter, leave) {
|
||||||
|
var symbol_addr = Module.findExportByName("libvdp.so", name_in_elf);
|
||||||
|
console.log(`${name_in_elf} addr is: ${symbol_addr}`);
|
||||||
|
Interceptor.attach(symbol_addr, {
|
||||||
|
onEnter: enter,
|
||||||
|
onLeave: leave,
|
||||||
|
});
|
||||||
|
console.log(`Hooked ${name_in_elf}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hook_p2p_read = () => {
|
||||||
|
var mangled_sym = "_Z8p2p_readPiihPci";
|
||||||
|
hook_export_fn(
|
||||||
|
mangled_sym,
|
||||||
|
(args) => {
|
||||||
|
// console.log(hexdump(
|
||||||
|
// args[0], {offset : 0, length : 0x200, header : true, ansi :
|
||||||
|
// false}));
|
||||||
|
|
||||||
|
let m_type = args[1];
|
||||||
|
let m_unk3 = args[2];
|
||||||
|
|
||||||
|
let m_size = args[4].toInt32();
|
||||||
|
console.log(m_type, m_unk3, m_size);
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 sym = "__android_log_print";
|
||||||
|
hook_fn(
|
||||||
|
sym,
|
||||||
|
(args) => {
|
||||||
|
// (ushort *param_1,int param_2,undefined4 *param_3,undefined8 param_4
|
||||||
|
let _prio = args[0].toInt32();
|
||||||
|
let _tag = args[1].readCString();
|
||||||
|
let fmt = args[2].readCString();
|
||||||
|
// console.log(fmt); // debug if crashes due to missing placeholder
|
||||||
|
const types = placeholderTypes(fmt); // ['s', 'd', ..]`
|
||||||
|
|
||||||
|
let o = {
|
||||||
|
s: (x) => x.readCString(),
|
||||||
|
d: (x) => x.toInt32(),
|
||||||
|
u: (x) => x.toInt32(),
|
||||||
|
x: (x) => x.toInt32().toString(16),
|
||||||
|
f: (x) => x.toFloat(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const values = types.map((t, idx) => o[t](args[idx + 3]));
|
||||||
|
const newStr = sprintf(fmt, values);
|
||||||
|
console.log(newStr);
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
},
|
||||||
|
() => {},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let indent = 0;
|
||||||
|
function doHooks() {
|
||||||
|
var libnative_addr = Module.findBaseAddress("libvdp.so");
|
||||||
|
// const prefixes = ["Send_Pkt*", "P2P*", "*RcvTh*", "parse_*"]; // "XQP2P*",
|
||||||
|
const prefixes = ["parse_*", "pack_*", "Send_Pkt*"]; // "XQP2P*",
|
||||||
|
const spam = ["XQP2P_Check_Buffer", "P2P_ChannelBufferCheck"];
|
||||||
|
prefixes
|
||||||
|
.map((prefix) => DebugSymbol.findFunctionsMatching(prefix))
|
||||||
|
.flat()
|
||||||
|
.map(DebugSymbol.fromAddress)
|
||||||
|
.filter((dbg) => !spam.includes(dbg.name))
|
||||||
|
.map((dbg) => {
|
||||||
|
Interceptor.attach(dbg.address, {
|
||||||
|
onEnter: (args) => {
|
||||||
|
indent = indent + 1;
|
||||||
|
console.log(" ".repeat(indent) + dbg.name);
|
||||||
|
},
|
||||||
|
onLeave: (retval) => {
|
||||||
|
indent = indent - 1;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(`Hooked ${dbg.name}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (libnative_addr) {
|
||||||
|
hook___android_log_print();
|
||||||
|
// hook_p2p_read();
|
||||||
|
// hook_pack_P2pId();
|
||||||
|
// hook_pack_ClntPkt();
|
||||||
|
} else {
|
||||||
|
console.log("NO WORKING");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchy = /%[0-9.-]*([a-z])/g;
|
||||||
|
const replacy = /(.*?)%[0-9.-]*([a-z])/g;
|
||||||
|
|
||||||
|
const placeholderTypes = (str) => {
|
||||||
|
// '%-16s, line %4d, %-16s:ret=%d,broadcast lan_seach to %s:%.3f!!!!'
|
||||||
|
// =>
|
||||||
|
// [ 's', 'd', 's', 'd', 's', 'f' ]
|
||||||
|
return [...str.matchAll(matchy)].map((m) => m[1]);
|
||||||
|
};
|
||||||
|
const sprintf = (str, values) => {
|
||||||
|
// '%-16s, line %4d, %-16s:ret=%d,broadcast lan_seach to %s:%.3f!!!!' +
|
||||||
|
// ["asd", 20, ...]
|
||||||
|
// =>
|
||||||
|
// asd, line 20, ...
|
||||||
|
const matches = str.matchAll(replacy);
|
||||||
|
return [...matches].map((m, idx) => m[1] + values[idx].toString()).join("");
|
||||||
|
};
|
||||||
|
setImmediate(doHooks);
|
||||||
Executable
+47
@@ -0,0 +1,47 @@
|
|||||||
|
#!/bin/env python
|
||||||
|
import frida
|
||||||
|
|
||||||
|
# Define the JavaScript code to hook System.loadLibrary()
|
||||||
|
js_code = """
|
||||||
|
const System = Java.use('java.lang.System');
|
||||||
|
|
||||||
|
System.loadLibrary.implementation = function(libraryName) {
|
||||||
|
console.log('Loading library: ' + libraryName);
|
||||||
|
// You can add your custom logic here before calling the original function.
|
||||||
|
return this.loadLibrary(libraryName);
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
target_package_name = "com.ysxlite.cam"
|
||||||
|
shared_library_name = "vdp.so"
|
||||||
|
native_function_name = "p2p_read"
|
||||||
|
js_code = open('asd.js').read()
|
||||||
|
def on_message(m, _data):
|
||||||
|
print('got', m, _data)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Replace 'com.example.targetapp' with the actual package name of your target app.
|
||||||
|
app_id = "com.ysxlite.cam"
|
||||||
|
target_app_package = 'com.ysxlite.cam'
|
||||||
|
target_app_package = 'YsxLite'
|
||||||
|
|
||||||
|
device = frida.get_usb_device()
|
||||||
|
session = device.attach(target_app_package)
|
||||||
|
#pid = device.spawn([app_id])
|
||||||
|
#print(pid)
|
||||||
|
#session = device.attach(pid)
|
||||||
|
# Attach to the target app
|
||||||
|
print(session)
|
||||||
|
|
||||||
|
# Create a script and load the JavaScript code
|
||||||
|
script = session.create_script(js_code)
|
||||||
|
|
||||||
|
script.on('message', on_message)
|
||||||
|
script.load()
|
||||||
|
# device.resume(target_app_package)
|
||||||
|
|
||||||
|
# Keep the script running to continue monitoring the app
|
||||||
|
input("Press Enter to stop...")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
Reference in New Issue
Block a user