Showing posts with label reverse-engineering. Show all posts
Showing posts with label reverse-engineering. Show all posts

Sunday, January 26, 2025

2023 Swisscom security.txt Challenge Writeup

For the last couple of years, I've been planting a CTF-like challenge as an easter egg in Swisscom's security.txt file (RFC 9116). The current challenge is here: https://www.swisscom.ch/.well-known/security.txt. All challenges are also archived on Github: https://github.com/swisscom/securitytxt. I thought it was about time to provide the solutions to the past challenges. You can find the writeup for 2022 in my last post. Now let's continue with year 2023. You were given the following string: 

aHR0cHM6Ly9pbWd1ci5jb20vYS9kaFlkUXpq

Experienced blue teamers will quickly recognize the Base64 encoding as well as guess it's a URL, judging from the prefix. The decoded value is indeed a link to the following image on the image sharing platform imgur:

It's a screenshot of Microsoft Minesweeper featuring some bizarre content in the game field. The way the tiles are arranged certainly does not represent an achievable game state. The image also contains an MD5 hash 9C45D38B74634C9DED60BEC640C5C3CA. Using it, we can find references to the winmine.exe binary on VirusTotal or on The Internet Archive. This is the version of minesweeper which was was originally shipped with Windows XP in 2001. You can download the binary and make sure it matches the given MD5 hash:


Ok, so now we need to make some guesses and assumptions. We are eventually looking for a flag, a secret text, to solve the challenge. If we look at the game field, we see that the tiles are arranged on three lines. The different tiles might map to characters that form words. We will first need to understand how the game field and the tiles are represented in memory. It's safe to assume, that we'll be dealing with a 2-dimensional array of elements. However, note that the game allows to customize the dimensions. By default (beginner mode), it's a 9x9 field. In the screenshot, we have 9x21.

