November 13, 2020

Reverse Engineering & Cracking – Part II

Reverse Engineering & Cracking – Part II

In the first part we looked at how we can change instructions, values etc. with the help of GDB at program runtime. Now we will have a look how we can save our changes, so that we can find our changes at the next program start. So we don’t have to patch our program every time we start it.

Docker preparation

This time I created a Docker Container and work directly with an ELF (Executable and Linkable Format). Additionally I install some practical tools directly. Here is my Docker File:

FROM ubuntu:20.10

ADD .gdbinit .

RUN  apt update && \
     apt upgrade -y && \
     apt install file python3 strace ltrace binutils gdb build-essential checksec vim -y

You can create the container with the following command. (Please make sure that Dockerfile is located in the same directory)

  • docker build -t investigate .

Preparation Code

I adapted the C – code from the first part for Linux (focus line 7 – on linux “u_int_t“):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int getRandomNumber() {
    return (u_int8_t) ((rand() % 25) + 65);
}

int main(int argc, char *argv[]) {

    if(argc != 2) {
        return EXIT_FAILURE;
    }
    

    time_t t;
    srand((unsigned) time(&t));

    printf("Check if license key is valid \n");
    char *license_arg = malloc(sizeof(char) * 4);
    strncpy(license_arg, argv[1], 4);

    char *random_license = malloc(sizeof(char) * 4);

    for(int i = 0; i < 4; i++) {
        char random_char = (char) getRandomNumber();
        strcat(random_license, &random_char);
    }

    int res = strcmp(random_license, license_arg);

    if (res == 0) {
        printf("license accepted \n");
    } else {
        printf("wrong license \n");
    }

    return EXIT_SUCCESS;
}

Starting the Container

Now we start our Docker Container and mount our current directory into the container under “/temp”. For this we use the following command:

  • docker run -it –rm -v ${PWD}:/temp investigate:latest /bin/bash

Program patching

First we have to compile our program. We do this with the help of GCC:

  • gcc elf_license.c -o elf_license -Wall

Then we start gdb with our program.It is important to start GDB with the parameter “–write” to modify our binary.

  • gdb –write elf_license

With the help of “disass main” we can display the disassembled main function. We remember from part I that the interesting part was the following (if your commands are displayed in AT&T syntax “mov %rsp,%rbp” then you can simply change gdb to Intel syntax with “set disassembly-flavor intel“. More about this syntax thing here)

Now we want to rewrite the cmp instruction at adress “0x000000000000001365” which is not compared with 0x0 but against 0x1. So no matter which license we specify, it will always be accepted.

  • Original: 0x0000000000001365 <+213>: cmp DWORD PTR [rbp-0x24],0x0 => Value in HEX[ 0x837dcc00]
  • Target: 0x0000000000001365 <+213>: cmp DWORD PTR [rbp-0x24],0x1 => Value in HEX[ 0x837dcc01 ]

With the following command we set a new value at the target address:

  • set *(char*) 0x0000000000001365 = 0x837dcc01

Then we close the GDB session directly with “q” and test our patch! This step is very important! .

Let’s test the result:

We have successfully changed our binary!!. I hope you had fun as always.

Leave a Reply

Your email address will not be published. Required fields are marked *