Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ghidra #22

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 62 additions & 32 deletions ReverseEngineering/LPC11U37F_Software.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
# LPC11U37F/501 Software

The purpose of this document is to track information regarding the software that
runs on the LPC11U37F main/master processor of the controller. The LPC11U37F
is a 32-bit processor ARMv6-M architecture with 16-bit Thumb ISA and includes
runs on the LPC11U37F main/master processor of the controller. The LPC11U37F
is a 32-bit processor ARMv6-M architecture with 16-bit Thumb ISA and includes
Thumb-2 technology.

## Firmware primer

The LPC11U37F binary is split into two parts: The first 0x2000 bytes contain
the bootloader, while the rest contains the firmware. You can find the version
of each component in Steam's controller "Support" screen, next to "bootloader
revision" and "firmware revision".

The bootloader's job is simple: If the firmware at 0x2000 looks correct (has the
right magic at offset 0x30) and GPREG1 of the CPU isn't set to a magic value,
the bootloader will simply jump to the firmware's entrypoint. However, if the
firmware doesn't have the right magic or GPREG1 has a magic value, the
bootloader will enter programming mode, exposing a HID device that the Steam
desktop software can communicate with to flash a new firmware.

The firmware's job is basically everything else, from playing the starting
jingle to getting button input and turning them into a HID stream to send over
USB/to the nRF chip.


# Reverse Engineering Artifacts

This section details the results of the reverse engineering effort. These are
This section details the results of the reverse engineering effort. These are
the final references that contain data which is the basis for other Subprojects.

Now that the artifacts below pertain to the vcf_wired_controller_d0g_57bf5c10.bin
Expand All @@ -20,7 +38,7 @@ This file contains data on how the simulation has shown the controller to behave
in different scenarios. The idea is to capture and identify as many actions
as possible (with a focus on finding recurring code and memory usage) so that
controller behavior can be understood to the extent and completely custom
firmware can be created.
firmware can be created.

## vcf_wired_controller_d0g_57bf5c10.h

Expand All @@ -29,11 +47,15 @@ This file tracks unique functions called in vcf_wired_controller_d0g_57bf5c10.c

## vcf_wired_controller_d0g_57bf5c10.mem

The file tracks memory usage and attempts to identify how different section of
memory are used by the firmware.
The file tracks memory usage and attempts to identify how different section of
memory are used by the firmware.

## vcf_wired_controller_d0g_57bf5c10.bootloader.gzf

# Resources
This file is a complete reverse engineering of the bootloader section of the
binary, using [Ghidra].

# Resources

* [Datasheet](http://www.nxp.com/documents/data_sheet/LPC11U3X.pdf?fasp=1&WT_TYPE=Data%20Sheets&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation&fileExt=.pdf)

Expand All @@ -44,12 +66,12 @@ The file tracks memory usage and attempts to identify how different section of

# Disassembling the Firmware

This section details the approaches attempted and ultimately used to reverse
This section details the approaches attempted and ultimately used to reverse
engineer the Steam Controller firmware running on the LPC11U37.

## [pinkySim](https://github.com/greggersaurus/pinkySim)

This is the primary method used for simulating the firmware and deconstructing
This is the primary method used for simulating the firmware and deconstructing
its behavior.

* Note: Need to build pinkySim specifically with command "make pinkySim" as building unit tests fails...
Expand All @@ -68,13 +90,13 @@ This is the primary method used for simulating the firmware and deconstructing

### Simulation Steps

#### Launch Simulator
#### Launch Simulator

The following command launches the emulator with the proper memory map for the
The following command launches the emulator with the proper memory map for the
LPC11U37F501, has the emulator halt on the first instruction to execute after
reset and instructs pinkySim to log all instructions executed to a file named
exeLog{timestmap}.csv. exeLog{timestmap}.c is also created, which makes a simple
attempt at a C-like decomposition of the simulated actions.
attempt at a C-like decomposition of the simulated actions.

* ./pinkySim --breakOnStart --logExe LPC11U37 --flash 0 131072 --ram 268435456 8192 --ram 536805376 16384 --ram 536870912 2048 --ram 536887296 2048 --ram 1073741824 16384 --ram 1073758208 16384 --ram 1073774592 16384 --ram 1073790976 16384 --ram 1073807360 16384 --ram 1073823744 16384 --ram 1073840128 16384 --ram 1073856512 16384 --ram 1073971200 16384 --ram 1073987584 16384 --ram 1074003968 16384 --ram 1074020352 16384 --ram 1074036736 16384 --ram 1074053120 16384 --ram 1074102272 16384 --ram 1074118656 16384 --ram 1074135040 16384 --ram 1074266112 16384 --ram 1342177280 16484 --ram 3758096384 1048576 firmware.bin
* Note: --ram 536805376 16384 --flash, but since we need to fill this ROM with the boot ROM code via gdb, this needs to be writable
Expand All @@ -99,64 +121,71 @@ This section details different paths from which we may want to simulate the firm
#### Initialization

By default, simulation starts at instruction specified via Vector Table RESET entry point.

Simulation is allowed to run with minimal intervention (i.e. loops waiting for
PLLs to lock or other hardware reactions are simulated as needed, pauses are
made to adjust values "read" from EEPROM).
made to adjust values "read" from EEPROM).