To better understand the inner workings of the program, we are going to proceed with a debugger for dynamic analysis. For this, I can highly recommend the open source x64dbg (you'll need to use the 32bit version, though), or if want to hack like it's 2001, you can also use Immunity Debugger or OllyDbg. First, we need identify the memory region of the game field. For this, we are going to exploit a cheat/easteregg, which - fun fact - already existed in previous Windows 3.1 versions of Minesweeper:

Type XYZZY and press [Shift][Enter]. The top left pixel on your screen will become white but turn black when your mouse is above a mine.

This will use the SetPixel() Windows API call provided in GDI32.dll, the Windows Graphics Device Interface. This is likely the only place the application will use this call, since it will rely on other, more abstract API calls to render all of the game elements instead. Run Minesweeper in the debugger, continue execution past the initial/default breakpoints, and apply the cheatcode. In the executable modules, look for the SetPixel symbol, listed as an export in gdi32.dll and set a breakpoint accordingly.



Now, hovering the cursor above a mine will trigger the breakpoint on the SetPixel() call. Going one step down the call stack, we can identify how the arguments are computed in the caller:

  • hDC: is the return value of the previous call to GetDC (this value is irrelevant)
  • X and Y: both originate from EDI, which has value 0. This confirms that we are setting the topmost/lefmost pixel of the screen.
  • Color: will be either 0x00000000 (black) or 0x00ffffff (white), depending on the value of EAX, which is the result of a computation involving a memory value at address 0x01005340.

By inspecting the memory values starting at memory address 0x01005340, we realize that there is a link to the displayed tiles on the game field. By editing the values in memory and some trial and error, we can start to understand the underlying layout. Starting at an offset of 32 bytes (at address 0x01005360), we can manipulate the displayed tiles by changing the bytes values:


After some exploration, we can devise that each row of the game field is stored using 32 bytes. As the game's dimensions can be changed, the actual fields are surrounded by "guard" values (0x10) each as top/bottom rows and left/right columns. The values depicted as XX below represent the actual tiles. The remaining values (0x0F) are just padding.

0x01005340: 0x10 0x10 0x10  0x10 0x10 0x10 0x10 ... 0x10
0x01005360: 0x10 XX XX XX ... XX 0x10 0x0F 0x0F ... 0x0F
0x01005380: 0x10 XX XX XX ... XX 0x10 0x0F 0x0F ... 0x0F
...
0x01005460: 0x10 XX XX XX ... XX 0x10 0x0F 0x0F ... 0x0F
0x01005480: 0x10 0x10 0x10  0x10 0x10 0x10 0x10 ... 0x10

In our case, using dimensions 9x21, the first row spans from memory addresses 0x01005361 to 0x01005375, the second row from 0x01005381 to 0x01005395, and so on, until the last row at addresses 0x01005461 to 0x01005475. By the way: all mentioned addresses will work for you as well, since winmine.exe does not support address space layout randomization (ASLR).

After we located the memory region, we still need to understand the mapping of bytes to tiles. For that, let's write a PyCommand for Immunity Debugger to fill out all possible values in the range 0-255 in memory:


There are two interesting observations:

  1. Even rows have a repeating pattern
  2. Odd rows are blank

From the first observation, we can derive that the different tile faces are represented using the 4 least significant bits. From the second observation, we derive that the 5th bit is a "blank" flag. Next is a mapping of printable ASCII characters to the corresponding tile faces. Due to the "blank" flag, only letters A-O can be recovered, and due to the repeating pattern, the mapping is ambiguous, e.g. the "Bomb with x" is either the + sign, or the letter k/K (fortunately, ASCII was designed such that uppercase and lowercase letters differ only in the 6th bit, which make them map to the same tile).

| Decimal | Binary    | Character | Tile Face       |
|---------|-----------|-----------|-----------------|
| 32      | 0100000   | Space     | Empty           |
| 33      | 0100001   | !         | 1
               |
| 34      | 0100010   | "         | 2               |
| 35      | 0100011   | #         | 3               |
| 36      | 0100100   | $         | 4               |
| 37      | 0100101   | %         | 5               |
| 38      | 0100110   | &         | 6               |
| 39      | 0100111   | '         | 7               |
| 40      | 0101000   | (         | 8              
|
| 41      | 0101001   | )         | Clicked ?       |
| 42      | 0101010   | *         | Black bomb      |
| 43      | 0101011   | +         | Bomb with x     |
| 44      | 0101100   | ,         | Bomb red bg     |
| 45      | 0101101   | -         | Unclicked ?     |
| 46      | 0101110   | .         | Flag            |
| 47      | 0101111   | /         | Unclicked Empty |
| 64      | 1000000   | @         | Empty           |
| 65      | 1000001   | A         | 1
               |
| 66      | 1000010   | B         | 2               |
| 67      | 1000011   | C         | 3               |
| 68      | 1000100   | D         | 4               |
| 69      | 1000101   | E         | 5               |
| 70      | 1000110   | F         | 6               |
| 71      | 1000111   | G         | 7               |
| 72      | 1001000   | H         | 8               |
| 73      | 1001001   | I         | Clicked ?       |
| 74      | 1001010   | J         | Black bomb      |
| 75      | 1001011   | K         | Bomb with x     |
| 76      | 1001100   | L         | Bomb red bg    
|
| 77      | 1001101   | M         | Unclicked ?     |
| 78      | 1001110   | N         | Flag            |
| 79      | 1001111   | O         | Unclicked Empty |
| 96      | 1100000   | `         | Empty           |
| 97      | 1100001   | a         | 1               |
| 98      | 1100010   | b         | 2               |
| 99      | 1100011   | c         | 3               |
| 100     | 1100100   | d         | 4               |
| 101     | 1100101   | e         | 5               |
| 102     | 1100110   | f         | 6               |
| 103     | 1100111   | g         | 7               |
| 104     | 1101000   | h         | 8               |
| 105     | 1101001   | i         | Clicked ?       |
| 106     | 1101010   | j         | Black bomb      |
| 107     | 1101011   | k         | Bomb with x     |
| 108     | 1101100   | l         | Bomb red bg     |
| 109     | 1101101   | m         | Unclicked ?     |
| 110     | 1101110   | n         | Flag            |
| 111     | 1101111   | o         | Unclicked Empty | |---------|-----------|-----------|-----------------|

Using this mapping, we can recover parts of the text. Every _ is then either a space, @, a backtick (`) or one of the letters P-Z:

GOOD_JOB!
_END_EMAIL__O
_ED._ILL___I__COM.COM

The first 10 people who wrote a message to the e-mail address received some Swisscom swag as a reward. Note: the e-mail address was chosen as a reference to the 1999 hacker/cyberpunk movie The Matrix, following the nomenclature of the meeting rooms in the Swisscom Cyber Defence offices. Any other references are explicitly excluded.

I hope you enjoyed solving this challenge. I got my inspiration for it after viewing the following video by jeFF0Falltrades: Reverse Engineering and Weaponizing XP Solitaire (Mini-Course).

Finally, here are some additional links and resources about Minesweeper you might enjoy:

Saturday, February 1, 2014

Experimenting with Software Defined Radio

In this blog post, I will describe my first project experimenting with a software defined radio (SDR). For those of you new to this technology, think of it as an RF frontend to your computer, which performs most signal processing from digitized radio waves in software. Hence, virtually any radio communication system can be implemented given capable software. There is already a plethora of projects for a variety of RF applications related to industry or consumer standards. The CGRAN maintains a list of projects, have a look at it to get an idea of what's all possible.

The test hardware

So, to become acquainted with the SDR, I chose to analyze this simple RF controlled power switch system I found at my local supermarket. The package contains three radio controlled connectors with a pass through socket for the electrical appliance. The remote control individually switches the connectors on and off by pressing on the corresponding buttons. When switching a controller on and off, the clicking sound of a relay is clearly audible.
Power Switch System 1204380 3M from Steffen AG

Anatomy of the controller

