Binary Cracking and Byte Patching With IDA Pro

This rare dissertation is committed to demonstrating the cracking and byte patching of a binary executable using IDA Pro to subvert various security constraints, as well as generating or producing the latest modified version (patched) of that specific binary. IDA Pro is typically utilized to analyze the disassembled code of a binary so that the internal mechanism can be comprehended and identify the inherent vulnerability in the source code.

This article has the following contents

  • Binary Sample
  • Patching Configuration in IDA Pro
  • Binary Analysis
  • Binary Cracking and Patching with IDA Pro
  • Script Patching Substitute
  • Final Note

IDA Pro appears to have managed mystical potentials in the reverse engineer's minds by having the impression that merely opening a binary with IDA will reveal all the secrets of a target file. IDA Pro is intended to assist you in consideration of the behavior of a binary by offering us disassembled code. IDA Pro is not designed to modify or patch the binary code to suit your needs like other tools such as OllyDbg and CFF Explorer. It is only a static-analysis disassembler tool. It can only facilitate your attempts to locate software vulnerabilities, bugs, and loopholes that are typically used by both White Hat and Black Hat professionals. Ultimately, it is up to your skills and how you apply them as to whether IDA makes your search for vulnerabilities easier. Essential This tutorial requires a thorough knowledge of Assembly Programming and Hex Code manipulation because patching a binary with IDA Pro especially deals with assembly opcode instructions. Besides that, the reverse engineer is supposed to operate the IDA Pro Software IDE features perfectly. This operation lists the following tools of the trade.

  • The Target Binary (C /C++ code)
  • IDA Pro Interactive Dissembler
  • IDA-Script File (*.idc files)
  • Assembly Language skills
  • ASCII Converter

Binary Sample

This article exposes the demonstration of byte patching over a typical C++ binary that essentially requires a user password to validate his identity and let him log into the system and such confidential information is only provided to the registered person indeed. There is of course no direct method to breach into this application without being authenticated except to reverse engineer or patch the critical bytes responsible for doing the validation. The following code will make the binary executable live as binaryCrack.exe.

We can use any compiler to execute the aforementioned binary source code that makes an executable as binaryCrack.exe and when we run that file, it will prompt us to enter the password. If we enter the correct password as “aAjay then it shows the congratulatory message otherwise issues the Wrong Password message as in the following.

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <conio.h>  
#define password "ajay"  
int _tmain(int argc, _TCHAR * argv[]) {  
  char pwd[100];  
  printf("Please enter the password::\n\n");  
  scanf("%s", pwd);  
  if (strcmp(pwd, password) == 0) {  
    printf("Congratulation!!\n\n");  
    printf("Ready to login with: %s", password);  
  } else {  
    printf("Wrong password");  
  }  
  getch();  
  return 0;  
} 

BinaryDebug

We might not have a real password and in such circumstances, we can't proceed without this information. So the only option left is Reverse Engineering this binary and to manipulate the sensitive bytes to suit your needs as we shall see in the next sections. Patching Configuration in IDA Pro The patching or editing of assembly code features is normally invisible in the IDA Pro. You can double-check it from the Edit menu that there are no Patch program options. Thus, to see this option, open the ileaguecfg configuration file of IDA Pro located at the Drive: \Program Files\IDA PRO Advanced Edition\cfg folder and scroll down to the DISPLAY_PATCH_SUBMENU option that is typically set to NO. So, make the following changes and save this file.

Display_Patch

After saving this file, re-launch the IDA PRO, and the moment you change the submenu option in the configuration file, you will see that the Patch program option becomes visible in the Edit menu as in the following.

PatchProgram

Now, load the target binary into IDA Pro, it will ask to create a new database, as usual, and then select the PE file option as in the following figure. An important point to remember is, don't forget to uncheck the Make imports segment option because some useful data can be lost from the database if this option is enabled as in the following.

LoadNewFile

The target file will be loaded into the IDA Pro but we could still not modify the byte sequence of the binary file even if the Patch program option is enabled in the Edit menu earlier. So here, the role of the special IDA script files came into light as they can modify the byte like OllyDbg as well as write the changes into the executable to make the effect permanent. The IDC script files can be downloaded from here. When downloaded, extract the files in a separate folder on the file system of your machine. There are a couple of script files that are provided, but mainly two script files are significant as in the following.

ScriptFile

After loading the target binary into the IDA Pro, open the folder where the previous IDA script files are located and execute the pe_sections.idc file to extend new functionality into IDA Pro for such binary patching and writing. You can ensure the new specifications from the Segments (shift + F7) windows that certain new segments are automatically added to.

NewSegment

After successful completion of such operations, we can modify as well as write the byte sequence into the binary file. Binary Analysis We have only the binary executable so it is nearly impossible to understand the logic implementation without the source code. But we can disassemble the source code of any binary by employing IDA Pro because unless we are aware of the logic flow, we do not know how to subvert any security mechanism. Hence, let's analyze the proper logic flow path of the binary file. Since we can consider the following image, IDA Pro disassembles the binary into raw assembly instruction sets. This program first, prompts the user to enter the password by displaying a string message and then compares this value to a predefined value “aAjay which might be the real password. The comparison happens via the string class strcmp method and if the value is 0 then the entered value is correct otherwise incorrect.

ShowRecord

If the value of the tax register is 1 then the execution is shifted towards the loc_411444 block by the jnz statement, where the “wrong password” message would be echoed to the screen as in the following.

WrongPassword

And if the value of eax is 0 then the jump won't throw the execution anywhere. The program indicates to us that we have entered the correct password as in the following.

CurrentPassword

We can easily anticipate that the Jump instruction determines whether the password is correct or incorrect. If the tax register has the value 1 then execution is diverted towards the “wrong password” box flow otherwise the “congratulation” message would be displayed. We are implying from the execution flow that everything depends on the JNZ instruction. So, the reverse engineer would surely be interested in this instruction because manipulation of this instruction can produce different results. Binary Cracking and Patching As we have concluded from the analysis, the outcome of this binary application is regulated by the jnz short 1oc_411444 statements. The 1oc_411444 instruction belongs to the unmatched password displaying block and execution is directly jumping to this block as you can see in the Red arrow.

ShowData

However, all we need to do is change the corresponding jnz statement-related bytes. So right-click on the current location of this statement and synchronize it with Hex Editor View to examine this statement byte sequence as in the following:

CurrentLocation

The hex view offers 16 bytes of sequence in one line and every two bytes represent only one assembly instruction set such that the hex value 75 35 belongs to .text: 0041140D address location where the assembly code jnz short 10c_411444 is implemented as the following.

AddressLocation

So we need to identify the correct bytes to a specific instruction so that we can modify it to suit our needs. The following figure shows the hex code that refers to which instruction is in the following.

ShowCase

Finally, we have concluded that hex code 35 is the key value that directs the execution flow of the program. However, select the address location 0041140D in text view go to the Edit menu, choose Patch program, and select Patch Bytes there. It will show up the entire 16 hex bytes sequence like in the hex view as in the following.

AddValue

To diffuse the effect of the jnz statement where the execution is shifting towards the 1oc_411444 block, we need to change its corresponding hex value from 35 to 00 which typically fills no action in the memory as in the following.

Values

The moment you change the 1oc_411444 instruction code to 00, it will also reflect in the assembly as in the following.

InstructionCode

You can also notice the modification in the hex view as in the following.

NoticeModification

One of the important changes to notice is that after making the value 00, this time no jump arrow is showing that was pointing to the execution that diverts to 1oc_411444 as in earlier.

ShowData

Now open the graph view and see that the “congratulation” block is merged into the main code rather than being separated as earlier before the editing of the hex value. The Blue arrow finally goes to the end of the statement block and the “wrong password” block is isolated or disconnected from the main operation. So even if we enter the wrong password value, the correct password block would always be executed because the jnz statement code is diffused to 00 and the 1oc_411444 block is disconnected as in the following.

DisconnectedData

Ok, we have done the byte editing, it is time to save the effect permanently into memory, but IDA Pro is not capable of writing bytes of the binary file into memory. It can instead write altered bytes into a database. So for this purpose, an IDA special script file is used here. Go to File select Script file and choose pe_write.idc that makes the perpetual effects in the memory as in the following.

EditingData

The moment you run the pe_write.idc file, you will see that bytes have been written to segments successfully and finally, IDA will prompt to re-save the binary file as in the following.

Sections Written out

Save the modified binary with the same name as binaryCrack.exe as in the following.

Binary Crack

Now, load the binaryCrack.exe and it will prompt you to enter the password, merely enter a value, and Bingo! The congratulatory message along with the original password appears. We have successfully bypassed or subverted the password mechanism by patching some related critical bytes using IDA Pro.

CrackDebuging

Patching String Bytes As we can observe in the binaryCrack.exe, a couple of string messages are showing. We can access all these strings into place via the String window (shift + F12) and can directly reach its assembly code merely by clicking the string.

AccemblyCode

It is not a good programming practice to show sensitive strings like serial keys or passwords directly. Such information should be hidden because after patching (reverse engineering) the password assembly code, the hacker can easily understand that the password is “Ajay” since it is showing after the “congratulation” message. So we can hide or rename the showing of the password on the screen by patching its corresponding bytes. So, double-click over the “Ajay” in the String windows, and IDA will let us reach its assembly code where we can modify its visibility.

IDA

Thereafter open the Hex view and we can observe the “ajay” byte code sequence as 61 6A 61 79 00 as in the following.

CodeSequence

Again open the Patch Bytes from the Patch program that resides in the Edit menu and replace all these bytes with 00 as in the following.

EditMenu

Now once again, run the pe_write.idc to make the changes perpetual in the binary file and the binaryCrack.exe. Enter any value as the password and observe that this time the real password is not showing.

RealPassword

Removing Segments A question comes into the mind of why should we display the string message after the “Congratulation” message when we subverted the password mechanism. We cannot allow the execution of a specific assembly code by using IDA Pro. Here, we can easily determine that the code instruction after address location 00411411 is senseless to be displayed as in the following.

AddressLocation1

This time we are not patching the bytes, instead, we are integrating them into new assembly code so that any string message won't be displayed after the “Congratulation” message. Hence, go and patch the program and choose to Assemble as in the following.

PatchProgram

Now place a nop assembly instruction (that stands for no operation) and it decides that none of the code would be executed as in the following.

InstructionAsemble

After this, you can see that a nop is placed after 0041132 locations as in the following.

Nop

Now, run pe_write.idc again and see that none of the code is executing after the message as in the following.

Messages

Script Patching Substitute It is not necessary that we can only patch bytes using an IDA Script file that exports the current IDA database into the EXE binary executable. Rather, we can choose another approach. First, make changes in the byte or hex code just by editing them and produce a new DIF file as a test. dif. Now open the test.dif file and it shows the original hex code and patched code as in the following.

OriginalCode

Later compile the following C program using any editor (I suggest using GCC in the Linux platform).

#include <stdio.h>
int main(int argc, char **argv) {
    char line[256];
    FILE *patch = stdin;
    FILE *input = NULL;
    unsigned int offset;
    int orig;
    int newval;
    int i;
    
    for (i = 1; i < argc; i += 2) {
        if (!strcmp(argv[i], "-p")) {
            if ((i + 1) < argc) {
                FILE *f = fopen(argv[i+1], "r");
                if (f) {
                    patch = f;
                }
                else {
                    fprintf(stderr, "Failed to open patch file %s\n", argv[i+1]);
                    exit(0);
                }
            }
        }
        else if (!strcmp(argv[i], "-i")) {
            if ((i + 1) < argc) {
                fprintf(stderr, "Opening %s\n", argv[i+1]);
                input = fopen(argv[i+1], "rb+");
                if (input == NULL) {
                    fprintf(stderr, "Failed to open input file %s\n", argv[i+1]);
                    exit(0);
                }
            }
        }
        else {
            fprintf(stderr, "usage:\n\t%s [-i <binary>] [-p <dif file>]\n", argv[0]);
            fprintf(stderr, "\t%s [-p <dif file>]\n", argv[0]);
            fprintf(stderr, "\t%s [-i <binary>] < <dif file>\n", argv[0]);
            fprintf(stderr, "\t%s < <dif file>\n", argv[0]);
            exit(0);
        }
    }
    
    if (patch == stdin) {
        fprintf(stderr, "Reading patch data from stdin.\n");
    }
    fgets(line, sizeof(line), patch); /* eat dif file intro line */
    fgets(line, sizeof(line), patch); /* eat blank line */
       
    if (input == NULL) {
        fprintf(stderr, "Inferring input file name from patch file data.\n");
        fscanf(patch, "%256s", line);
        input = fopen(line, "rb+");
        if (input == NULL) {
            fprintf(stderr, "Failed to open input file %s\n", line);
            exit(0);
        }
    }
    else { /* don't need input file name, but need to skip it in dif file */
        fgets(line, sizeof(line), patch);
    }
    
    while (fscanf(patch, "%x: %x %x", &offset, &orig, &newval) == 3) {
        fseek(input, offset, SEEK_SET);
        if (fgetc(input) == orig) {
            fseek(input, offset, SEEK_SET);
            fputc(newval, input);
        }
        else {
            //original bytes don't match expected?
        }
    }
    fclose(input);
    if (patch != stdin) {
        fclose(patch);
    }
}

After compiling this code successfully, execute the following command in a command prompt that requires the DIF file and the new patched file name as in the following.

ida_patcher.exe -i PatchedApp.exe -p binaryCrackPatched.dif

This approach also fulfills the same objective and produces a patched binary as defined earlier in the papers.

Final Note

So, we have learned one of the amazing tactics of patching the binary and producing a new executable file using IDA Pro, for which crackers used to struggle because of the IDA limitation that it can only disassemble the binary code to analyze the vulnerabilities or bugs in the code. We can temporarily divert the instruction code by modifying the ZF register during debugging just by placing the breakpoint but can't patch or modify the bytes sequence into the memory directly to produce a new binary executable because IDA Pro makes changes in the database, not in the binary executable. This paper taught us how to see the hidden features of the Patch program in the IDA Pro IDE. We have also come across string patching and a new way to modify bytes by producing a DIF file that is later passed as an argument to a custom C patch code.