/*
 * Locate the TLS PSK used by the dishwasher as the password that
 * protects access over the network.
 *
 * Launch it with:
 * frida --no-pause -f com.bshg.homeconnect.android.release -U -l find-psk.frida
 *
 * This will also dump all of the cleartext SSL traffic before encryption
 * and after decryption.  For websocket traffic from the server, this
 * will be in the clear, although to the server is masked with an XOR
 * value.
 *
 * Note that it has to delay the Interceptor attach calls until the
 * library has been dlopen()'ed by the application, which is why there
 * is a setTimeout().
 *
 * TODO: Is the PSK deterministic or is it randomly generated and stored
 * in the cloud?
 *
 * TODO: XOR unmask the websock TX traffic
 */


setTimeout(() => {
console.log("looking for libHCPService.so");

const SSL_get_servername = new NativeFunction(
	Module.getExportByName("libHCPService.so", "SSL_get_servername"),
	"pointer",
	["pointer","int"]
);

Interceptor.attach(Module.getExportByName("libHCPService.so", "SSL_read"),
{
	onEnter(args) {
		this.ssl = args[0];
		this.buf = args[1];
	},
	onLeave(retval) {
		const server_ptr = SSL_get_servername(this.ssl, 0);
		const server = server_ptr.readUtf8String();

		retval |= 0;
		if (retval <= 0)
			return;

		console.log("RX", server);
		console.log(Memory.readByteArray(this.buf, retval));
	},
})

Interceptor.attach(Module.getExportByName("libHCPService.so", "SSL_write"),
{
	onEnter(args) {
		this.ssl = args[0];
		const len = Number(args[2]);
		const server_ptr = SSL_get_servername(this.ssl, 0);
		const server = server_ptr.readUtf8String();

		console.log("TX", server);
		console.log(Memory.readByteArray(args[1], len));
	},
})

/*
 * hcp::client_psk_callback is called when OpenSSL has made a connection and
 * the server has offered a client hint.
 */
Interceptor.attach(Module.getExportByName("libHCPService.so", "_ZN3hcp19client_psk_callbackEP6ssl_stPKcPcjPhj"),
{
	onEnter(args) {
		this.ssl = args[0];
		this.identity = args[2];
		this.psk_buf = args[4];
		const hint = Memory.readUtf8String(args[1]);
		console.log("psk callback hint '" + hint + "'");
	},
	onLeave(len) {
		len |= 0;
		console.log("psk", len, this.psk_buf);
		const buf = Memory.readByteArray(this.psk_buf, len);
		console.log(buf);
	},
})

}, 1000)
