Saturday, January 17, 2026

2025 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 2024, 2023, and 2022 in posts tagged with securitytxt. Now let's continue with year 2025. You were given a base64-encoded URL leading to file 2025.woz. After downloading, let's try to identify it:

$ file 2025.woz
2025.woz: Apple ][ WOZ 2.0 Disk Image, 5.25 inch, ant0inet

It seems we're looking at a 5.25 inch floppy disk image for the Apple ][ computer, citing Wikipedia:

The Apple II (stylized as apple ][) is a personal computer released by Apple Inc. in June 1977. It was one of the first successful mass-produced microcomputer products and is widely regarded as one of the most important personal computers of all time due to its role in popularizing home computing and influencing later software development.

The Apple II was designed primarily by Steve Wozniak. The system is based around the 8-bit MOS Technology 6502 microprocessor.
  
The Apple II at first used data cassette storage, like most other microcomputers of the time. In 1978, the company introduced an external 5 1⁄4 inch floppy disk drive, called Disk II (stylized as Disk ][), attached through a controller card that plugs into one of the computer's expansion slots (usually slot 6). The Disk II interface, created by Wozniak, is regarded as an engineering masterpiece for its economy of electronic components.

Now, let's talk about the WOZ disk image file format, obviously named after Steve "The Woz" Wozniak. The format was created aside the Applesauce project, which provides hardware and software components for the digital preservation of floppy disks. The WOZ format was designed to preserve the physical aspects and to recreate an accurate image of a disk's structure and layout. It does this by capturing the magnetic flux signals off the read head. So instead of storing logical bits, the format stores digitized samples of analog signal levels. As an analogy, think of storing text as a recording of a morse code transmission in a WAV file instead of using ASCII. By doing this, it is possible to reproduce the quirks on the physical level that were exploited for copy protection. The WOZ format specification is publicly available and implemented in many Apple ][ emulators.

Applesauce Flux Image (source: archive.org)

 

Let's use MAME (multi-purpose emulation framwork) to emulate an Apple ][ and boot from the disk image. I love that the authors went so far as to emulate the Disk ]['s stepper motor sounds. You'll need the copyrighted ROM images to run the MAME Apple driver, or a public domain replacement. Let's choose the Apple //e model from 1983, since it supports more memory:

PS C:\> .\mame.exe apple2e -flop1 .\2025.woz -window 

Using AppleCommander to analyze the logical layout, we can observe that it's a DOS 3.3 bootable disk containing a set of Applesoft BASIC programs in tokenized format (A), a plain text file stored in ASCII format (T), and two machine language programs (B). You can go ahead and run or open the files, they will contain some (hopefully) fun references and useful hints to solve the challenge. Obviously, the file named FLAG will be of interest. However, running it will result in ERROR #8, which according to the Apple II DOS Manual (page 200) refers to an "I/O Error".

Let's have a quick look at the organization of a DOS 3.3 formatted disk. Each side of a diskette is divided in 35 concentric tracks, numbered from 0 to 34 (0x22). Each track is then divided in 16 sectors of 256 bytes. Therefore one diskette side has a total capacity of 35 * 16 * 256 = 143'360 bytes. However, 64 sectors (16 KB) are reserved for the system: the DOS code (boot sector and DOS routines, up to 48 sectors), the VTOC (volume table of contents, 1 sector), and the Catalog sectors (15 sectors).

The VTOC is anchored in the middle of the disk at track 17 / sector 0. It refers to the Catalog sectors (track 17 / sectors 1 - 15), which contain information about files, for example their name, attributes and a reference to the TS list sector. Finally, the TS list sector stores an ordered list of track/sector pairs allocated to the file, which contain the actual data.

Here's the breakdown for file "FLAG":

  • Catalog sector (track 17 / sector 15), offset 0x74: catalog entry for file FLAG
  • TS list (track 3 / sector 9): list of track/sectors allocated to file FLAG (81 sectors)
  • track 3 / sector 10 through track  8 / sector 10: file data

Using a disk utility such as Copy II Plus shows that something's wrong with the first sector of file FLAG, and there's no way to read/write the sector data!

Ok, so we need to dig deeper. I'll try my best to describe the underlying physical encoding and the corresponding mapping in the WOZ format, though I highly recommend Beneath Apple DOS for better understanding. At this level, data is stored as a continuous stream of analog signals. In the context of magnetic storage, state changes can be detected from a flux transition, i.e. a change of magnetic polarity on the disk surface. The disk drive's head generates a voltage pulse whenever passing over a transition.

So far we can represent zeros and ones. But when we start to group bits into bytes, or want to organize data into larger structures we are facing two main issues:

  1. Similar to placing the needle on the track of a vinyl record, we have no clue where the bit stream actually starts as soon as the read head is positioned over a track. We can't even locate the 8-bit byte boundaries, let alone the start of each sector on that track.
  2. We cannot rely on precise timings (e.g. due to varying spin rate), therefore a continuous synchronisation is needed to prevent losing the timing reference. The drive needs regular flux transitions, otherwise reading long strings of 0s or 1s will result in unreliable data transmission.

 To address the second point, Wozniak devised the following encoding rules for Disk ][:

  1. No more than two consecutive zero bits
  2. Every byte must start with a 1 bit

These rules mean that out of all possible 256 values only specific byte values are valid for writing to disk, which resulted in the 5-and-3 (DOS 3.2 and earlier) and 6-and-2 (DOS 3.3) GCR encoding. In the latter encoding, 3 bytes of user data (24 bits) are encoded in 4 bytes on disk (32 bits), resulting in a ratio of 3:4 (75% efficiency). Out of the set of "legal" bytes, 0xAA and 0xD5 were chosen as reserved values.

Since the reserved values would not occur in user data, there were used to mark the beginning of sectors. This means that at the moment the read head starts reading the bit stream from a new track, it waits until the special marker byte sequence [0xD5, 0xAA, 0x96] passes underneath.

Now, as described in this excellent article on Apple II Copy Protection, which was provided as hint, one could have chosen other reserved bytes to mark the beginning of a sector:

The easiest way to defeat a simple disk copy program is to alter the sector data in some way that’s consistent, but different from the standard.

Magic Bytes: Who says D5 AA 96 must mark the start of a sector? A copy protected disk might use D5 D5 96, or some other sequence that works just as well, assuming you’re looking for it. But a simple disk copy program will only be looking for D5 AA 96, so it will never find the start of those sectors. It will appear as if the disk is empty.

Let's investigate the data of track 3 by looking at the raw bit stream in the WOZ file and see if we can identify any sector markers. For this, I created a WOZ binary template for the 010 Editor, which parses its data structure.


The bit stream of track 3 is stored from offset 0x5400 to 0x6E00. When looking for sector markers, we expect to find 16 matching values of [0xD5, 0xAA, 0x96] in that range (16 sectors per track), but instead we only find 4 of them. The reason is that the bit stream is not aligned on a byte boundary. Therefore, let's look for occurences of bit-shifted versions of the sector marker:

  • D5 AA 96 (shift 0): 4 occurences
  • 6A D5 4B (shift 1): 0 occurences 
  • 35 6A A5 (shift 2): 4 occurences
  • 9A B5 52 (shift 3): 0 occurences
  • CD 5A A9 (shift 4): 3 occurences
  • E6 AD 54 (shift 5): 0 occurences
  • F3 56 AA (shift 6): 4 occurences
  • F9 AB 55 (shift 7): 0 occurences 

This only results in 15 sector markers, the missing one expected to be shifted by 4 bits. Now let's search for the modified sector marker [0xD5, 0xD5, 0x96], but also shifted by 4 bits: [0x5D, 0x59, 0x6F]. It occurs only once in the entire file at offset 0x6362. You will need to patch the file at that position with value [0x5A, 0xA9, 0x6F].

According to the WOZ format specification, the CRC32 value at offset 0x08 is optional, and can be set to 0. However, MAME will not run without the correct CRC32 value. To compute the value, use the checksum tool built in 010 editor. Otherwise, wozardry will also recompute the CRC32 anytime you edit the file (e.g. adding metadata).


 Now save the file, launch MAME again and BRUN the FLAG:


The first 10 people who wrote a message to the e-mail address with the solution 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.

No comments:

Post a Comment