Unknown paths are identified to be revisited lated with further stimuli to
simulation runs. These are being marked by TODO: UNKOWN PATHS.

Attempts are made being made to identify SRAM0 memory usage.

#### Exceptions
#### Exceptions

This section details attempts to simulate certain exception paths. This is being
This section details attempts to simulate certain exception paths. This is being
pursued as Reset/Init path eventually called WFI instruction. This implies
interrupts occurring is a necessary part of system boot (i.e. either successful
connection or shutdown due to connection timeout).

Simulating an exception can be achieved by setting the PC register to the
Simulating an exception can be achieved by setting the PC register to the
instruction specified in the Vector Table. However, keep in mind the nuances
of how IRQ actually work and that simply setting the PC will allow you to
simulate the interrupt accurately, but may be desctructive in terms of picking
back up where the main thread code was interrupted.
of how IRQ actually work and that simply setting the PC will allow you to
simulate the interrupt accurately, but may be desctructive in terms of picking
back up where the main thread code was interrupted.

According to 24.3.3.6.1 xPSR, PC, LR, R12, R3, R2, R1 and R0 are saved upon
interrupt and restored upon exit. Save and restore these values if you want to
pick up the main thread after simulating an interrupt.

Also, according 24.3.3.6.1 LR is set to EXC_RETURN upon interrupt entry. Thus a
bx to LR (assuming no further stack pushes (without matching pops) to change
LR), will indicate an interrupt exit. In short, set LR to a know instruction
bx to LR (assuming no further stack pushes (without matching pops) to change
LR), will indicate an interrupt exit. In short, set LR to a know instruction
(maybe a WFI instruction or something that will cause an emulator break) before
changing the PC to the interrupt handler so that you know when the interrupt
changing the PC to the interrupt handler so that you know when the interrupt
handler is exiting.

## [FirmwareParser.py](./FirmwareParser.py)

This is only being used to display the Vector Table.

The original idea was to create disassembler that can recreate assembly file,
The original idea was to create disassembler that can recreate assembly file,
distinguishing data versus instructions by evaluating code and all possible
branches.
branches.

In the end this was a larger undertaking than expected. It would make more
sense to leverage pinkySim's ability to decode instructions and their
In the end this was a larger undertaking than expected. It would make more
sense to leverage pinkySim's ability to decode instructions and their
behavior to do this, as opposed to starting from scratch.

## [Ghidra]

Ghidra allows doing static analysis of binaries. We have a tutorial showing how
to load LPC11uxx binaries and start reverse engineering them at
[ghidra_guide.md](guidra_guide.md). Furthermore, you can load the existing gzf
present in this repository in Ghidra to see already-labeled functions.

## [Reverse Engineering for Beginners](https://github.com/dennis714/RE-for-beginners)

Have not made much use of this yet.
Have not made much use of this yet.

Free book geared towards beginners on how to reverse engineer code.

## [Radare](http://www.radare.org/r/)

This may be worth learning and using as a supplementary tool (now that time spent
with pinkySim has give me better understanding of assembly flow).
with pinkySim has give me better understanding of assembly flow).

Somewhat different approach than pinkySim in that we are looking at assembly and trying
Somewhat different approach than pinkySim in that we are looking at assembly and trying
to assess actions that could be taken and potential purpose, as opposed to focusing on
actions taken during simulation and why they were taken (and maybe should not have been).

