RETracker
RETracker
is a reverse engineering framework for the Polyend Tracker written in Python.
It is based on unofficial patches that it applies to the vendor’s stock firmware.
These patches replace the Tracker’s MTP file transfer functionality (disabled by Polyend with the introduction of firmware v1.4.0) with a custom USB HID handler.
The RETracker's
custom USB handler introduces new, non-official features to the Polyend Tracker
that can be controlled from a computer via USB.
The RETracker
firmware’s basic features comprise the following:
- Reading/dumping of memory
- Writing/patching of memory
- Execution of custom code/redirection of control flow
- Writing files to the tracker’s SD card
These features are a solid base for adding further functions to the Polyend Tracker
during run-time, by assembling position-independend code on the host, transferring it to the Tracker and having the new USB handler execute the freshly implanted code. There are a number of features available already that can be transferred dynamically to the device.
Make sure to check them out and/or add your own!
Adding to that, the memory reading/writing functions allow the USB host to inspect the Tracker's
memory by creating hex-dumps or by disassembling code in ARM or Thumb mode.
Finally, the file transfer function (currently the only direction implemented is from the USB host to the Tracker's
SD card) allows new firmware files or NES
roms to be copied to the Tracker, without having to go through the intended process of swapping the SD card between the Tracker
and your computer.
HAPPY HACKING!
Installation
First of all, RETracker requires a number of dependencies to be installed.
Please check them out and make sure you have them all installed before you go on.
Once all dependencies are installed, a patched firmware can be created by running build_fw.py.
# python build_fw.py
usage: build_fw.py [-h] infile outfile
build_fw.py: error: the following arguments are required: infile, outfile
Example:
# python build_fw.py PolyendTracker_1.5.0.ptf PolyendTracker_RETracker.ptf
MD5: ce894299bc35996186528364951c901e
Found 1 patch
Assembling patch #1
Description: "Memory dumping/patching/code execution/file transfer via USB"
Reading input file
Applying patch
Creating output file
Done
Once a RETracker
firmware is successfully built, it should be copied to the Tracker's
"/firmware/"
folder on the root of its SD card.
The firmware flashing procedure is straight forward and doesn’t differ from the ordinary process.
On the device
- press the
config
button - go to the
Firmware
menu - enter the
Firmware update
sub menu - choose the firmware you would like to flash onto the
Polyend Tracker
If the newly created firmware does not show up on the device, there may be a naming scheme for the firmware that must be followed (must start with PolyendTracker_
and end with .ptf
?).
If that is the case, renaming the file on your computer may help.
You’re welcome! ?
ACHTUNG!!! It is normal for the UI to behave differently during the update process when flashing a patched firmware.
Please patiently wait for the update to finish until the device reboots.
In case something still went wrong, please consult the Polyend Tracker
user manual, which explains the steps on how to enter the emergency update procedure
.
Supported Firmware Versions
RETracker currently supports Polyend Tracker
in firmware version 1.5.0, which is the most recent firmware as of this writing.
How does it work?
Polyend Tracker firmware images ship in intel hex format.
The build_fw.py tool converts the firmware to its plain binary format, which holds all the firmware’s code and data.
It then applies patches to the converted binary according to information found in tracker/firmware.py before converting the file back to intel-hex format again.
From there on, the Polyend Tracker
can be communicated with by plugging it into a USB port of a computer running retracker.py.
RETracker Usage
The main workhorse of this project probably is retracker.py
, which provides a command line interface to the user.
# python retracker.py -h
usage: retracker.py [-h]
[-r ADDRESS SIZE FILE | -w ADDRESS DATA | -x ADDRESS SIZE | -d ADDRESS SIZE | -a POLYP | -e ADDRESS | -t SRC_FILENAME DST_FILENAME]
optional arguments:
-h, --help show this help message and exit
-r ADDRESS SIZE FILE, --readmem ADDRESS SIZE FILE
Save memory to local file. Example: retracker.py -r 70100000 4f0 dump.bin
-w ADDRESS DATA, --writemem ADDRESS DATA
Write memory. Example: retracker.py -w 70100000 4141ACAB4141
-x ADDRESS SIZE, --hexdump ADDRESS SIZE
Create hex-dump of memory. Example: retracker.py -x 0 ffff
-d ADDRESS SIZE, --disassemble ADDRESS SIZE
Disassemble code at ADDRESS (ARM/Thumb aware). Example: retracker.py -d 3c01 c000
-a POLYP, --assemble POLYP
Load POLYP patchfile Example: retracker.py -a polyp.flashscreen
-e ADDRESS, --exec ADDRESS
Execute code at ADDRESS (ARM/Thumb aware). Example: retracker.py -e 70100001
-t SRC_FILENAME DST_FILENAME, --transfer SRC_FILENAME DST_FILENAME
Transfer SRC_FILENAME to Tracker's DST_FILENAME. Example: retracker.py -t
PolyendTracker_1.5.0.ptf Firmware/PolyendTracker_cstm.ptf
Examples:
# python retracker.py -d 0002B99d 100
Connected to Polyend Tracker
Detected fw patch v0.3.0 on Tracker firmware v1.5.0
Disassembling 0002B99C-0002BA9C in Thumb mode
0x0002B99C: push {r4}
0x0002B99E: ldr r4, [pc, #0x6c]
0x0002B9A0: umull ip, r4, r4, r1
0x0002B9A4: lsrs r4, r4, #3
0x0002B9A6: add.w r1, r1, r4, lsl #2
0x0002B9AA: uxtb r1, r1
0x0002B9AC: cmp r3, #0x1f
0x0002B9AE: ite ls
0x0002B9B0: addls r4, r0, r3
0x0002B9B2: addhi.w r4, r0, #0x1f
0x0002B9B6: adds r3, r0, r1
0x0002B9B8: ldrb r4, [r4, #5]
0x0002B9BA: strb.w r4, [r3, #0xc8]
0x0002B9BE: cbz r2, #0x2b9e4
0x0002B9C0: add.w r2, r0, r1, lsr #3
# python retracker.py -x 0002B99d 100
Connected to Polyend Tracker
Detected fw patch v0.3.0 on Tracker firmware v1.5.0
Dumping 0002B99D-0002BA9D
0002b99d b4 1b 4c a4 fb 01 c4 e4 08 01 eb 84 01 c9 b2 1f |..L.............|
0002b9ad 2b 94 bf c4 18 00 f1 1f 04 43 18 64 79 83 f8 c8 |+........C.dy...|
0002b9bd 40 8a b1 00 eb d1 02 01 23 92 f8 b6 40 01 f0 07 |@.......#...@...|
0002b9cd 01 03 fa 01 f1 21 43 82 f8 b6 10 01 23 5d f8 04 |.....!C.....#]..|
0002b9dd 4b 80 f8 b5 30 70 47 00 eb d1 04 01 22 94 f8 b6 |K...0pG....."...|
0002b9ed 30 01 f0 07 01 02 fa 01 f1 23 ea 01 01 84 f8 b6 |0........#......|
0002b9fd 10 01 23 5d f8 04 4b 80 f8 b5 30 70 47 00 bf ab |..#]..K...0pG...|
0002ba0d aa aa aa 00 eb 01 0c 8c f8 c8 30 82 b1 00 eb d1 |..........0.....|
0002ba1d 02 01 23 92 f8 b6 c0 01 f0 07 01 03 fa 01 f1 41 |..#............A|
0002ba2d ea 0c 01 01 23 82 f8 b6 10 80 f8 b5 30 70 47 00 |....#.......0pG.|
0002ba3d eb d1 0c 01 22 9c f8 b6 30 01 f0 07 01 02 fa 01 |...."...0.......|
0002ba4d f1 23 ea 01 01 01 23 8c f8 b6 10 80 f8 b5 30 70 |.#....#.......0p|
0002ba5d 47 00 bf 0f 49 00 23 30 b5 01 f1 3f 05 1c 46 4f |G...I.#0...?..FO|
0002ba6d f0 01 0e 01 e0 11 f8 01 3f c2 18 00 eb d3 0c 82 |........?.......|
0002ba7d f8 c8 40 9c f8 b6 20 03 f0 07 03 0e fa 03 f3 22 |..@... ........"|
0002ba8d ea 03 03 a9 42 8c f8 b6 30 ec d1 80 f8 b5 e0 30 |....B...0......0|
Whereas some of the more common command line options allow memory to be written, read and hex-dumped, the more exciting features are probably the -e
and -a
options.
They allow code to be executed on the device.
The -e
option allows code to be branched to directly, for example after having written code/data to the device’s memory using the -w
option.
The lowest bit of an address
argument passed to the retracker.py
command line utility specifies whether or not to use Thumb mode (0: ARM mode, 1: Thumb mode).
The -a
command line argument accepts so called Polyps
, which are Python modules containing patches for the Polyend Tracker
in the form of assembly routines and version-specific offsets and data.
Loading any of these modules using the -a
command line option causes their assembly routines
- to be assembled on the fly
- transferred to the connected device
- executed on the connected device
Example:
# python retracker.py -a polyp.scroller
Connected to Polyend Tracker
Detected fw patch v0.3.0 on Tracker firmware v1.5.0
Assembling patch #1
Description: "Text scroller on the Tracker's pads"
Target address: 70100000
Mode: thumb
Patching memory
Running code...
Done
This does not only allow for convenient and sped-up development of custom code and features, it also does not require new firmware to be flashed onto the Tracker
for new code to be tested (but a reboot in the worst case).
Please have a look at the available modules in the polyp/ folder, which contains a few initial demos that fade the Tracker's
screen in and out or repurpose its pads as a text-scroller canvas.
Reverse Engineering the Tracker
The Polyend Tracker
is believed to be based on a µc similar to the Teensy 3.6 of which data sheets and other tech info is available here.
Be sure to check out the MK66FX manual for a memory map in order to avoid running into device crashes when dumping memory.
The Tracker
firmware image is in intel-hex format and can be loaded directly by the IDA Pro disassembler and probably others such as GHIDRA or Binary Ninja using an ARM processor module in little-endian mode.
The firmware can be mapped to base address 0, with address 4 being a pointer to the reset vector (start disassembling there).
Most, if not all of its code runs in Thumb mode.
I’ve found address 0x70100000
and above to be a reliable address to plant a Polyp
into and run its code from there.
Disclaimer
The author does not take any responsibility for any damage this project may cause to your Polyend Tracker.
By using RETracker or any information derived, you agree that you are using any of this project’s code, data and other information at your own risk.