Accidentally solving the Swisscom 2025 security.txt challenge
Background
A while ago, I was mindlessly browsing the Meetup website, looking for some local meetups. I accidentally ended up on a 2024 Swisscom security.txt Challenge Writeup blog post that sounded like fun.
Turns out, this is a yearly thing1:
$ curl -s https://swisscom.ch/.well-known/security.txt | tail -n 2
# Canihazchallenge: aHR0cHM6Ly9naXRodWIuY29tL3N3aXNzY29tL3NlY3VyaXR5dHh0L2Jsb2IvbWFzdGVyL2NoYWxsZW5nZXMvMjAyNS53b3o=
For the base64-challenged, that string leads to 2025.woz file on Swisscom’s github.
My thought was: Hm, I wonder how hard it would be?
Turns out… it was rather pleasant.
I’m going to walk you through some of it here2.
Writeup
First things first, what the hell is a .woz
, right?
$ file 2025.woz
2025.woz: Apple ][ WOZ 2.0 Disk Image, 5.25 inch, ant0inet
Ah, Apple II – the machine I never had, having grown up behind the Iron Curtain.
Still, fun. What happens when you boot it?
I’ll spare you the boring bits3, CATALOG
reveals a few scripts (A
),
two binaries (B
), and a text file (T
):
The target is obviously to run the FLAG
binary, but BRUN FLAG
magically
doesn’t work:
It throws ERROR #8
, which my oft-used stochastic parrotry interprets
as a general Input/Output error4.
So something’s screwed up with the binary.
After a bit of a dig, I ended up with a woz2dsk
script that can convert the unwieldy .woz
format to a more readable5 .dsk
format.
A huge advantage is that you can still boot the .dsk
in the typical emulators.
And from there, it was a bit of figuring out what’s wrong with the file, and how to repair it.
Should you embark on this journey, you might find the following links valuable:
- Apple DOS file system
- 6502 disassembler
- a2tools to dump individual
files from the
.dsk
call -151
to drop into the machine language monitor (aka System Monitor), in case you need to dump/write memory
And how was I going to solve it? Ruby, obviously. All 91 lines of it, including moderately extensive comments and debug out:
#!/usr/bin/env ruby
# ...
require 'pp'
# ...
def human_name(name)
name.map { |x| (x ^ 0x80).chr }.join.strip
end
File.open('a.dsk', 'r+b:ascii-8bit') do |f|
# ...
# patch it?
if human_name(name) == 'FLAG'
# ...
puts %[Patching done, now load it up... then: "brun flag"]
end
# ...
end
# I mean, I said I'm not telling, right?
Overall, it was a fun exercise6 that ended in a rather satisfying:
Even better: a few days later I received a cache of Swisscom SWAG, including the card above and some fun stickers (“PoC or it didn’t happen”, “I hacked Swisscom and all I got was this lousy sticker.”, etc)7.
100% would try again next year – and recommend it to others. ;)
If for nothing else, then for the “surely it can’t be that hard” aspect.
Game on.
-
Who woulda thunk, by the blog post title, right? ↩
-
Not all of it, because in bird culture that’s considered a dick move. ↩
-
That your favorite flavor of stochastic parrotry explains in sufficient detail in under 50 seconds. ↩
-
Reminds me of the old DOS joke: “Who the hell is General I/O error, and why is he reading my disk?” ↩
-
In hex editor, I mean… ↩
-
Took about 3-4 hours (from an Apple II virgin) to get the flag, then probably the same time to make it fully repeatable and put a bow on the Ruby. ↩
-
Thank you,
ant0inet
! ↩