Expand All @@ -169,7 +198,7 @@ Somewhat different approach than pinkySim in that we are looking at assembly and
* What about #if 0 section with armv6 options?
* How to deal with firmware stripped binary format (i.e. no code/data sections information)?
* Build up scripting tooling to handle this? (i.e. don't decode instructions we "know" we "cannot reach")
* Scripting to identify code/data semi-automatically?
* Scripting to identify code/data semi-automatically?
* Can use flow visualization to identify different sections of code to focus on?
* Allows us to see paths we are not taking (and where they might go), rather than just knowing a branch was not taken.

Expand Down Expand Up @@ -204,7 +233,7 @@ This proved to not be particularly useful for raw stripped binary.
This proved to not be particularly useful for raw stripped binary.

* ./arm-none-eabi-objdump -b binary -D vcf_wired_controller_d0g_57bf5c10.bin -m arm attempts to disassemble binary file
* With have firmware binary format (i.e. no code/data sections information) this only helps so much.
* With have firmware binary format (i.e. no code/data sections information) this only helps so much.
* Simulation with pinkySim can be utilized to possibly rebuild this section information and then revisit this tool?

## [ARMu](http://pel.hu/armu/)
Expand All @@ -219,3 +248,4 @@ Have not need to look into this much yet.

* Worth looking into?

[Ghidra]: https://github.com/NationalSecurityAgency/ghidra
27 changes: 15 additions & 12 deletions ReverseEngineering/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Reverse Engineering

Welcome to Reverse Engineering Subproject portion the Open Steam Controller effort.
Welcome to Reverse Engineering Subproject portion the Open Steam Controller effort.

The work in this directory is the result of trying to understand the hardware
and its capabilities based on the available resources. In this case the resources
available were the circuit board itself and the raw binary firmware for the
controller's main processor (the LPC11U37F).
controller's main processor (the LPC11U37F).

There is a lot of really neat and useful information captured here (i.e. the
fact that there is a section of EEPROM where Jingle Data can be stored to
change the official firmware's default behavior, how the interface to the
Trackpads works) and the result of these efforts are the basis of many of the
Trackpads works) and the result of these efforts are the basis of many of the
Subprojects in the Open Steam Controller effort. If anything is unclear, or
you think I am not drawing proper attention to feature I have unearthed,
please be sure to let me know.
Expand All @@ -19,7 +19,7 @@ See the sections below for further details on the data that has been captured
in regards to the hardware and software, but please note that this is my first attempt
at reverse engineering. I may have not gone about this in the most efficient
or understandable manner, but I have done my best to make sure the results
are captured concisely so that others may benefit from it.
are captured concisely so that others may benefit from it.


# Understanding the Hardware
Expand All @@ -28,26 +28,29 @@ This section captures details on the controller hardware (i.e. what pins are
connected to what peripherals or pins on other chips). This data was sometimes
obtained simply by using digital multimeter to ohm out connections. Other times
reverse engineering the firmware, or running tests with custom firmware were
required to fully understand how the hardware was designed.
required to fully understand how the hardware was designed.

See [Luna_maiboard_V000456-00_rev3.md](./Luna_maiboard_V000456-00_rev3.md)
for information regarding the Steam Controller hardware pertaining to
See [Luna_maiboard_V000456-00_rev3.md](./Luna_maiboard_V000456-00_rev3.md)
for information regarding the Steam Controller hardware pertaining to
Luna_mainboard V000456-00 rev3.


# Understanding the Software

This section captures details on the software running on the controller
## PinkySim and Ghidra

This section captures details on the software running on the controller
processors. This data was primarily obtained by using a modified version
of [pinkySim](https://github.com/greggersaurus/pinkySim), which allowed for
simulating the main processor (LPC11U37F) and logging relevant actions.
simulating the main processor (LPC11U37F) and logging relevant actions.
Verification of different behaviors often required running custom firmware
to ensure the proper paths were being simulated.
to ensure the proper paths were being simulated. A separate effort doing static
analysis using [Ghidra](https://github.com/NationalSecurityAgency/ghidra) is
also described.

See [LPC11U37F_Software.md](./LPC11U37F_Software.md) for information regarding
the software running on the LPC11U37 main/master processor.


# TODO

See [TODO](./TODO.md) for details.
Loading