To read the main.js
for further analysis or extracting the private key stored by Bambu in the app:
bambu-connect-beta-darwin-arm64-v1.0.4_4bb9cf0.dmg
. Inside, you can find the files of the underlying Electron app in Bambu Connect (Beta).app/Contents/Resources
folder./Bambu Connect (Beta).app/Contents/Resources/app.asar.unpacked/.vite/build/main.node
and can be extracted. Unpacking app.asar
without fixing it first will result in an encrypted main.js
file and 100 GB of decoy files generated. Don't try it.main.node
in Ghidra and Auto-Analyze it. Then search for the GetKey
function, or press G and go to 0000b67e
.B0AE6995063C191D2B404637FBC193AE10DAB86A6BC1B1DE67B5AEE6E03018A2
D8BCE831F1284E1993D98EE807101F10F27AFF4E30BD4B420E057D02B8E9BD1B
asarfix
and use it to fix the archive: npx asarfix app.asar -k <KEY> -o fixed.asar
npx asar extract fixed.asar src
./src/.vite/build/main.js
is minified. Use any JavaScript beautifier (for example prettier) to make it better readable. Interesting user code including the private key is at the end of the file.The private key and certs are further obfuscated. To get cleartext, you need to do:
Encrypted string from cy()
-> ure(string, key)
-> RC4 decryption -> decodeURIComponent()
-> final string.
Example Python reimplementation to extract the secrets, easy to run. Copy the content of t
from function cy()
in main.js
and paste it here. After running, you have a private key from Bambu Lab.
import urllib.parse
def cy():
t = [
# copy from main.js
]
return t
def ure(t, e):
# RC4 implementation
r = list(range(256))
n = 0
s = ""
# Key-scheduling algorithm (KSA)
for o in range(256):
n = (n + r[o] + ord(e[o % len(e)])) % 256
r[o], r[n] = r[n], r[o]
# Pseudo-random generation algorithm (PRGA)
o = n = 0
for byte in t:
o = (o + 1) % 256
n = (n + r[o]) % 256
r[o], r[n] = r[n], r[o]
k = r[(r[o] + r[n]) % 256]
s += chr(byte ^ k)
return s
def lt(t, e):
r = cy()
n = t - 106
s = r[n]
s = ure(s, e)
return urllib.parse.unquote(s)
def extract_certs_and_key():
try:
result = {}
result["Are"] = lt(106, "1o9B")
result["fre"] = lt(107, "FT2A")
result["private_key"] = lt(108, "Tlj0")
result["cert"] = lt(109, "NPub")
result["crl"] = lt(110, "x077")
except Exception as e:
print(f"Error extracting certs/key: {e}")
for key, value in result.items():
print(f"{key}:\n{value}\n")
if __name__ == "__main__":
extract_certs_and_key()