Skip to content

Instantly share code, notes, and snippets.

@dev-zzo
Last active February 9, 2023 00:08
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dev-zzo/88bd6e78dc62e2ed32616c4889151f8a to your computer and use it in GitHub Desktop.
Save dev-zzo/88bd6e78dc62e2ed32616c4889151f8a to your computer and use it in GitHub Desktop.
ChameleonMini fun

Getting it to work

The device is shipped with test firmware installed. To burn a proper firmware, you will need:

The instructions on the blog page are incorrect because Rev G hardware uses ATxmega128A4U instead of ATxmega32A4U. Why? Probably an outdated version of hardware.

Note for Windows users: the dfu-programmer utility is built for 32 bits. Take the correct libusb0.dll otherwise it won't start at all.

Complete log for flashing the device:

$ >dfu-programmer.exe atxmega128a4u get bootloader-version
Bootloader Version: 0x04 (4)

$ >dfu-programmer.exe atxmega128a4u erase
Checking memory from 0x0 to 0x1FFFF...  Not blank at 0x1.
Erasing flash...  Success
Checking memory from 0x0 to 0x1FFFF...  Empty.

$ >dfu-programmer.exe atxmega128a4u flash --eeprom Chameleon-Mini.eep
Checking memory from 0x0 to 0x5F...  Empty.
0%                            100%  Programming 0x60 bytes...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]  Success
0%                            100%  Reading 0x800 bytes...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]  Success
Validating...  Success
0x60 bytes written into 0x800 bytes memory (4.69%).

$ >dfu-programmer.exe atxmega128a4u flash Chameleon-Mini.hex
Checking memory from 0x0 to 0x1FFFF...  Empty.
0%                            100%  Programming 0x20000 bytes...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]  Success
0%                            100%  Reading 0x20000 bytes...
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]  Success
Validating...  Success
0x20000 bytes written into 0x20000 bytes memory (100.00%).

$ >dfu-programmer.exe atxmega128a4u launch

Verify the device enumerates properly via the device manager.

Working with the device

Chameleon presents itself as a USB-based virtual serial port; this ensures there is no need to write additional OS specific drivers. To use the device, simply fire off your favourite terminal program; if you don't have one, then teraterm is recommended on Windows (as putty, while convenient, does not support XModem protocol which is used for a couple of things). On Linux, you may use e.g. socat: socat - /dev/ttyACM0,crnl -- adjust to your system.

The device provides a simple command line interface that exposes all functionality that is implemented in firmware. Everything that can be done goes through that command line.

Two very important concepts are configuration and setting. A configuration is basically which mode the device will operate in: emulating a card, sniffing comms, or maybe acting as a reader. A setting is basically a memory slot which keeps the selected configuration among other things; you can select a setting via command line or (if configured) to cycle through them by pressing RBTN (on rev G hardware).

Identifying MIFARE cards

The simplest thing you can do is to try to identify any cards you currently have. To do that, we'll need to:

  • Select an unused setting, say, setting #2: SETTING=2
  • Configure the device into the reader mode: CONFIG=ISO14443A_READER
  • Use the IDENTIFY command to perform card identification!

Example outputs:

101:OK WITH TEXT
MIFARE Ultralight
ATQA:   4400
UID:    04386FC28B4981
SAK:    00
101:OK WITH TEXT
MIFARE Classic 1k
ATQA:   0400
UID:    9EE3DC29
SAK:    08
101:OK WITH TEXT
Unknown card type.
ATQA:   4400
UID:    049A46F2E13980
SAK:    20

Reading out a MIFARE Ultralight card

Since MIFARE Ultralight cards do not implement any kind of security, we can read them easily.

Put the Chameleon into the reader mode as discussed previously. Now, after you've identified your card to be a MIFARE Ultralight card, use the DUMP_MFU command to read out the contents. Example dumps are shown below.

101:OK WITH TEXT
04386FDBC28B4981814808007F09E816
060A0021000000000000FC6CDD698D7E
1278D45F7DFCFC7253E7FF3C03FCFF0C
FCFCFCFCFCFCFCFCFCFCFC0030AB30B2
101:OK WITH TEXT
046053BFAAF948819A480000230A7016
060A002100000000000028B8696C3C6A
C5B1FFB1A92818289F6028E8D728A9AF
28282828282828282828280027606767

Emulating a MIFARE Ultralight card

First of all, you would need to obtain a dump of the card you'd like to emulate. How you do that is out of scope of this tutorial :-) but a good starting point can be simply reading the card with Chameleon and converting the hex dump into a binary file.

Supposing you have the dump handy:

  • Choose an unused setting slot and select it.
  • Configure the slot to use MIFARE Ultralight: CONFIG=MF_ULTRALIGHT
  • Upload the dump to Chameleon: punch in the UPLOAD command and then proceed to upload via XModem, which your terminal software should provide.
  • Verify things worked by checking the UID of the card via UID? -- it should match.

Note Chameleon does not respond with anything to indicate a successful upload.

Now use Chameleon as you would use your usual tag -- it should work just find. Remember to switch the battery ON if you are going to disconnect it from USB.

Emulating a MIFARE Classic 1k card

The procedure is exactly the same -- obtain a card dump, upload it, test it. The only difference is to use CONFIG=MF_CLASSIC_1K command to configure the device properly.

Using the logging facility

