Author: admin

  • Essential Tools & Techniques for Android WiFi/BT SPI Flash Firmware Dumping

    Introduction: Unlocking the Secrets of Android WiFi/BT Firmware

    In the realm of Android device security research and hardware reverse engineering, gaining access to low-level firmware is paramount. The WiFi and Bluetooth modules, often integrated into a single chip, operate on their own dedicated firmware stored in a Serial Peripheral Interface (SPI) flash memory. Dumping this firmware allows researchers to uncover vulnerabilities, analyze proprietary protocols, understand hardware initialization sequences, and even develop custom modifications. This expert-level guide will walk you through the essential tools and techniques required to successfully extract WiFi/BT SPI flash firmware from Android devices.

    Why Dump SPI Flash Firmware?

    The firmware running on WiFi/Bluetooth chips is a black box for most. By extracting it, you open up numerous possibilities:

    • Vulnerability Research: Discovering buffer overflows, logic flaws, or backdoor functionalities that could lead to remote code execution or data exfiltration.
    • Protocol Analysis: Understanding the intricate details of how WiFi and Bluetooth communicate at a low level, which is critical for security audits or interoperability projects.
    • Forensic Analysis: Recovering sensitive data or logs that might be stored within the firmware.
    • Custom Firmware Development: Creating modified firmware for specialized applications, performance enhancements, or security hardening.
    • Hardware Debugging: Gaining insight into hardware initialization issues or unexpected behavior.

    Identifying the Target: Locating the SPI Flash Chip

    Before you can dump the firmware, you need to physically locate the SPI flash chip associated with the WiFi/BT module. This often requires careful visual inspection and, at times, reference to datasheets or schematics (if available).

    Physical Identification Steps:

    1. Disassemble the Device: Carefully open your Android device, usually by removing screws and prying open plastic clips. Be mindful of fragile flex cables.
    2. Locate the WiFi/BT Module: On the PCB, the WiFi/BT module is often a small, shielded IC (Integrated Circuit) or a dedicated module. Common manufacturers include Broadcom (now Cypress), Qualcomm Atheros, and MediaTek. Look for markings like BCMxxxx, QCAxxxx, or MTxxxx.
    3. Identify the SPI Flash: The SPI flash chip is typically an 8-pin SOIC (Small Outline Integrated Circuit) or WSON (Very-very-thin Small Outline No-lead) package, located in close proximity to the WiFi/BT module. It will have identifiable markings, often from manufacturers like Winbond, MXIC (Macronix), or GigaDevice, with a part number that usually includes ’25Q’ or ’25L’ followed by a size (e.g., W25Q64FW for a 64Mbit/8MB flash).
    4. Consult Datasheets: Once identified, search for the chip’s datasheet online. This will provide crucial information on its pinout (VCC, GND, CS, CLK, MOSI, MISO) and operational voltage.

    Essential Tools for SPI Flash Dumping

    A successful dump requires a combination of hardware and software tools:

    Hardware:

    • Soldering Station: A fine-tip soldering iron, solder, flux, desoldering braid, and possibly a hot air station for desoldering surface-mount chips.
    • Magnification: A microscope or a good magnifying lamp is crucial for working with tiny SMD components.
    • Test Clips/Probes: SOIC test clips (for in-circuit) or fine-gauge wires (30AWG kynar) for soldering.
    • SPI Programmer: Dedicated SPI programmers like the CH341A Programmer (cost-effective, widely supported), a Bus Pirate, or a custom setup using an FT232H breakout board.
    • Logic Analyzer: (Optional but highly recommended) A tool like a Saleae Logic Analyzer or an OpenBench Logic Sniffer (with Sigrok) helps verify connections and diagnose bus activity.
    • Multimeter/Oscilloscope: For checking voltage levels and signal integrity.

    Software:

    • Flashrom: A universal flash programmer software, widely used for reading/writing SPI flash chips. Compatible with many programmers.
    • Custom Scripts: Python scripts using libraries like `spidev` (for Raspberry Pi) or `pyftdi` (for FT232H) for more control.
    • Hex Editor: For initial inspection of the dumped firmware (e.g., HxD, 010 Editor).
    • Firmware Analysis Tools: Binwalk for extracting embedded files, IDA Pro or Ghidra for reverse engineering binary code.

    Method 1: In-Circuit SPI Flash Dumping (Challenging)

    Dumping the flash while it remains soldered on the board is convenient but fraught with challenges. The main issues are power delivery and bus contention from the main SoC or the WiFi/BT chip itself.

    Steps for In-Circuit Dumping:

    1. Identify SPI Pins: Using the datasheet, identify VCC, GND, CS (Chip Select), CLK (Clock), MOSI (Master Out Slave In), and MISO (Master In Slave Out) pins.
    2. Connect Test Clips/Wires: Attach a SOIC test clip or carefully solder thin wires to each of the relevant pins. Ensure good, isolated connections.
    3. Connect to SPI Programmer: Wire the test clips/wires to your chosen SPI programmer (e.g., CH341A, Bus Pirate). Match the pinouts exactly.
    4. Power the Device (Carefully): This is the trickiest part. Ideally, power the SPI flash directly from your programmer (e.g., 3.3V) if your programmer supports it and the chip can be isolated from the main board’s power. Alternatively, power the entire Android device, but then you risk bus contention. You might need to hold the WiFi/BT module in reset or find a way to disable its access to the SPI bus.
    5. Execute Flashrom: Once connections are stable and power is applied, use `flashrom` from your computer.
    sudo flashrom -p ch341a_spi -r wifi_bt_firmware.bin

    Replace `ch341a_spi` with your programmer’s driver (e.g., `buspirate_spi` for Bus Pirate). If `flashrom` can’t detect the chip, check your connections, power, and try specifying the chip type with `-c <chip_type>` (e.g., `W25Q64FW`).

    Method 2: Out-of-Circuit SPI Flash Dumping (Recommended)

    This method involves desoldering the SPI flash chip from the PCB and placing it into a dedicated adapter on the programmer. While it requires more hardware manipulation, it’s often more reliable as it eliminates bus contention and power issues.

    Steps for Out-of-Circuit Dumping:

    1. Desolder the Chip: Using a hot air station set to appropriate temperature (e.g., 300-350°C for lead-free solder, lower for leaded) and low airflow, carefully desolder the SOIC/WSON chip. Apply flux generously before heating. Use fine tweezers to gently lift the chip once solder is molten. Practice on a donor board first if you’re new to hot air rework.
    2. Clean Pads: Clean any residual solder from the chip’s pads and the PCB’s pads using desoldering braid and isopropyl alcohol.
    3. Place in Adapter: Insert the desoldered SPI flash chip into an appropriate SOIC or WSON test socket adapter for your programmer. Ensure correct orientation (pin 1 alignment).
    4. Connect to Programmer: Plug the adapter into your CH341A programmer or universal programmer.
    5. Execute Flashrom: Connect the programmer to your computer and run `flashrom`.
    sudo flashrom -p ch341a_spi -r wifi_bt_firmware_desoldered.bin

    Again, if automatic detection fails, try specifying the chip type with `-c`. This method usually provides the most consistent and error-free dumps.

    Analyzing the Dumped Firmware

    Once you have a `*.bin` file, the real reverse engineering begins:

    • Binwalk: Use `binwalk -Me wifi_bt_firmware.bin` to automatically extract embedded filesystems, images, and other known file formats. This can reveal libraries, configuration files, and even other firmware blobs.
    • Hex Editor: Open the file in a hex editor to look for human-readable strings, magic bytes, or specific sequences.
    • Disassemblers/Decompilers: Load the relevant sections (identified by Binwalk or manual analysis) into IDA Pro or Ghidra. You’ll need to know the CPU architecture of the WiFi/BT module (often ARM M-series or a proprietary core). Look for bootloaders, main firmware code, and data structures.

    Challenges and Troubleshooting

    • Incorrect Voltage: Ensure your programmer operates at the correct voltage (e.g., 3.3V or 1.8V) for your flash chip. Most CH341A programmers have a jumper for this.
    • Bus Contention: If dumping in-circuit, other components on the SPI bus can interfere. Trying to hold the main SoC in reset or powering down specific components might help.
    • Write Protection: Some SPI flash chips have hardware or software write protection mechanisms. Read operations should still work, but modifying the firmware would be blocked.
    • Physical Damage: Desoldering can be tricky. Excessive heat or force can damage the chip or PCB traces.
    • Pinout Mismatch: Double-check all connections. A single wrong connection can prevent detection or cause corruption.

    Conclusion

    Dumping Android WiFi/BT SPI flash firmware is a powerful technique for anyone engaged in serious hardware reverse engineering or security research. While it requires precision, the right tools, and patience, the insights gained can be invaluable. By following these detailed steps, you’ll be well-equipped to extract, analyze, and ultimately understand the hidden complexities within your device’s wireless communication firmware.

  • Deep Dive: Reverse Engineering Android WiFi/BT Firmware from SPI Flash Dumps

    Introduction: The Hidden World of Android WiFi/BT Firmware

    Modern Android devices rely heavily on integrated WiFi and Bluetooth modules for connectivity. While these modules appear as black boxes to most users and even application developers, beneath the surface lies complex firmware responsible for their operation. This firmware, often stored on a dedicated SPI (Serial Peripheral Interface) flash chip, dictates everything from radio behavior and protocol handling to power management and security features. Reverse engineering these firmware dumps can unlock critical insights into device security, expose vulnerabilities, or even enable custom functionalities beyond official specifications.

    Understanding how to extract, analyze, and potentially modify this firmware is a crucial skill for hardware hackers, security researchers, and advanced enthusiasts looking to truly understand and control their devices. This guide will walk you through the process, from identifying the SPI flash chip to initial analysis of its contents.

    Identifying and Accessing the SPI Flash Chip

    Locating the Chip

    The first step in any hardware reverse engineering endeavor is physical identification. On an Android device’s Printed Circuit Board (PCB), the WiFi/Bluetooth module is typically a distinct component, often a shielded IC or a module containing several chips. The SPI flash chip holding its firmware will usually be a small, 8-pin Surface Mount Device (SMD) package (SOP/SOIC) located in close proximity to the main WiFi/BT controller IC.

    • Visual Clues: Look for markings like “25Qxx”, “W25Qxx”, “MX25Lxx”, or similar part numbers from manufacturers like Winbond, Macronix, or Gigadevice. These are common identifiers for SPI NOR flash memory.
    • Proximity: It will almost always be next to the main SoC or the dedicated WiFi/BT controller chip. Sometimes, it might be under a metal shield that needs to be carefully removed.
    • Pin Count: SPI flash chips are predominantly 8-pin devices.

    Essential Tools for Dumping

    To successfully dump the firmware, you’ll need a few specialized tools:

    • SPI Programmer: Devices like the CH341A programmer (inexpensive and widely available), Bus Pirate, or custom FPGA-based solutions are suitable.
    • SOIC Test Clip: An 8-pin SOIC clip is invaluable for non-destructive connection to the chip. Alternatively, fine-tipped soldering equipment and thin wires can be used for direct soldering.
    • Logic Analyzer (Optional but Recommended): Useful for verifying SPI communication and troubleshooting connections.
    • Multimeter: For checking continuity and voltage levels.
    • Magnifying Glass/Microscope: Essential for precise identification and connection to small SMD components.

    Dumping the Firmware: A Step-by-Step Guide

    Physical Connection

    Connecting to the SPI flash chip requires precision. Ensure the Android device is completely powered off and, ideally, its battery disconnected to prevent accidental shorts or damage. The typical pinout for an 8-pin SPI flash is:

    • Pin 1: CS# (Chip Select)
    • Pin 2: SO (Serial Data Output / MISO)
    • Pin 3: WP# (Write Protect)
    • Pin 4: GND (Ground)
    • Pin 5: SI (Serial Data Input / MOSI)
    • Pin 6: CLK (Serial Clock)
    • Pin 7: HOLD# (Hold)
    • Pin 8: VCC (Power Supply)

    Using the SOIC clip, carefully attach it to the chip, ensuring all pins make good contact. Double-check the orientation – Pin 1 is usually marked with a dot or a bevel on the chip. Connect the corresponding pins from the SOIC clip to your SPI programmer. Crucially, if the device’s main power supply cannot be completely isolated, ensure your programmer is set to the correct voltage (typically 1.8V or 3.3V) to avoid damaging the chip or the device.

    Using a SPI Programmer (e.g., CH341A with `flashrom`)

    For most cheap SPI programmers like the CH341A, the `flashrom` utility is the de facto standard. First, ensure `flashrom` is installed on your Linux-based system:

    sudo apt update && sudo apt install flashrom

    Once installed and your programmer is connected to your computer (usually via USB) and the SPI flash chip, you can attempt to read the firmware:

    sudo flashrom --programmer ch341a_spi -r wifi_bt_firmware.bin

    If `flashrom` detects your chip, it will proceed to read the entire contents into `wifi_bt_firmware.bin`. If detection fails, you might need to specify the chip type manually (e.g., `-c W25Q128FV`) after identifying it or troubleshoot your connections. Always perform at least two consecutive dumps and verify their MD5 or SHA256 hashes to ensure data integrity and a clean read.

    md5sum wifi_bt_firmware.bin

    Initial Analysis: Unveiling the Firmware Structure

    With a clean firmware dump in hand, the real work begins. The goal is to understand what’s inside – file systems, executables, configuration data, and more.

    Basic File Type Identification with `file`

    Start with the simplest tool to get a hint about the dump’s contents:

    file wifi_bt_firmware.bin

    This might reveal it as

  • The Complete Lab: Dumping and Analyzing Android WiFi/BT SPI Flash Firmware

    Introduction

    The wireless capabilities of Android devices—Wi-Fi and Bluetooth—are powered by dedicated chipsets, often containing their own firmware stored on external SPI (Serial Peripheral Interface) flash memory. Reverse engineering this firmware is crucial for security research, vulnerability discovery, custom driver development, or simply understanding device behavior at a deeper level. This guide provides a comprehensive, expert-level tutorial on identifying, dumping, and initially analyzing the SPI flash firmware from Android WiFi/Bluetooth modules.

    Understanding the intricacies of these modules can uncover hidden debug interfaces, exploit potential vulnerabilities, or even enable unsupported features. We’ll cover everything from hardware identification and connection techniques to software tools for dumping and initial binary analysis, empowering you to explore the low-level secrets of your Android device’s wireless stack.

    Understanding Android WiFi/BT Firmware Storage

    SPI Flash Fundamentals

    SPI flash memory is a non-volatile memory solution widely used in embedded systems due to its simplicity, low pin count, and relatively high read/write speeds. It’s ideal for storing firmware, bootloaders, and configuration data. Wireless chipsets like those from Broadcom, Qualcomm, or MediaTek frequently utilize external SPI flash chips to store their operational firmware. These chips typically communicate with the main SoC (System on Chip) or the wireless module’s internal microcontroller via the SPI bus.

    A typical SPI flash chip will have 8 pins in a SOIC (Small Outline Integrated Circuit) or WSON (Very Very thin Small Outline No-lead) package. Key pins include:

    • VCC: Power supply
    • GND: Ground
    • CS (Chip Select): Activates/deactivates the chip
    • CLK (Clock): Synchronizes data transfer
    • MOSI (Master Out Slave In): Data sent from master (programmer) to slave (flash)
    • MISO (Master In Slave Out): Data sent from slave (flash) to master (programmer)
    • WP (Write Protect): Prevents accidental writes
    • HOLD (Hold): Pauses transmission

    Common Locations and Chipsets

    On an Android device PCB (Printed Circuit Board), the WiFi/Bluetooth module often appears as a shielded component or a standalone chip package. The SPI flash chip associated with it will usually be in close proximity. Look for small, 8-pin SOIC or WSON packages with markings that correspond to flash memory manufacturers like Winbond, GigaDevice, Macronix, or MXIC.

    Common WiFi/BT chipsets found in Android devices include:

    • Broadcom: BCM43xx series (e.g., BCM4339, BCM4354)
    • Qualcomm Atheros: QCAxxxx series (e.g., QCA6174, QCA9377)
    • MediaTek: MTxxxx series (e.g., MT6631, MT7668)

    Identifying the main WiFi/BT chip first often helps locate its associated SPI flash. A quick search for the identified chip’s datasheet or block diagram can confirm its firmware storage mechanism.

    Hardware Setup for SPI Flash Dumping

    Essential Tools

    To successfully dump SPI flash firmware, you’ll need a few specialized tools:

    • SPI Programmer: A device capable of communicating over the SPI bus. Popular choices include:
      • Raspberry Pi (with `spidev` module enabled)
      • Bus Pirate
      • FT232H Breakout Board
      • Dedicated USB SPI Programmers (e.g., CH341A)
    • SOIC/WSON Test Clip: An essential tool for non-destructive connection to the chip. Ensure it matches your chip’s package size (e.g., SOIC8 150mil or 200mil, WSON8).
    • Jumper Wires: For connecting the programmer to the clip.
    • Multimeter: To verify voltage levels and continuity.
    • Magnifying Glass/Microscope: To aid in chip identification and precise clip placement.
    • Soldering Iron & Solder (optional): If a clip is not feasible, direct soldering might be necessary.
    • ESD Protection: Always use an anti-static mat and wrist strap.

    Identifying the SPI Flash and Pinout

    Once you’ve located a likely SPI flash chip, carefully note down its markings. Search online for the datasheet using the manufacturer and part number. The datasheet will provide the exact pinout, maximum voltage, and supported commands.

    For example, a common Winbond W25Q64FV (64Mbit / 8MB) SOIC-8 chip pinout:

    • Pin 1: CS# (Chip Select)
    • Pin 2: DO (Data Out / MISO)
    • Pin 3: WP# (Write Protect)
    • Pin 4: GND (Ground)
    • Pin 5: DI (Data In / MOSI)
    • Pin 6: CLK (Serial Clock)
    • Pin 7: HOLD# (Hold)
    • Pin 8: VCC (Power Supply)

    Important: Always verify the VCC (power supply) of the target flash chip. Most operate at 3.3V, but some older or specific chips might use 1.8V or 5V. Ensure your SPI programmer’s I/O voltage matches the chip’s VCC to prevent damage.

    Connecting the Programmer (Raspberry Pi Example)

    Using a Raspberry Pi as an SPI programmer is a cost-effective and powerful solution. First, enable SPI on your Raspberry Pi:

    sudo raspi-config

    Navigate to "Interface Options" > "SPI" > "Yes" to enable the SPI interface. Then, connect your SOIC/WSON clip to the Raspberry Pi’s GPIO pins:

    • Flash VCC (Pin 8) <–> Raspberry Pi 3.3V (Pin 1 or 17)
    • Flash GND (Pin 4) <–> Raspberry Pi GND (Pin 6, 9, 14, 20, 25, 30, 34, 39)
    • Flash CS# (Pin 1) <–> Raspberry Pi CE0 (GPIO8, Pin 24)
    • Flash CLK (Pin 6) <–> Raspberry Pi SCLK (GPIO11, Pin 23)
    • Flash MOSI (Pin 5) <–> Raspberry Pi MOSI (GPIO10, Pin 19)
    • Flash MISO (Pin 2) <–> Raspberry Pi MISO (GPIO9, Pin 21)
    • Flash WP# (Pin 3) <–> Raspberry Pi GND (for disabling write protect)
    • Flash HOLD# (Pin 7) <–> Raspberry Pi 3.3V (for disabling hold function)

    Ensure the Android device is powered off and disconnected from any power source before connecting the clip. Verify all connections with a multimeter before proceeding.

    Dumping the Firmware

    Software Tools: `flashrom`

    `flashrom` is an open-source utility for identifying, reading, writing, verifying, and erasing flash chips. It supports a wide range of programmers and flash chip types, making it the go-to tool for this task.

    Installation and Configuration

    On your Raspberry Pi (or any Linux system with SPI support), install `flashrom`:

    sudo apt update sudo apt install flashrom

    Verify that the SPI device node exists:

    ls /dev/spidev0.0

    If it doesn’t appear, ensure SPI is correctly enabled and the `spidev` kernel module is loaded (`sudo modprobe spidev`).

    Performing the Dump

    With `flashrom` installed and your hardware connected, you can now attempt to detect and dump the firmware. First, try to detect the chip:

    sudo flashrom -p linux_spi:dev=/dev/spidev0.0 -L

    The `-L` flag lists supported chips and tries to detect yours. If `flashrom` successfully identifies your chip (e.g., "Found Winbond flash chip ‘W25Q64.V’ (8192 kB)"), you can proceed to dump the content:

    sudo flashrom -p linux_spi:dev=/dev/spidev0.0 -r wifi_bt_firmware.bin

    This command instructs `flashrom` to read the entire contents of the flash chip and save it to `wifi_bt_firmware.bin`. The process can take several minutes depending on the chip size and SPI speed. It’s good practice to dump the firmware multiple times and compare the checksums (e.g., using `sha256sum`) to ensure a consistent and error-free dump.

    sha256sum wifi_bt_firmware.bin sha256sum wifi_bt_firmware_2.bin

    If the checksums match, you have a reliable dump.

    Analyzing the Firmware Dump

    Initial Inspection with `binwalk`

    `binwalk` is a fast, easy-to-use tool for analyzing binary images, specifically designed for firmware analysis. It can identify embedded files and executable code:

    binwalk wifi_bt_firmware.bin

    This command will scan the binary for known file headers, compressed data, and file system structures. Common findings might include:

    • ELF executables (ARM, MIPS)
    • Compressed data (zlib, LZMA)
    • Filesystem images (squashfs, jffs2, cramfs)
    • Certificate data

    To extract any identified files, use the `-e` flag:

    binwalk -e wifi_bt_firmware.bin

    This will create a directory (e.g., `_wifi_bt_firmware.bin.extracted`) containing all extracted components, allowing for further individual analysis.

    String Analysis and Heuristics

    The `strings` utility is invaluable for quickly identifying human-readable text within a binary. This can reveal debug messages, version numbers, configuration parameters, function names, and even hardcoded credentials:

    strings wifi_bt_firmware.bin | less strings wifi_bt_firmware.bin | grep -i "bluetooth" strings wifi_bt_firmware.bin | grep -i "debug"

    Look for interesting keywords related to network configurations, security, or device-specific functionalities. These strings often provide valuable context for understanding the firmware’s purpose and potential attack surfaces.

    Firmware Emulation/Disassembly (Briefly)

    For deeper analysis, especially if `binwalk` extracted executable code (like ARM ELF files), you’ll need reverse engineering tools:

    • Ghidra / IDA Pro: For disassembling and decompiling the firmware. These tools help visualize control flow, identify functions, and understand the logic.
    • Unicorn Engine: For emulating specific code paths or functions within the firmware without needing the actual hardware. This is useful for dynamic analysis of firmware components.

    This level of analysis is complex and often requires a deep understanding of assembly language and processor architecture, but it’s the next logical step once initial structures are identified.

    Conclusion

    Dumping and analyzing Android WiFi/Bluetooth SPI flash firmware is a fundamental skill in hardware reverse engineering and security research. This guide has equipped you with the knowledge and practical steps to identify the flash chip, connect an SPI programmer, reliably dump the firmware, and perform initial analysis using `flashrom`, `binwalk`, and `strings`. From here, the journey branches into deeper binary analysis, exploit development, or custom firmware modification, opening up a world of possibilities for understanding and controlling your device’s wireless capabilities.

  • Troubleshooting & Forensics: Using SPI Flash Dumps for Android WiFi/BT Firmware Analysis

    Introduction: Unlocking the Black Box of Android Connectivity

    In the complex world of Android devices, the WiFi and Bluetooth modules are critical components, yet their inner workings often remain a black box. When troubleshooting persistent connectivity issues, investigating potential firmware-level malware, or conducting advanced hardware forensics, accessing the firmware that governs these modules becomes paramount. Standard debugging tools often fall short, as the WiFi/BT firmware typically operates on a dedicated chip, separate from the main application processor and its accessible storage.

    This article delves into the expert-level technique of direct SPI flash dumping. By physically extracting the firmware from the WiFi/Bluetooth module’s dedicated SPI flash memory, we gain unprecedented insight into its operation, configuration, and potential vulnerabilities. This method is crucial for deep-dive analysis that goes beyond what software-level tools can provide.

    Understanding SPI Flash and its Role in WiFi/BT Modules

    What is SPI Flash?

    SPI (Serial Peripheral Interface) flash memory is a type of non-volatile storage commonly used in embedded systems due to its simplicity, speed, and low pin count. It communicates serially with a host controller (in this case, often a dedicated microcontroller within the WiFi/BT module itself, or sometimes directly controlled by the SoC during boot). Unlike NAND or eMMC which require complex controllers, SPI flash is relatively straightforward to interface with, making it ideal for storing bootloaders, configuration data, and firmware images for peripherals.

    Why WiFi/BT Firmware Resides on SPI Flash

    Modern WiFi and Bluetooth modules (e.g., from Broadcom, Qualcomm, MediaTek) are often highly integrated System-on-Chips (SoCs) themselves. To operate efficiently and independently of the main Android SoC, they require their own dedicated firmware and configuration data. This data is typically stored on a small, external SPI flash chip adjacent to the WiFi/BT module on the PCB. This design allows the WiFi/BT SoC to boot quickly, manage its radio functions, and communicate with the main Android processor via various interfaces (SDIO, PCIe, UART) using its pre-loaded firmware, even before the main Android OS is fully operational.

    Prerequisites and Tools

    Before attempting an SPI flash dump, ensure you have the following:

    • Android Device: The target device requiring analysis.
    • SPI Programmer: A hardware device capable of reading/writing SPI flash. Popular choices include the Bus Pirate, Raspberry Pi (with appropriate software), or dedicated USB-based programmers like the CH341A.
    • SOIC Clip or Soldering Equipment: An eight-pin SOIC test clip (e.g., Pomona 5250) is highly recommended for non-destructive connection. If a clip isn’t feasible, a fine-tip soldering iron, flux, and thin wires are necessary.
    • Multimeter: For identifying pinouts and verifying connections.
    • Magnification: A microscope or strong loupe is essential for inspecting small surface-mount components.
    • Software:
      • Flashrom: An open-source utility for identifying and programming flash chips.
      • Binwalk: A firmware analysis tool for extracting embedded files and executables.
      • Hex Editor: For low-level binary analysis (e.g., HxD, 010 Editor, Bless).
      • Strings Utility: For extracting human-readable strings from binary data.

    Step-by-Step: Obtaining the SPI Flash Dump

    1. Locating the SPI Flash Chip on the Android Device

    The first critical step involves carefully disassembling the Android device to expose the mainboard. Once exposed, identify the WiFi/BT module, which is typically a shielded metal can or a distinct IC package often marked with vendor logos (e.g., Broadcom, Qualcomm). Next, look for a small, 8-pin SOIC (Small Outline Integrated Circuit) package located very close to the WiFi/BT module. These chips are usually marked with vendor names like Winbond (W25Q series), Macronix (MX25L series), or GigaDevice. Consult datasheets for potential chip markings if unsure. A multimeter can help identify GND and VCC pins for confirmation.

    2. Connecting the SPI Programmer

    Connecting the SPI programmer requires precision. The SOIC clip is the safest method. Carefully align the clip with the chip, ensuring good contact on all eight pins. Pin 1 of the chip is usually indicated by a dot or a bevel. If soldering, identify the pinout from the chip’s datasheet (VCC, GND, CS, CLK, MISO, MOSI) and carefully solder thin wires from the chip’s pins to your programmer’s corresponding pins.

    A typical SPI pinout for an 8-pin SOIC flash chip:

    Pin 1: CS (Chip Select)Pin 2: SO (Serial Data Out / MISO)Pin 3: WP (Write Protect)Pin 4: GND (Ground)Pin 5: SI (Serial Data In / MOSI)Pin 6: CLK (Serial Clock)Pin 7: HOLD (Hold)Pin 8: VCC (Power Supply)

    Ensure your programmer’s voltage (typically 3.3V) matches the chip’s operating voltage to prevent damage.

    3. Dumping the Firmware with Flashrom

    With the programmer connected, install `flashrom` on your analysis workstation. Assuming your programmer (e.g., Bus Pirate) is recognized as a serial device (e.g., `/dev/ttyUSB0`):

    First, detect the chip:

    flashrom -p buspirate_spi:dev=/dev/ttyUSB0 -V

    This command attempts to identify the flash chip. If successful, you’ll see details about the detected chip. If not, recheck connections and voltage.

    Once detected, proceed to dump the flash content:

    flashrom -p buspirate_spi:dev=/dev/ttyUSB0 -r wifi_bt_firmware.bin

    This command reads the entire content of the SPI flash chip and saves it to `wifi_bt_firmware.bin`. The process can take several minutes depending on the flash size and programmer speed. Always dump multiple times and compare checksums to ensure a consistent, error-free dump.

    Analyzing the SPI Flash Dump

    Once you have a reliable `wifi_bt_firmware.bin` file, the real analysis begins.

    1. Initial Inspection with Binwalk

    Binwalk is an indispensable tool for initial firmware analysis. It can identify common file system signatures, compression algorithms, and executable code within binary blobs.

    binwalk -Me wifi_bt_firmware.bin

    The `-Me` flag recursively extracts identified components. Binwalk might reveal embedded Linux kernel images, root file systems (like SquashFS, JFFS2), configuration files, and raw firmware blobs specific to the WiFi/BT chip. These extracted components provide a structured view of the firmware’s contents.

    2. Deep Dive with Hex Editors and String Search

    For a more granular view, use a hex editor to inspect the raw binary data. Look for human-readable strings that can provide context:

    hexdump -C wifi_bt_firmware.bin | lessstrings -n 8 wifi_bt_firmware.bin | grep -i

  • Android WiFi/BT Firmware Dump: Your Practical Guide to SPI Flash Extraction

    Introduction: Unlocking the Secrets of Android WiFi/BT Firmware

    In the realm of Android hardware reverse engineering, gaining access to the low-level firmware that controls critical components like Wi-Fi and Bluetooth modules is a pivotal step. This firmware, often stored on dedicated Serial Peripheral Interface (SPI) flash memory chips, dictates how these wireless communication systems operate, handles protocols, and manages security. Understanding and analyzing this firmware can uncover vulnerabilities, facilitate custom module development, aid in debugging complex hardware issues, or even enable specialized device functionality.

    This guide provides a comprehensive, expert-level walkthrough on how to physically extract (dump) the WiFi/Bluetooth firmware directly from the SPI flash memory of an Android device. We will cover everything from identifying the target chip to using specialized hardware and software tools to read its contents.

    Prerequisites: Tools of the Trade

    Before embarking on the firmware dumping journey, ensure you have the following essential hardware and software components:

    Hardware Tools:

    • Android Device: The target device for firmware extraction.
    • Soldering Iron & Solder: For desoldering or making fine connections if a clip is not feasible.
    • Hot Air Rework Station: Indispensable for safely desoldering surface-mount chips, especially WSON/QFN packages.
    • Magnification Device: A microscope or powerful magnifying lamp is crucial for identifying small chip markings and precise soldering.
    • Multimeter: For checking continuity, voltage levels, and identifying ground/VCC pins.
    • SPI Programmer: A dedicated device to interface with the SPI flash. Popular choices include:
      • CH341A Programmer: Affordable and widely available (ensure it supports 3.3V/1.8V if your chip is lower voltage).
      • Bus Pirate: Versatile tool with SPI support.
      • J-Link/ST-Link: Some debug probes can also be configured for SPI communication.
    • SOIC/WSON/SOP Test Clip: A spring-loaded clip (e.g., Pomona 5250) can connect directly to the chip pins without desoldering, saving time and reducing risk for larger packages.
    • Fine Gauge Wires: Kynar or similar wires (30 AWG) for direct soldering if clips aren’t an option.
    • Flux & Isopropyl Alcohol: For clean soldering and post- 작업 cleanup.
    • ESD Mat & Wrist Strap: Essential for preventing electrostatic discharge damage to sensitive components.

    Software Tools:

    • Flashrom: An open-source utility for identifying, reading, writing, and erasing flash ROM chips. Highly recommended for SPI operations.
    • Hex Editor: For initial inspection of the dumped binary (e.g., HxD, 010 Editor, Bless).
    • Manufacturer Datasheets: Crucial for identifying chip pinouts and operating voltages.
    • Linux-based OS: (e.g., Ubuntu, Kali Linux) is ideal as `flashrom` is natively supported and most SPI programmers have better driver support.

    Step 1: Disassembling the Android Device and Locating the SPI Flash

    Device Disassembly:

    Carefully disassemble your Android device. This often involves heat (for adhesive screens/backs), plastic prying tools, and small screwdrivers. Document each step and organize screws to ensure proper reassembly.

    Identifying the WiFi/BT Module:

    Once the device is open, locate the main PCB. The WiFi/Bluetooth module is typically an integrated circuit (IC) or a System-on-Chip (SoC) often housed within a shielded can or clearly marked on the PCB. Common manufacturers include Broadcom (now Cypress), Qualcomm, MediaTek, and Realtek. Look for antennas connected to this module.

    Pinpointing the SPI Flash Chip:

    The WiFi/BT module often interfaces with a separate, smaller SPI flash chip that stores its firmware. This chip is usually located very close to the main WiFi/BT IC. Key characteristics to look for:

    • Size: Typically small, 8-pin (SOIC-8, WSON-8) or sometimes 16-pin packages.
    • Markings: Look for manufacturer logos (e.g., Winbond, Macronix/MXIC, Gigadevice, Spansion, Adesto) and part numbers (e.g., “W25Q64FW” for Winbond 64Mbit).
    • Traces: Observe traces connecting to the main WiFi/BT module. SPI communication typically involves four main lines (MOSI, MISO, SCK, CS#) plus VCC and GND.

    Once you’ve tentatively identified a chip, search its part number online to retrieve its datasheet. This datasheet is critical for confirming it’s an SPI flash, identifying its pinout, and determining its operating voltage (e.g., 3.3V, 1.8V). Never assume the voltage; always verify with the datasheet.

    Step 2: Connecting to the SPI Flash Chip

    This is the most delicate part of the process, requiring precision.

    Method A: In-Circuit Connection (Using a Test Clip)

    If the chip is a SOIC-8 or similar package with accessible pins, a test clip is the safest and easiest method.

    1. Clean the Chip: Use isopropyl alcohol to clean any flux residue or contaminants from the chip’s pins.
    2. Attach the Clip: Carefully align and attach the SOIC clip to the chip. Ensure all pins make good contact. Double-check the orientation of Pin 1 on the clip with Pin 1 on the chip.
    3. Wire to Programmer: Connect the clip’s breakout wires to your SPI programmer according to the pinout from the datasheet:
      • VCC: Chip VCC to Programmer VCC
      • GND: Chip GND to Programmer GND
      • SCK (Serial Clock): Chip SCK to Programmer SCK
      • MOSI (Master Out Slave In): Chip MOSI to Programmer MOSI
      • MISO (Master In Slave Out): Chip MISO to Programmer MISO
      • CS# (Chip Select): Chip CS# to Programmer CS#
    4. Power: Ensure your programmer provides the correct voltage to the chip (e.g., 3.3V or 1.8V). Some chips can be powered by the programmer, others might require the device to be partially powered (which is riskier). It’s generally safer to power the chip *only* from the programmer or remove the chip entirely. If powering in-circuit, ensure the device is off and the flash chip’s VCC is isolated from the main board’s power rails.

    Method B: Desoldering the Chip (If Clips are Not Feasible)

    For smaller WSON, QFN, or BGA packages, desoldering is often necessary. This requires a hot air rework station.

    1. Prepare the Area: Apply flux around the chip.
    2. Heat and Remove: Using appropriate hot air temperature (refer to component manufacturer’s recommended reflow profile, typically 250-300°C for lead-free solder) and airflow, carefully heat the chip until solder melts. Gently lift the chip with tweezers.
    3. Mount to Adapter: Once removed, solder the chip onto a suitable breakout board (e.g., WSON-8 to DIP-8 adapter) to easily connect it to your SPI programmer.

    Step 3: Dumping the Firmware with Flashrom

    With your SPI programmer connected to the flash chip (either in-circuit or on an adapter), it’s time to use `flashrom`.

    1. Install Flashrom:

    If you haven’t already, install `flashrom` on your Linux system. On Debian/Ubuntu:

    sudo apt update sudo apt install flashrom

    2. Connect the SPI Programmer:

    Plug your CH341A (or other programmer) into your computer’s USB port.

    3. Identify the Programmer and Chip:

    First, verify `flashrom` can detect your programmer. For a CH341A:

    sudo flashrom -p ch341a_spi

    If detected, `flashrom` will attempt to identify the connected SPI flash chip. If it successfully identifies it (e.g., “Found Winbond flash chip ‘W25Q64FW’ (8192 kB)”), you’re good to go.

    If `flashrom` doesn’t identify the chip, double-check your connections, power supply, and ensure the correct voltage is being applied. You might need to manually specify the chip type if `flashrom` fails to auto-detect:

    sudo flashrom -p ch341a_spi -c W25Q64FW

    (Replace `W25Q64FW` with your specific chip model.)

    4. Read the Firmware:

    To dump the entire contents of the flash chip to a binary file, use the `-r` option:

    sudo flashrom -p ch341a_spi -r wifi_bt_firmware.bin

    This command will read the flash memory and save it as `wifi_bt_firmware.bin` in your current directory. The process can take a few minutes depending on the flash size.

    5. Verify the Dump:

    It’s crucial to verify the integrity of your dump. Read the flash memory multiple times and compare the resulting files. If they are identical, you have a reliable dump.

    sudo flashrom -p ch341a_spi -r wifi_bt_firmware_2.bin sha256sum wifi_bt_firmware.bin sha256sum wifi_bt_firmware_2.bin

    The SHA256 checksums should match exactly.

    Step 4: Analyzing the Dumped Firmware

    Once you have a verified firmware dump, you can begin the analysis phase.

    • Hex Editor: Open `wifi_bt_firmware.bin` in a hex editor. Look for readable strings, potential version numbers, device identifiers, or configuration data.
    • Binwalk: This powerful tool can identify common file types and embedded structures within binary images.
    • binwalk -Me wifi_bt_firmware.bin
    • Ghidra/IDA Pro: For deeper analysis, these disassemblers and reverse engineering frameworks can be used to disassemble the firmware, identify functions, and understand its logical flow. You’ll need to know the CPU architecture of the WiFi/BT module (e.g., ARM, MIPS) to correctly analyze the code.

    Conclusion

    Dumping Android WiFi/Bluetooth firmware from SPI flash is a fundamental technique in hardware reverse engineering. It provides a direct window into the low-level operations of these critical wireless components. While requiring careful execution and specific tools, the ability to extract, analyze, and potentially modify this firmware opens up numerous possibilities for security research, custom development, and deeper hardware understanding. Always proceed with caution, ensure proper ESD practices, and verify your results thoroughly.

  • Scripting Android UART Interactions: Automate Bring-Up, Logs & Custom Commands

    Introduction: The Unseen Gateway – UART in Android Systems

    In the intricate world of Android hardware reverse engineering and system bring-up, the Universal Asynchronous Receiver-Transmitter (UART) interface stands as an invaluable, often overlooked, console. Unlike ADB, which relies on a functional OS, UART provides a low-level, direct communication channel with the device’s bootloader, kernel, and early user-space processes. This direct access is crucial for diagnosing boot failures, bypassing software locks, dumping critical logs during early boot stages, and even injecting commands before the Android operating system fully initializes. While manual interaction via tools like Minicom or Screen is common, automating these interactions with scripts can drastically improve efficiency, reproducibility, and the depth of analysis, especially during repetitive bring-up tasks or complex debugging scenarios.

    Why UART is Essential for Android Bring-Up and RE

    • Early Boot Visibility: Capture logs from the bootloader (U-Boot, Little Kernel, LK) and early kernel stages that are invisible to ADB.
    • Bypass OS Locks: Gain a console even when the Android OS is bricked, locked, or unresponsive.
    • System Diagnostics: Debug kernel panics, boot loops, and hardware initialization issues.
    • Security Research: Interact with secure boot processes, analyze firmware, and potentially find vulnerabilities.
    • Automated Testing: Script command injection and log capturing for automated regression testing during hardware development.

    Identifying and Connecting to the UART Console

    Before scripting, you need to physically locate and connect to the UART pins on your Android device. This often involves disassembling the device and identifying test points or dedicated debug headers.

    1. Pin Identification and Location

    Typical UART interfaces consist of four pins: TX (transmit), RX (receive), GND (ground), and VCC (power, often unused for data communication but useful for orientation). Common locations include:

    • Test Points: Small, unlabeled pads on the PCB, often near the SoC or power management ICs. Look for clusters of three or four pads.
    • Dedicated Debug Headers: Sometimes a 4-pin header is explicitly labeled or commonly found on development boards.
    • USB Data Lines (D+/D-): Rarely, USB data lines can be re-purposed for UART during early boot.
    • Component Datasheets/Schematics: If available, these are the definitive source for pin identification.

    Once identified, use a multimeter in continuity mode to confirm GND. You can often infer TX/RX by observing activity during boot with an oscilloscope, or simply try connecting and swapping TX/RX if no output appears.

    2. Hardware Connection

    You’ll need a USB-to-TTL serial adapter (e.g., FTDI FT232R, CP2102, CH340G). Connect as follows:

    • Device TX <–> Adapter RX
    • Device RX <–> Adapter TX
    • Device GND <–> Adapter GND

    Crucial Note: Ensure the adapter’s voltage level (3.3V or 1.8V) matches the device’s UART voltage. Supplying 5V to a 1.8V rail can damage the device.

    3. Initial Manual Connection and Baud Rate Discovery

    Once connected, plug the USB-to-TTL adapter into your host PC. Identify the serial port (e.g., /dev/ttyUSB0 on Linux, COMx on Windows). The most challenging part is often finding the correct baud rate. Common baud rates include 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600. Try the most common (115200) first, then systematically cycle through others while rebooting the device.

    Using minicom (Linux example):

    sudo apt-get install minicom # If not installed
    sudo minicom -s # Configure serial port (e.g., /dev/ttyUSB0, 115200 8N1)
    # Save configuration and exit. Then run:
    sudo minicom
    

    Reboot your Android device. If you see garbled text, try a different baud rate. Clear text indicates success.

    Automating UART with Python and PySerial

    Python’s pyserial library is the industry standard for serial communication. It allows for programmatic control over the UART interface, enabling automation of complex interactions.

    1. Installation

    pip install pyserial
    

    2. Basic Scripting: Reading Boot Logs

    This script connects to the serial port and continuously prints incoming data, effectively capturing the entire boot log.

    import serial
    import sys
    
    # Configuration
    SERIAL_PORT = '/dev/ttyUSB0'  # Or 'COM3' on Windows
    BAUD_RATE = 115200
    TIMEOUT = 1  # Read timeout in seconds
    
    def capture_boot_log(port, baud_rate, timeout):
        try:
            ser = serial.Serial(port, baud_rate, timeout=timeout)
            print(f"Connected to {port} at {baud_rate} baud.")
            print("Waiting for data... Reboot your Android device now.")
            
            with open("boot_log.txt", "w") as f:
                while True:
                    try:
                        line = ser.readline().decode('utf-8', errors='ignore').strip()
                        if line:
                            print(line)
                            f.write(line + 'n')
                    except serial.SerialException as e:
                        print(f"Serial error: {e}")
                        break
                    except KeyboardInterrupt:
                        print("Log capture stopped by user.")
                        break
        except serial.SerialException as e:
            print(f"Error connecting to serial port: {e}")
            sys.exit(1)
        finally:
            if 'ser' in locals() and ser.is_open:
                ser.close()
                print("Serial port closed.")
    
    if __name__ == "__main__":
        capture_boot_log(SERIAL_PORT, BAUD_RATE, TIMEOUT)
    

    3. Sending Commands and Receiving Responses

    To interact with the bootloader or kernel console, you’ll need to send commands and parse the responses. This is particularly useful for debugging or changing boot parameters.

    import serial
    import time
    
    SERIAL_PORT = '/dev/ttyUSB0'
    BAUD_RATE = 115200
    
    def send_and_receive(port, baud_rate, command, timeout=5, delay_after_cmd=0.1):
        try:
            ser = serial.Serial(port, baud_rate, timeout=timeout)
            print(f"Connected to {port} at {baud_rate} baud.")
    
            # Clear any pending input
            ser.flushInput()
            
            # Send command with newline
            ser.write(command.encode('utf-8') + b'n')
            print(f"Sent command: {command}")
            time.sleep(delay_after_cmd) # Give device time to process
    
            response = []
            start_time = time.time()
            while (time.time() - start_time)  0:
                    line = ser.readline().decode('utf-8', errors='ignore').strip()
                    if line:
                        response.append(line)
                else:
                    time.sleep(0.01) # Small delay to prevent busy-waiting
            
            ser.close()
            return "n".join(response)
    
        except serial.SerialException as e:
            print(f"Error: {e}")
            return None
    
    if __name__ == "__main__":
        # Example: Send 'help' command to U-Boot or Linux kernel console
        # Make sure your device is at a point where it accepts input (e.g., U-Boot prompt)
        print("Attempting to send 'help' command...")
        output = send_and_receive(SERIAL_PORT, BAUD_RATE, "help", timeout=10)
        if output:
            print("n--- Received Response ---")
            print(output)
            print("-------------------------")
        else:
            print("No response or error.")
    
        # Example: Check kernel version
        print("nAttempting to send 'cat /proc/version' command...")
        output = send_and_receive(SERIAL_PORT, BAUD_RATE, "cat /proc/version", timeout=5)
        if output:
            print("n--- Received Response ---")
            print(output)
            print("-------------------------")
        else:
            print("No response or error.")
    ```

    Advanced Automation: Bring-Up Sequences and Conditional Logic

    The real power of scripting lies in automating complex sequences that would be tedious or impossible to perform manually with precise timing.

    1. Automating Bootloader Interaction

    During Android system bring-up, you might need to interrupt the boot process at the bootloader prompt (e.g., U-Boot) to change environment variables, flash new images, or boot from a different partition. This requires sending a specific character (often space or 's') at the exact moment the bootloader displays its prompt.

    import serial
    import time
    import re
    
    SERIAL_PORT = '/dev/ttyUSB0'
    BAUD_RATE = 115200
    BOOTLOADER_PROMPT_REGEX = r"U-Boot>" # Adjust for your specific bootloader
    INTERRUPT_KEY = b' '
    
    def automate_bootloader_interrupt(port, baud_rate):
        try:
            ser = serial.Serial(port, baud_rate, timeout=0.1) # Shorter timeout for responsive reading
            print(f"Connected to {port} at {baud_rate} baud. Waiting for bootloader prompt...")
    
            buffer = b""
            while True:
                data = ser.read(ser.in_waiting or 1) # Read available data or wait for one byte
                if data:
                    buffer += data
                    decoded_buffer = buffer.decode('utf-8', errors='ignore')
                    # print(decoded_buffer) # Uncomment for verbose debugging
                    
                    if re.search(BOOTLOADER_PROMPT_REGEX, decoded_buffer):
                        print("Bootloader prompt detected! Sending interrupt key...")
                        ser.write(INTERRUPT_KEY)
                        ser.write(b'n') # Sometimes a newline is needed to confirm
                        time.sleep(0.5)
                        print("Interrupt sent. Entering bootloader console.")
                        
                        # Now we are in the bootloader console, send a command
                        ser.write(b'printenvn')
                        time.sleep(1) # Give time for command to execute
    
                        response = ser.read(ser.in_waiting).decode('utf-8', errors='ignore')
                        print("n--- Bootloader Environment ---")
                        print(response)
                        print("------------------------------")
                        break
                time.sleep(0.01) # Prevent busy-waiting
    
        except serial.SerialException as e:
            print(f"Error: {e}")
        except KeyboardInterrupt:
            print("Script terminated by user.")
        finally:
            if 'ser' in locals() and ser.is_open:
                ser.close()
                print("Serial port closed.")
    
    if __name__ == "__main__":
        # To test this, power cycle your Android device while the script is running.
        automate_bootloader_interrupt(SERIAL_PORT, BAUD_RATE)
    ```

    2. Custom Command Sequences for Debugging

    Imagine you want to enable a specific debug mode early in the kernel boot, then capture logs for a few seconds, and finally reset the device. A script can handle this with precision.

    # (Assumes functions like send_and_receive from above are available or integrated)
    
    def debug_sequence(port, baud_rate):
        print("Starting debug sequence...")
        
        # Phase 1: Wait for a specific kernel message, then send a debug command
        ser = serial.Serial(port, baud_rate, timeout=0.1)
        print("Waiting for kernel to initialize...")
        buffer = ""
        while "init: Starting service 'healthd'" not in buffer:
            data = ser.read(ser.in_waiting or 1).decode('utf-8', errors='ignore')
            buffer += data
            if data: # Print data as it comes
                sys.stdout.write(data)
                sys.stdout.flush()
            time.sleep(0.01)
        
        print("nKernel healthd service detected. Injecting debug command...")
        ser.write(b'echo 1 > /sys/kernel/debug/tracing/tracing_onn') # Example command
        time.sleep(0.5)
        ser.write(b'dmesg | tail -n 20n')
        time.sleep(1)
        
        debug_output = ser.read(ser.in_waiting).decode('utf-8', errors='ignore')
        print("n--- Debug Command Output ---")
        print(debug_output)
        print("----------------------------")
    
        # Phase 2: Capture logs for a set duration
        print("Capturing logs for 5 seconds...")
        log_buffer = []
        start_time = time.time()
        while (time.time() - start_time) < 5:
            line = ser.readline().decode('utf-8', errors='ignore').strip()
            if line: 
                print(line)
                log_buffer.append(line)
        
        with open("debug_session_log.txt", "w") as f:
            f.write("n".join(log_buffer))
        print("Logs saved to debug_session_log.txt")
    
        # Phase 3: Send reboot command (if applicable/safe)
        print("Sending reboot command...")
        ser.write(b'rebootn')
        time.sleep(2) # Give time for reboot to initiate
    
        ser.close()
        print("Debug sequence completed.")
    
    if __name__ == "__main__":
        # This script assumes you start the Android device, then run this script
        # at the point where the kernel starts booting.
        debug_sequence(SERIAL_PORT, BAUD_RATE)
    

    These examples illustrate the foundation. With conditional logic, regular expressions, and careful timing, you can craft highly sophisticated scripts to navigate complex boot processes, automate firmware updates, or conduct deep-dive diagnostics for any Android device accessible via UART.

    Conclusion

    Scripting Android UART interactions is a powerful technique for anyone involved in hardware bring-up, reverse engineering, or deep-level debugging. By moving beyond manual console interaction and embracing automation with tools like Python's pyserial library, engineers and researchers can significantly enhance their capabilities to capture critical boot logs, inject precise commands at specific stages, and streamline complex diagnostic workflows. Mastering this skill unlocks a level of control and insight into Android systems that is simply not achievable through higher-level interfaces like ADB, making it an indispensable tool in the advanced technical arsenal.

  • Qualcomm & MediaTek UART Debug: Specific Tricks for Different Android Chipsets

    Introduction: The Unseen Lifeline of Android System Bring-Up

    In the intricate world of Android hardware reverse engineering and system bring-up, the Universal Asynchronous Receiver-Transmitter (UART) debug console stands as an indispensable tool. Before the Android operating system fully boots and `adb` becomes available, UART provides a direct, low-level serial communication channel to the device’s bootloaders and kernel. This enables developers and researchers to observe critical boot messages, debug early-stage crashes, and even interact with the system at a privileged level. While the fundamental principles of UART remain consistent, the specific methodologies and pin identification tricks often vary significantly between leading Android chipset manufacturers like Qualcomm and MediaTek.

    Understanding UART Fundamentals

    UART facilitates full-duplex serial communication between two devices. For debugging, we typically connect a host PC to the target device. The core signals involved are:

    • TX (Transmit): Data output from the target device.
    • RX (Receive): Data input to the target device.
    • GND (Ground): Common ground reference.

    These connections are typically made via a USB-to-TTL serial adapter (e.g., based on FTDI, CP2102, or CH340 chipsets), which converts the device’s TTL logic levels (1.8V, 3.3V, or 5V) to USB signals for your PC. Identifying the correct voltage level is crucial; connecting a 3.3V adapter to a 1.8V UART line can damage the chipset.

    The Role of UART in Android Boot Stages

    During the boot process, UART output typically includes:

    • Initial Boot ROM / Preloader (MediaTek): Low-level hardware initialization.
    • Primary Bootloader (PBL – Qualcomm) / Secondary Bootloader (SBL): Early hardware setup, boot device detection.
    • Little Kernel (LK) / U-Boot: Bootloader stage, responsible for loading the kernel.
    • Linux Kernel: Device driver initialization, system services start.

    Observing these messages is vital for diagnosing bootloops, kernel panics, and other early-stage failures that leave no trace once the system reboots.

    Qualcomm Chipsets: Unearthing the Debug Port

    Pin Identification Challenges and Techniques

    Qualcomm devices often present a greater challenge in locating exposed UART pins. Unlike some simpler boards, they rarely feature clearly labeled headers. Here’s how to approach it:

    1. Schematic/Boardview Analysis: If available, the device’s schematic or boardview is the ultimate source. Look for ‘UART_DM’, ‘UART_DEBUG’, or ‘MSM_UART’ related pins, often routed to test points (TPs).
    2. Visual Inspection: Look for clusters of small, unpopulated solder pads (often 3 or 4) near the SoC, PMIC, or USB port. These are common locations for debug headers.
    3. Continuity Check (Multimeter): Once potential pads are identified, use a multimeter in continuity mode. The GND pin is usually easy to find (connected to the board’s ground plane).
    4. Logic Analyzer & Oscillosocpe: This is the most reliable method without schematics. Connect a logic analyzer to suspicious pads and monitor them during boot. UART signals will appear as distinct asynchronous serial waveforms. You’ll typically look for a steady stream of data (TX from the device) during boot. The baud rate can often be inferred from the bit timing.

    Qualcomm’s debug UART typically operates at 115200 baud, 8N1 (8 data bits, no parity, 1 stop bit). However, early boot stages might use different speeds, or the kernel might switch to a different rate. Always try 115200 first.

    Interpreting Qualcomm Debug Output

    Early Qualcomm output often starts with low-level diagnostics from the Primary Bootloader (PBL) and Secondary Bootloader (SBL). Messages like:

    PBL: Booting primary bootloader. (0xXXXXXXXX)

    followed by SBL messages detailing eMMC/UFS initialization, partition loading, and eventually the Little Kernel (LK) or a custom bootloader loading. Kernel output will then follow, detailing driver initialization and Android’s startup.

    MediaTek Chipsets: More Accessible Debugging

    Pin Identification and Common Practices

    MediaTek chipsets are generally more developer-friendly when it comes to debug access. Often, you’ll find:

    • Labeled Headers: Many MediaTek development boards or even some retail devices explicitly label debug headers (e.g., ‘TXD’, ‘RXD’, ‘GND’, ‘VCC’).
    • Easily Identifiable Test Points: Even if not a full header, dedicated test points for UART are frequently present and can be identified by following traces from the SoC.
    • Documentation: MediaTek often provides more comprehensive documentation for their reference designs, which can help pinpoint UART locations.

    Similar to Qualcomm, a logic analyzer remains the most robust method for identification if labels are absent. MediaTek UARTs also commonly use 115200 baud, 8N1, though variations can exist. For voltage, 1.8V is common on modern chipsets, but 3.3V is still found.

    MediaTek Boot Stages and UART Interaction

    MediaTek’s boot process starts with the ‘Preloader’, an initial boot ROM that sets up basic hardware. UART output here is critical. Subsequently, the ‘Little Kernel’ (LK) takes over. MediaTek’s LK is often more verbose and interactive through the UART than Qualcomm’s equivalent. You might be able to halt the boot process and issue commands at the LK prompt:

    Welcome to LK! (YYYY-MM-DD HH:MM:SS) 

    At this prompt, commands like `help` can reveal available functions. This level of interaction is invaluable for flashing, partition manipulation, or even memory dumps before the full Android system loads.

    For example, to list partitions in LK:

    lk> part list

    This level of low-level control is a significant advantage in MediaTek reverse engineering and system bring-up.

    Setting Up Your Debug Environment

    Hardware Connections

    1. Identify Pins: Using the techniques above, locate TX, RX, and GND on your device. Confirm the voltage level (e.g., 1.8V or 3.3V) with a multimeter.
    2. Connect Adapter: Connect your USB-to-TTL adapter:
      • Adapter’s TX to Device’s RX
      • Adapter’s RX to Device’s TX
      • Adapter’s GND to Device’s GND

      Make sure to use an adapter that supports the correct voltage level (e.g., a 1.8V adapter for a 1.8V UART, or a switchable 3.3V/5V adapter if the device is 3.3V).

    3. Power On: Connect your device to its power source (battery or external power supply).
    4. Connect to PC: Plug the USB-to-TTL adapter into your computer.

    Software Configuration

    On your host PC, you’ll need a terminal emulator. Common choices include:

    • Linux/macOS: `minicom` or `screen`
    • Windows: PuTTY, Tera Term

    Example using `screen` on Linux (assuming your adapter is `/dev/ttyUSB0`):

    screen /dev/ttyUSB0 115200

    For `minicom`:

    minicom -s

    Then configure the serial port: select `/dev/ttyUSB0`, set baud rate to 115200, 8 data bits, no parity, 1 stop bit (8N1), and disable hardware/software flow control. Save as default, then exit setup to run.

    Advanced Tips and Troubleshooting

    • Power Cycle: Always power cycle the device after connecting UART to catch the very first boot messages.
    • Voltage Mismatch: If you get garbled output or no output, double-check your voltage levels. A mismatch can result in corrupted data or even damage.
    • TX/RX Swap: If you get no output, try swapping the TX and RX lines. This is a common mistake.
    • Baud Rate Hunting: While 115200 is standard, some devices use 9600, 57600, or even 230400. If initial attempts fail, cycle through common baud rates.
    • Activity Monitoring: A logic analyzer is invaluable for confirming UART activity, identifying TX/RX, and automatically detecting the baud rate.
    • Obscured Pins: Sometimes, debug pads are under shielding or BGA components. This requires careful physical disassembly, desoldering, or even sanding down layers to expose the traces.

    Mastering UART debugging for both Qualcomm and MediaTek chipsets is a cornerstone skill for anyone involved in deep Android system analysis. It provides an unparalleled window into the very first moments of a device’s life, critical for understanding, modifying, and repairing complex embedded systems.

  • Beyond ADB: How to Gain Full Control Over Android Startup with UART Console

    Introduction: The Deep Dive Beyond ADB

    For most Android developers and power users, the Android Debug Bridge (ADB) is the go-to tool for interacting with a device. It allows for application installation, shell access, log retrieval, and much more. However, ADB operates within the Android operating system itself. What happens when the OS won’t boot? What if you need to debug the bootloader, the kernel, or the very early stages of the Android init process? This is where the UART (Universal Asynchronous Receiver/Transmitter) console becomes an indispensable tool. Gaining UART access provides a low-level, serial interface to the device, offering unparalleled insight and control over the entire boot sequence, making it crucial for hardware reverse engineering, system bring-up, and deep-seated debugging.

    What is UART and Why It’s Indispensable?

    UART is a hardware communication protocol that allows for serial data exchange between two devices. In embedded systems like Android devices, a dedicated UART controller typically connects to a set of pins on the System-on-Chip (SoC). These pins are often exposed on the Printed Circuit Board (PCB) as test points or a dedicated debug header. Unlike USB, which requires complex drivers and enumeration, UART is a very simple, direct communication method that is often active from the moment the SoC powers on.

    Its criticality stems from:

    • Pre-boot Debugging: It’s active before the bootloader even starts, allowing you to see initial ROM code output, bootloader logs, and interrupt the boot sequence.
    • Kernel Debugging: Provides real-time kernel boot messages (`dmesg`), crash logs, and the ability to interact with the kernel console.
    • Early Android Init: Observe the `init` process as it starts essential services, crucial for diagnosing boot loops or failures before ADB can even connect.
    • Bypass OS Issues: Even if the Android OS is completely corrupted, UART can often still provide access to the bootloader, enabling re-flashing or recovery.

    Identifying and Accessing UART Ports

    Physical Identification on the PCB

    Finding the UART pins often requires a bit of detective work:

    • Visual Inspection: Look for unpopulated headers (e.g., 4-pin 2.54mm or 1.27mm pitch) or clusters of test points (small copper pads) near the SoC. Common labels might include ‘TX’, ‘RX’, ‘GND’, ‘VCC’.
    • Datasheets & Schematics: If available (often for development boards or open-source devices), these are the definitive source for pinouts.
    • Common SoC Placement: UART pins are frequently located close to the main SoC itself, or sometimes routed to an accessible edge connector.
    • Probing with a Multimeter/Oscilloscope:
    1. Ground (GND): Easily found by checking continuity to any metal shielding or the negative terminal of the battery connector.
    2. Voltage (VCC/3.3V/1.8V): Power on the device. Look for a stable voltage (typically 1.8V or 3.3V, sometimes 5V) on one of the potential UART pins. This isn’t always present for communication, but indicates a power line.
    3. Transmit (TX) & Receive (RX): With the device powered on, probe suspected data pins. The TX pin will usually show fluctuating voltage levels (data activity) especially during boot-up. The RX pin will typically be idle (high or low, depending on logic level) until data is sent to it. An oscilloscope is ideal for identifying data patterns and determining the baud rate.

    Voltage Level Matching

    Crucially, you must match the logic voltage levels of your device’s UART to your USB-to-UART converter. Modern Android devices often use 1.8V logic, while older or larger embedded systems might use 3.3V or 5V. Connecting a 3.3V converter to a 1.8V device can damage the device’s SoC. Many converters support multiple voltage levels (e.g., FT232RL breakout boards often have jumpers or switches). Always verify the voltage before connecting.

    Connecting Your Hardware

    Once you’ve identified TX, RX, and GND, you’ll need a USB-to-UART converter. Popular chips include FT232RL (FTDI), CH340, and CP2102. Ensure your converter supports the correct voltage level.

    • Converter’s TX connects to Device’s RX
    • Converter’s RX connects to Device’s TX
    • Converter’s GND connects to Device’s GND

    Important: Do NOT connect the VCC/power pin from your USB-to-UART converter to your Android device unless you are absolutely sure it’s needed and correctly configured. Powering the device via its own battery/power supply is standard practice.

    Software Setup: The Terminal Interface

    With the physical connection established, you’ll need a serial terminal program on your host computer.

    Linux Example (using screen or minicom)

    # Identify your USB-to-UART device (e.g., /dev/ttyUSB0 or /dev/ttyACM0)ls /dev/tty*# Install screen (if not already installed)sudo apt-get install screen# Connect with a common baud rate (e.g., 115200)screen /dev/ttyUSB0 115200# Alternatively, for more features, use minicom (Ctrl+A, then Z for menu)sudo apt-get install minicomminicom -b 115200 -o -D /dev/ttyUSB0

    Common baud rates for bootloaders and kernels include 9600, 19200, 38400, 57600, 115200, 460800, and 921600. 115200 is a very common default. If you see gibberish, try different baud rates.

    Windows Example (using PuTTY)

    1. Download and run PuTTY.
    2. Select
  • DIY Android UART Debug Adapter: Build Your Own Tool for Hardware Reverse Engineering

    Introduction to UART Debugging in Android Hardware Reverse Engineering

    In the intricate world of Android hardware reverse engineering, gaining low-level access to a device is paramount. While ADB (Android Debug Bridge) offers significant capabilities once the system is booted, it often falls short when dealing with bootloader issues, bricked devices, or when bypassing higher-level security mechanisms. This is where the Universal Asynchronous Receiver-Transmitter (UART) debug console becomes an indispensable tool. UART provides a direct, serial communication channel to the device’s core, offering insights into the boot process, kernel messages, and even an interactive shell before the Android operating system fully loads. This article will guide you through building your own DIY UART debug adapter, transforming a simple USB-to-TTL converter into a powerful forensic and debugging tool for Android devices.

    Why UART for Android Reverse Engineering?

    UART offers a unique window into an Android device’s soul, particularly during the critical boot-up phase. Here’s why it’s essential for hardware reverse engineers:

    • Early Boot Access: UART provides visibility into the bootloader and kernel initialization, allowing you to observe processes that occur before ADB becomes available. This is crucial for debugging boot loops or understanding device bring-up sequences.
    • Bypassing Security: Some Android devices might have USB debugging disabled or require specific authentication. UART often operates at a lower hardware level, sometimes bypassing software-imposed restrictions.
    • Kernel and Bootloader Debugging: Gain direct access to kernel messages, panic outputs, and bootloader logs. This can reveal vulnerabilities, help analyze custom firmwares, or assist in unbricking efforts.
    • Interactive Shell: On many devices, especially development boards or devices with less stringent security, the UART console can provide an interactive shell (e.g., U-Boot prompt or a minimal Linux shell) allowing direct command execution.

    Understanding UART Basics and Required Components

    UART Fundamentals

    UART communication relies on at least three signals: Transmit (TX), Receive (RX), and Ground (GND). A fourth pin, VCC, might also be present but is generally not connected when debugging a device that has its own power supply.

    • TX (Transmit): Sends data from the device (or adapter) to the connected peer.
    • RX (Receive): Receives data from the connected peer.
    • GND (Ground): Provides a common electrical reference point. Essential for communication.
    • VCC (Voltage Common Collector): Supplies power. Warning: Never connect VCC unless you are absolutely sure about voltage compatibility and that your device needs external power from the adapter. Incorrect voltage can permanently damage your device.

    Modern Android devices typically operate at 1.8V or 3.3V logic levels. It’s crucial that your USB-to-TTL adapter supports these levels.

    Components You’ll Need

    • USB-to-TTL Serial Adapter: A common adapter like the FT232RL, CP2102, or CH340G based modules. Ensure it supports 3.3V and 1.8V logic levels (many have jumpers to select).
    • Jumper Wires: Female-to-female or male-to-female, depending on your device’s test points.
    • Multimeter: Essential for identifying pins and checking voltage levels.
    • Soldering Iron and Solder (Optional but Recommended): For more permanent or reliable connections to small test points.
    • Magnifying Glass or USB Microscope (Optional): For inspecting tiny test points.
    • Android Device: The target for your reverse engineering efforts.
    • Computer: Running Linux, Windows, or macOS for the serial terminal software.

    Identifying UART Pins on Your Android Device

    This is often the most challenging part. Patience and methodical testing are key.

    1. Visual Inspection

    • Look for Test Points: Many PCBs have unlabeled test pads or small through-holes. These are prime candidates for UART.
    • Silkscreen Markings: Sometimes, pins are labeled directly on the PCB (e.g., TX, RX, GND).
    • FCC IDs and Schematics: Search online for your device’s FCC ID. This can sometimes lead to internal photos or even schematics that reveal pinouts.
    • Proximity: UART pins are often found near the main SoC, power management ICs, or even close to USB ports or headphone jacks.

    2. Using a Multimeter to Locate Pins

    Before connecting anything, power off your device and then reconnect the battery if it was removed for inspection.

    1. Locate GND: This is the easiest. Find any large ground plane or a metal shield and confirm continuity with the negative terminal of the battery. Mark it.
    2. Locate VCC (Optional, and with Caution): If you suspect a VCC pin, measure its voltage relative to GND when the device is powered on. Common voltages are 1.8V or 3.3V. If you find a stable voltage here, mark it, but do not connect it to your adapter’s VCC unless you are trying to power the board via the adapter (which is not recommended for debugging).
    3. Locate TX (Transmit) and RX (Receive): This requires some trial and error with the device powered on.
      • Set your multimeter to DC voltage mode.
      • Place the negative probe on a known GND point.
      • Carefully probe suspicious test points. A TX pin will often show a fluctuating voltage (e.g., ~1.8V or ~3.3V when idle, dropping or changing when data is transmitted), especially during device boot-up. An RX pin might show a stable voltage.
    4. The “Trial and Error with Loopback” Method: If you’ve narrowed down a few potential TX/RX pairs:
      • Connect your USB-to-TTL adapter to your PC.
      • Connect the potential GND pin on the device to the GND pin on your adapter.
      • Connect a potential TX pin on the device to the RX pin on your adapter.
      • Connect a potential RX pin on the device to the TX pin on your adapter.
      • Launch your serial terminal software (see next section) and set a common baud rate (e.g., 115200).
      • Power on the Android device. If you see gibberish or nothing, try different baud rates (9600, 57600, 230400, 460800, 921600). If still nothing, swap the TX and RX connections from the device to the adapter. Repeat until you get legible output.

    Connecting Your DIY UART Adapter

    Once you’ve identified the TX, RX, and GND pins on your Android device and selected the correct voltage level on your USB-to-TTL adapter (e.g., 3.3V or 1.8V), you can make the connections:

    1. Connect USB-to-TTL Adapter to PC: Plug your USB-to-TTL adapter into a USB port on your computer.
    2. Adapter Drivers: Install any necessary drivers for your adapter chip (FT232RL, CP2102, CH340G). On Linux, most are built-in. On Windows, you’ll likely need to download them.
    3. GND to GND: Connect the GND pin of your Android device to the GND pin of your USB-to-TTL adapter. This is the most critical connection.
    4. TX (Device) to RX (Adapter): Connect the Transmit (TX) pin of your Android device to the Receive (RX) pin of your USB-to-TTL adapter.
    5. RX (Device) to TX (Adapter): Connect the Receive (RX) pin of your Android device to the Transmit (TX) pin of your USB-to-TTL adapter.
    6. Do NOT Connect VCC: As reiterated, leave the VCC pin of the adapter disconnected unless you are explicitly trying to power the board through the adapter and are certain of voltage compatibility. Power your Android device via its own battery or power supply.

    Software Setup and Debugging

    With your hardware connected, it’s time to set up your computer to receive the serial data.

    1. Identify the Serial Port

    • Linux: Open a terminal and run dmesg | grep tty after plugging in the adapter. Look for entries like ttyUSB0 or ttyACM0. You can also check ls /dev/ttyUSB* or ls /dev/ttyACM*.
    • Windows: Open Device Manager and look under
  • Building Custom Proxies & Monitors for Android USB Debug Port Security Research

    Introduction: Unveiling the Hidden Depths of Android USB Debug Ports

    The USB debug port on an Android device is far more than just a charging interface or a data transfer conduit. It’s a critical gateway for developers, diagnostics, and, unfortunately, a potential attack surface for adversaries. For security researchers, understanding and controlling the data flowing through this port is paramount. While tools like Wireshark and `adb logcat` provide high-level insights, truly deep dives into proprietary protocols, vulnerability discovery, and low-level manipulation often require custom solutions. This article guides you through the process of building custom hardware and software proxies and monitors to gain unprecedented control over Android USB debug port communications.

    Understanding Android USB Debugging and Its Security Implications

    Android Debug Bridge (ADB) is the primary tool for communicating with Android devices over USB. It provides a robust set of commands for debugging, installing apps, shell access, and more. Underlying ADB are various USB protocols and configurations, often including USB-OTG (On-The-Go), CDC-ECM (Ethernet Control Model for network tethering), MTP (Media Transfer Protocol), and PTP (Picture Transfer Protocol), in addition to the proprietary ADB protocol itself. Each of these protocols presents a unique attack surface. A compromised debug port can lead to:

    • Unauthorized data extraction and injection.
    • Execution of arbitrary commands with elevated privileges.
    • Circumvention of device security features (e.g., bootloader unlocking, factory reset protection bypass).
    • Analysis of proprietary vendor implementations for vulnerabilities.

    The ability to intercept, modify, and inject packets at the USB layer allows researchers to test the robustness of Android’s USB stack and the security of applications interacting with it.

    Why Custom Proxies & Monitors? The Need for Low-Level Control

    Off-the-shelf USB sniffers (like those from Total Phase or BeagleBone Black acting as a sniffer) are excellent for passive monitoring. However, they typically don’t allow for active manipulation or real-time interception and modification of data streams. Custom proxies bridge this gap by placing a controllable intermediary between the Android device and the host (e.g., a PC or another Android device). This setup enables:

    • **Active Interception:** Reading and logging all traffic in both directions.
    • **Packet Manipulation:** Modifying specific bytes or entire packets on the fly.
    • **Fuzzing:** Injecting malformed packets to discover stack vulnerabilities.
    • **Protocol Reversal:** Understanding undocumented vendor-specific USB protocols.
    • **Bypass Attempts:** Testing mechanisms to bypass debug port access restrictions or authentication.

    By acting as both a USB host and a USB device simultaneously, a custom proxy provides unparalleled flexibility for security research.

    Hardware Setup & Prerequisites

    To build a custom USB proxy, you’ll need a few key components:

    1. Single-Board Computer (SBC)

      A powerful SBC with multiple USB ports is ideal. Raspberry Pi models (e.g., Pi 4) are excellent choices due to their versatile USB 2.0/3.0 capabilities and robust Linux support. Some SBCs also offer USB-OTG ports that can be configured as either host or device.

    2. USB-OTG Cables & Adapters

      Appropriate cables to connect your Android device to the SBC and the SBC to your research workstation.

    3. Target Android Device

      An Android device with developer options and USB debugging enabled. A rooted device provides additional flexibility for on-device analysis.

    4. Linux Host Machine

      A Linux distribution (Ubuntu, Debian, Kali Linux) for development and analysis. Essential tools include `libusb-dev`, `python3-dev`, `pyusb`, Wireshark, and potentially a kernel with `usb_f_mass_storage` and `g_ether` modules enabled if you plan to emulate specific USB device types.

    Building a Basic USB Passthrough/Monitor with Python and `pyusb`

    Before building a full proxy, let’s understand how to interact with USB devices programmatically. `pyusb` is a Python wrapper for `libusb` that allows enumerating, configuring, and communicating with USB devices. This example shows basic device enumeration and reading data from endpoints.

    First, ensure `pyusb` is installed:

    pip install pyusb

    Here’s a conceptual script to enumerate devices and attempt to read from an endpoint (requires root for direct device access):

    import usb.coreimport usb.util# Find your Android device (adjust vendor_id and product_id)VENDOR_ID = 0x18D1 # Google Inc.PRODUCT_ID = 0x4EE2 # Android Phone (check with lsusb)dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)if dev is None:    raise ValueError('Device not found')print(f