kakaotalk_analysis/scripts/frida/trace_loco.js
2023-12-30 19:51:11 +01:00

124 lines
3.5 KiB
JavaScript

/*
Decrypt and print LOCO traffic of KakaoTalk 10.4.3.
*/
import { dumpByteArray, printStacktrace } from "./utils.js";
Java.perform(function () {
hookDoFinal2();
hookKeyGeneratorGenerateKey();
hookSharedSecretStore();
printLocoBody();
});
const locoKey = Java.array(
"byte",
[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]
);
const locoFileNames = [
"V2SLSink.kt",
"V2SLSource.kt",
"V2SLHandshake.kt",
"LocoV2SLSocket.kt",
];
const patchLocoKey = true;
const printStacktrace = false;
function hookDoFinal2() {
var cipherInit = Java.use("javax.crypto.Cipher")["doFinal"].overload("[B");
cipherInit.implementation = function (byteArr) {
var tmp = this.doFinal(byteArr);
var caller = Java.use("java.lang.Exception").$new().getStackTrace()[1];
if (locoFileNames.includes(caller.getFileName())) {
console.log("[Cipher.doFinal2()]: " + " cipherObj: " + this);
console.log("Caller: " + caller.getFileName());
dumpByteArray("In buffer (cipher: " + this.getAlgorithm() + ")", byteArr);
dumpByteArray("Result", tmp);
// var result_base64 = Java.use("android.util.Base64").encodeToString(tmp, 0);
// console.log("Result in Base64: " + result_base64)
if (printStacktrace) {
printStacktrace();
}
console.log("##############################################");
}
return tmp;
};
}
function hookKeyGeneratorGenerateKey() {
var generateKey = Java.use("javax.crypto.KeyGenerator")[
"generateKey"
].overload();
generateKey.implementation = function () {
var tmp = this.generateKey();
var caller = Java.use("java.lang.Exception").$new().getStackTrace()[1];
const secretKeySpec = Java.cast(
tmp,
Java.use("javax.crypto.spec.SecretKeySpec")
);
const encodedKey = secretKeySpec.getEncoded();
if (locoFileNames.includes(caller.getFileName())) {
// console.log("[KeyGenerator.generateKey()]: Object: " + tmp);
console.log("Caller: " + caller.getFileName());
// dumpByteArray("[KeyGenerator.generateKey()]: Key", encodedKey);
var base64_key = Java.use("android.util.Base64").encodeToString(
encodedKey,
0
);
console.log("Generated key: " + base64_key);
if (printStacktrace) {
printStacktrace();
}
}
if (patchLocoKey) {
dumpByteArray("Patching LOCO AES key with key", locoKey);
const SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
var fakeKey = SecretKeySpec.$new(locoKey, "AES");
tmp = fakeKey;
}
console.log("##############################################");
return tmp;
};
}
function hookSharedSecretStore() {
var locoCipherHelper = Java.use("com.kakao.talk.secret.LocoCipherHelper$e")[
"$init"
].overload("java.lang.String", "long");
locoCipherHelper.implementation = function (arg0, arg1) {
var tmp = this.$init(arg0, arg1);
var caller = Java.use("java.lang.Exception").$new().getStackTrace()[1];
console.log("Secret Chat shared secret: " + arg0);
console.log("Secret Chat seed for nonce: " + arg1);
console.log(this.toString());
console.log("Caller: " + caller.getFileName());
console.log("##############################################");
};
}
function printLocoBody() {
Java.choose("com.kakao.talk.loco.protocol.LocoBody", {
onMatch: function (instance) {
if (instance) {
console.log("LOCO body: " + instance);
}
},
onComplete: function () {},
});
}