Wanted to Spy on My Dog, Ended Up Spying on TP-Link Published on Saturday, September 13, 2025, by Joshua Kennedy --- Overview The author purchased a cheap TP-Link Tapo indoor camera to monitor their dog but quickly got frustrated with the device’s setup and obscure cloud requirements. This led them down a technical rabbit hole involving reverse-engineering, APK decompilation, man-in-the-middle (MITM) attacks, and cryptographic analysis to understand and bypass the onboarding process. --- Key Challenges and Motivations Difficulty integrating the camera with Frigate (open-source NVR) due to proprietary APIs. Annoyance over forced "Tapo Care" subscription pushes. Discovery that changing cloud password does not sync with paired device passwords. Desire for a cloudless onboarding method to avoid unnecessary dependencies. --- Man-in-the-Middle (MITM) Setup Traditional MITM: routing device traffic through a proxy with a custom TLS certificate. Modern apps use certificate pinning and ignore proxy settings, complicating MITM. Dynamic instrumentation with Frida was employed to bypass pinning and force traffic through mitmproxy. Setup included: Tapo App (with Frida hooks) Laptop running mitmproxy Tapo Camera Result: Captured initial unauthenticated login call using admin before password changes. --- Findings from Intercepted Traffic Default password exists for initial login, separate from the cloud password. All subsequent API calls are encapsulated in an encrypted "securePassthrough" channel. Encrypted messages prevent straightforward inspection. --- APK Decompiled with JADX Analysis focused on CameraOnboardingViewModel class. Found a function returning the default password. The default password (with encrypttype: 3) was revealed as: --- Enhancing mitmproxy for Decryption Used PyTapo for reference implementation of the authentication flow. Created a mitmproxy script tapodecryptpretty.py to: Detect login handshake parameters. Derive session keys (lsk and ivb). Decrypt and pretty-print API payloads inline in mitmproxy. Dump decrypted JSON payloads for offline analysis. --- Analysis of Onboarding API Calls Complete API calls captured during onboarding included: getAppComponentList setLanguage scanApList bindToCloud changeAdminPassword setTimezone setRecordPlan setDeviceLocation connectAp getConnectStatus setAccountEnabled changeThirdAccount Core calls distilled for onboarding: scanApList — Scans available Wi-Fi access points. setAccountEnabled + changeThirdAccount — Enables RTSP/ONVIF accounts. changeAdminPassword — Changes default password to cloud password. connectAp — Connects camera to selected Wi-Fi network. Other calls (e.g., timezones, record plans) are ancillary. --- Outcome: Cloudless Onboarding Script The author developed a bash script tapoonboard.sh that automates: Logging in with the default admin password. Selecting and connecting to Wi-Fi. Disabling default on-screen display (OSD) logos. Enabling RTSP/ONVIF streaming functionality. Changing the admin password to the cloud password. --- Final Observations on Tapo Firmware Mixed cryptographic practices: uses both SHA-256 and legacy MD5 hashing. Two public keys manage password transmission; one is secret and hard-coded. Password synchronization between app and device is inconsistent. Overall, the firmware appears hastily assembled by amateur cryptographers. Considering camera’s low price point, these shortcomings are perhaps expected. --- Epilogue After all this effort, the author finally achieved what they originally wanted: watching their dog while away. The footage