Chameleon is able to write a log of events occurring over the air, which is useful to debug things or simply learn about inner workings of the card.

  • Set up your emulation
  • Enable logging on Chameleon by using the LOGMODE=MEMORY command; it will cause the log to be written to internal memory
  • Perform the operation you're interested in, for example, present Chameleon to the reader
  • Download the log using the LOGDOWNLOAD command; use XModem as usual to get the data out
  • Use the chamlog tool provided with the rest of software bundle to make the log human-readable!

For example, this is the log of a Proxmark3 acting as a reader against a development build of the DESFire emulation code running on Chameleon:

>chamlog.py -f log
64174 ms <+64174 ms>:CODEC RX         (1   bytes) [52]
64174 ms <    +0 ms>:CODEC TX         (2   bytes) [4403]
64175 ms <    +1 ms>:CODEC RX         (2   bytes) [9320]
64175 ms <    +0 ms>:CODEC TX         (5   bytes) [88deadba41]
64176 ms <    +1 ms>:CODEC RX         (9   bytes) [937088deadba41e83b]
64176 ms <    +0 ms>:CODEC TX         (3   bytes) [24d836]
64177 ms <    +1 ms>:CODEC RX         (2   bytes) [9520]
64177 ms <    +0 ms>:CODEC TX         (5   bytes) [be111111af]
64178 ms <    +1 ms>:CODEC RX         (9   bytes) [9570be111111af8a6f]
64178 ms <    +0 ms>:CODEC TX         (3   bytes) [20fc70]
64179 ms <    +1 ms>:CODEC RX         (4   bytes) [e0803173]
64179 ms <    +0 ms>:CODEC TX         (8   bytes) [0675008102006e79]
64246 ms <   +67 ms>:CODEC RX         (1   bytes) [40]
64328 ms <   +82 ms>:CODEC RX         (1   bytes) [43]
64410 ms <   +82 ms>:CODEC RX         (4   bytes) [500057cd]
64410 ms <    +0 ms>:APP HALT         (0   bytes) []

Troubleshooting

I get binary garbage on the terminal

This typically means that the logging mode is set to LIVE; this also breaks most Python tools that come with Chameleon.

Fix: You can turn logging off by issuing the LOGMODE=OFF command, and everything should be fine.

@cons0l3
Copy link

cons0l3 commented Oct 12, 2016

very nice. excellent job.

maybe you could add a passage on commenly made errors e.g. if the terminal shows garbled or unreadable bytes in response to commands, you have to set the LOGMODE=OFF, because it was logging the NFC communication to the terminal (LOGMODE=LIVE). if the provided python tools throw errors on decoding to ascii turn off LOGMODE=LIVE.

maybe also an chapter on the python tools...

@scaery
Copy link

scaery commented Oct 16, 2016

And here`s the classic one for Linux Heads:

socat - /dev/ttyACM0,crnl

version?
config?
config=?
-> http://rawgit.com/emsec/ChameleonMini/master/Doc/Doxygen/html/Page_Configurations.html
config=MF_CLASSIC_1K
uid?
uid=01020304

For everything else just type

help

That will get you the basics on running with the Chameleon Mini.

@dev-zzo
Copy link
Author

dev-zzo commented Oct 28, 2016

@cons0l3 @scaery Thanks, added!

@michpappas
Copy link

The socat command provided above does not work correctly (at least on my system), as it echoes the responses back to the Chameleon, which then interprets them as commands. Example:

# socat - /dev/ttyACM0,crnl
help
101:OK WITH TEXT

VERSION,CONFIG,UID,READONLY,UPLOAD,DOWNLOAD,RESET,UPGRADE,MEMSIZE,UIDSIZE,RBUTTON,RBUTTON_LONG,LBUTTON,LBUTTON_LONG,LEDGREEN,LEDRED,LOGMODE,LOGMEM,LOGDOWNLOAD,LOGSTORE,LOGCLEAR,SETTING,CLEAR,STORE,RECALL,CHARGING,HELP,RSSI,SYSTICK,SEND_RAW,SEND,GETUID,DUMP_MFU,IDENTIFY,TIMEOUT,THRESHOLD,FIELD

200:UNKNOWN COMMAND

Notice the UNKNOWN_COMMAND error. If you strace the above you'll get the following:

# strace -p10219
Process 10219 attached
select(6, [0 5], [], [], NULL)          = 1 (in [0])
recvfrom(3, 0x7ffe22e008c0, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e00340, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
read(0, "help\n", 8192)                 = 5
recvfrom(3, 0x7ffe22e00340, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e00840, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
write(5, "help\r\n", 6)                 = 6
recvfrom(3, 0x7ffe22e00840, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e008c0, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
select(6, [0 5], [5], [], NULL)         = 1 (out [5])
recvfrom(3, 0x7ffe22e008c0, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e008c0, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
select(6, [0 5], [], [], NULL)          = 1 (in [5])
recvfrom(3, 0x7ffe22e008c0, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e00340, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
read(5, "200:UNKNOWN COMMAND\n", 8192)  = 20
recvfrom(3, 0x7ffe22e00340, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
recvfrom(3, 0x7ffe22e00840, 511, 64, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
write(1, "200:UNKNOWN COMMAND\n", 20)   = 20

The following works for me (but I like minicom better):

socat - /dev/ttyACM0,crnl,raw,echo=0

@maxieds
Copy link

maxieds commented Jan 4, 2018

Another Easy Method for Working with the Chameleon Mini Device

There is also now an open-source Android app (ChameleonMiniLiveDebugger) [signed apk from here] available on the Play Store that makes getting started with the device much easier. All it requires is the Chameleon Mini, a Droid phone, and this usb adapter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment