Hack.lu 2015 CTF Write-Up: Secret Library
Books are a great thing. And since libraries are a big amount of books you can read in one place, they’re great, too.
But this secret library some guys started is a bit different. You have to know the exact title of a book to get it, you can’t look around. So you have to know another person in the library who knows some book titles or you won’t be able to read anything. A bit like an invite-only library.
This whole thing seems weird. Could you poke around and try to figure out what they’re up to? If you could grab one of their books, that would be awesome.
connect to school.fluxfingers.net:1527
download
Challenge Overview
To solve this challenge we need to reverse an ELF 64-bit binary. The user can interact with the program by submitting different “magic words” (8-digit hexadecimal numbers), which trigger different actions; for example, the magic word 420B65F7
permits the user to authenticate itself, while F1140B88
prints the content of a book, and so on.
After a bit of reversing, we summarized the logic of the program with the following pseudocode (relevant parts only):
From the code we can see that there is a special user with library card 00278F03
- the head librarian - which is allowed to see the titles of all the books contained in this secret library. As the challenge description suggests, we can’t read the content of any book without knowing its name, and the only way to know the books titles is to authenticate as the head librarian.
Unfortunately, by looking at the disassembled code we found it is not possible to bypass the can_prove_it()
check, since it will require to blindly guess a lot of bytes picked from /dev/urandom
. We must look for different ways to set the library card to 00278F03
and then print the list of book titles.
The “WTF is that doing there” moment
After a lot of time spent on the wrong track, we finally caught a very suspicious syscall in the middle of the following (decompiled) function:
This function is executed for every character of any magic word read by the program; if the character is one of 0123456789ABCDEF
, then it simply returns its decimal value, otherwise -1
.
But, in addition, if the character is one of :;<=>?@
(ascii code greater than 57
and less or equal to 64
), then the function will also execute that strange syscall. Its disassembly is the following:
The syscall apparently sets the byte at 0x603397
to zero. How this can be useful to us? Well, by inspecting a little more the binary we found that the library card is stored at 0x603394
using four bytes; thus, the syscall will overwrite its most significative byte with zero! And, if you remember, the head librarian card starts exactly with the null byte ;)
The solution
We need first to authenticate (using the magic word 420B65F7
) with a library card that is equal to the one of the head librarian except for the most significative byte (e.g. 11278F03
); then, we input the very magic word 1337:123
to simply trigger the syscall that will zero the msb of the previously insterted library card. Finally, since we are now authenticated as the head librarian, we print the books titles (using the magic word 952A7224
):
So, the library has only one book named 16F7F4D391F030CF
. We can read the content of a book with the magic word F1140B88
:
\o/