The remote and the connectors are both configured via dip switches inside the enclosure. The address scheme comprises a 5 bit system code (positions 1 to 5 in the pictures below), commonly used by all devices. Also, a unit code (positions A-E) is assigned to each of the connectors to individually address them. Interestingly enough, position E is not provided on the remote, instead, there is a master on/off switch that addresses all units at once.
Dip switches for the selection of the system code (common to all devices)
and the unit code (individual to each connector)
On the back of the remote control, the model number and most interestingly, the operating frequency 433.92MHz are engraved on the enclosure. Within the enclosure, a PCB with a single IC labeled AZ08C20, P50 0322D. Unfortunately, I couldn't find any specification for this chip that would ease the task of analyzing the control signal. There are specifications publicly available for similar ICs that helped me grasp the encoding principle: for example Princeton Technologies PT2262 and PT2272, and Holtek HT12A and HT12E.
 
The remote control's IC:
AZ08C20 P50 0322D

Visualizing the signal

For this, I designed a GNURadio flowgraph. The source block provides the data from the SDR. Use either a UHD source for USRP devices from Ettus Research or else a OsmoSDR source for USB DVB-T dongles, BladeRF or HackRF. The data provided by the source is a stream of complex I/Q values, represented by pairs of 32bit floats. If you're not familiar with I/Q data, here are two excellent write-ups to learn about this data format and why it's used for SDRs. After reading this, you'll understand how the Complex to Mag^2 block is used to convert the complex I/Q samples into a real, scalar magnitude sample. The Threshold block is used to distinguish between HIGH and LOW states of the signal. Both real and discrete signals are input to the Scope Sink for the visusalization. The Wav File Sink is used to create a .wav file which can then be analyzed using common audio processing software such as Audacity.
GNURadio flowgraph used to visualize the signal

In the scope visusalization, we can see that the amplitude of the carrier frequency is modulated to form pulses of varying widths. This modulation scheme is called (binary) amplitude shift keying (ASK) or also sometimes On-Off-Keying (OOK). The encoding is a discretization of pulse width modulation (PWM), where pulses of different widths represent different information symbols. I determined the duration of the short (unit) pulse to be 533µs by measuring the number of samples across its width. The long pulse is twice as long: 2*533µs = 1.066ms. The blank between each pulse is of same duration as the unit. Effectively, each pulse starts after a period of 3*533µs = 1.6ms. Messages are continually sent in bursts of 25 pulse periods with a pause of 3.2ms inbetween, for a total of 128ms per message.

Replaying the signal (security implications)

Having recorded the signal as .wav file or as raw data, the flowgraph can be reversed to replay the messages. Choose the Wav File Source and connect it to your SDR sink (either UHD Sink or OsmoSDR Sink). This already suffices to trigger the switch. This indicates that there is no security whatsoever to protect the connectors from receiving messages not originating from the remote control. Also note that the number of possible different addresses (given by the combination of dip switch positions) is very low, 2^5 = 32, hence an attacker can very rapidly guess it by running through all possibilities.

Reverse-engineering

Assigning a short pulse to 0 and a long pulse to 1, I wrote down the different code patterns while pressing each button and systematically changing the dip switch positions. I could not identify every bit's meaning in these patterns, but I retrieved enough information to synthesize message which would actually trigger the switch. Here are some examples having all dip switches for the system code on HIGH:

                         DIPSW ????? ?????? B ?? EDCBA  ?
A         OFF            11111 00011 100101 0 00 00001 0
B         ON             11111 00011 100111 1 00 00010 0
B         OFF            11111 00011 101000 0 00 00010 0
C         ON             11111 00011 101001 1 00 00100 0
C         OFF            11111 00011 101010 0 00 00100 0
D         ON             11111 00011 101100 1 00 01000 0
D         OFF            11111 00011 101100 0 00 01000 0
Master    ON             11111 00011 101101 1 00 00000 0
Master    OFF            11111 00011 101110 0 00 00000 0


So obviously, the dip switches are reflected by the 5 first bits in the message. The 17th bit always correlates with the on (1) and off (0) button. Finally, bits 20-24 reflect the unit code. Concerning the remaining bits, I suspect bits 11-16 to be a counter and the rest to be padding.

Synthesizing the signal

After gathering all this information about the signal and the encoding, I decided to write a small GNURadio application with python to replicate the remote control in software by emitting the signal from the SDR. You can access the code here on github. The basic idea behind the modulator is to process the incoming stream of bits and converting them into I/Q samples. In order to describe the pulse train, I defined a intermediate 2-bit mapping according to following diagram, which will help you understand the code:
Intermediate 2-bit encoding of the pulse-widths

Using this mapping, a logical 0 is encoded with 01, a logical 1 is encoded with 10 and the pause between each burst is encoded with 00. Note that code 11 is never used. The GUI is designed to resemble the remote control's interface:
Application replicating
the remote control. Uses the
GNURadio framework

 That's it, I hope you enjoyed reading this. If you did, don't miss the flattr button ;-)

Monday, August 13, 2012

vortex6

The goal of vortex level 6 is to reverse engineer a binary executable to exploit it. I used objdump to decompile the code section. Check out the solution on github: https://github.com/antoinet/vortex/tree/master/vortex06