Hacklu Qual 2015: Secret Library

 October 27, 2015   TalkyBird

Secret Library

by TheJH (Reversing)

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

You can download the challenge’s binary file here.

The main logic

The target is a 64-bit ELF file. Since its logic is quite simple I won’t explain in details the assembly code. Here’s the pseudo code of the main communication:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
special_input = 0;              // stored at 0x603394
char input_buffer[9];
char file_name[9];

while (true) {
    input = read_user_input();  // Read user input into input_buffer and
                                // return the number represented by input_buffer as hex string
                                // Only '0'-'9', 'A'-'F' are accepted.
    switch (input) {
    case 0x952A7224:
        if (special_input == 0x278F03): {
            display("sure! the head librarian ...\n");
            display_current_dir();          // Display content of current directory
        }
        break;
    case 0xF1140B88:
        display("you want me to show you a book?....\n");
        file_name[0] = 0;
        for (int i = 0; i < 2; i++) {
            if (read_user_input() & 1)
                strcat(file_name, input_buffer);
            else: {
                display("pah! we don't have books ....\n");
                break;
            }
        }
        display_file_content(file_name);
        break;
    case 0xF39ED0C:
        convert_bin_to_hex();
        break;
    case 0x420B65F7:
        display("alright, show me your library card.\n");
        special_input = read_user_input();
        if (special_input == 0x278F03) {
            display("oh, you say you're the head librarian? prove it!\n");
            // Here's is the guessing game
            // we have 10 tries to guess the random number from "/dev/urandom"
            if (failed_to_guess)
                special_input = 0;
        }
        display("alright!\n");
    }
}

So here are the steps we should follow to get the flag:

  • Enter “420B65F7”, the program responses: “alright, show me your library card.
  • Enter “00278F03”, the program responses: “oh, you say you’re the head librarian? prove it!
  • Playing the guessing game and win the game to ensure that special_input == 0x278F03
  • Enter “952A7224”, then the program will tell us the content of the current directory and of course the name of the flag file which contains hopefully only hex characters.
  • Enter “F1140B88”, the program response: “you want me to show you a book? …”, then we enter the flag file name twice as hex string, then we have a flag.

But how can we win the guessing game? Well I may say it’s impossible!

rt_sigprocmask

The trick here is the function at 0x400AF6 that converts an 8-bit hex character into the number it represents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int hex_char_to_number(char ch) {
    if (ch < '0')
        return -1;
    if (ch <= '9')
        return (ch - '0');  // '0' -> '9'
    if (ch < 'A') {
        // Tricky
        //ch = [0x3A - 0x40]
        rt_sigprocmask(SIG_BLOCK, NULL, (sigset_t*)0x603397, sizeof(sigset_t));
    } else if (ch <= 'F')
        return (ch - 'A' + 10); // 'A' -> 'F'
    else
        return -1;
}

If we enter any character in range from 0x3A (‘:’) to 0x40 (‘@’) the program will call rt_sigprocmask to return the current blocked signals to offset 0x603397. Since there is usually no blocked signal, the 8 bytes starting at 0x603397 will be zero-filled.

The interesting part is the special_input variable which is stored at 0x603394. Since this ELF is little-endian, the rt_sigprocmask call will overwrite the most significant byte of special_input and set it to zero.

Solution

So here’s how we should enter to get the flag:

  • Enter “420B65F7”, the program responses: “alright, show me your library card.”.
  • Enter “XY278F03”, where XY could be any two hex characters (‘0’-‘F’,’A’-‘9’) except “00”. The program responses: “alright!” and set the value of special_input to XY278F03.
  • Enter a string that contains at least one character in range 0x3A-0x40 to trigger the rt_sigprocmask. The most significant byte of special_input will be set to zero. This means that secial_input == 0x00278F03
  • Enter “952A7224”, then the program will show us the name of the flag file.
  • Enter “F1140B88”, then enter two hex strings representing the name of the flag file to get the flag.

Here’s our example input while connecting to school.fluxfingers.net:1527:

And we have the following responses from server:

hi! this is the secret library. if you want me to speak to you, you need to know the magic words.
alright, show me your library card.
alright!
warning: invalid hexchar '@'
you do know the magic words, right?
sure! the head librarian is allowed to know about all the books!
------------
16F7F4D391F030CF
------------

Then we know the flag file name is “16F7F4D391F030CF”. We connect to school.fluxfingers.net:1527 again and enter the following sequences:

  • F1140B88
  • 16F7F4D3
  • 91F030CF

Here’s how the server responses:

hi! this is the secret library. if you want me to speak to you, you need to know the magic words.
you want me to show you a book? certainly! just tell me the name of the book.
oh, yes, we have that! here you go...
flag{our_secret_is_that_we_really_just_have_this_one_book}

====================

So the flag is flag{our_secret_is_that_we_really_just_have_this_one_book}

HackTheVote Qual 2016: Trump Trump
HackTheVote Qual 2016: Trump Trump  07/11/2016  TalkyBird
HackTheVote Qual 2016: The Best RSA
HackTheVote Qual 2016: The Best RSA  07/11/2016  TalkyBird
EKOPARTY Qual 2016: The Fake Satoshi
EKOPARTY Qual 2016: The Fake Satoshi  01/11/2016  TalkyBird