Hacking

Password discovery and patching by disassembling: Explained

AJ Kumar
January 28, 2015 by
AJ Kumar

Disguising the source code of an application from to hide it from malicious hands isn't an ultimate way to protect it from being reverse engineered. Though many layman developers consider this approach the finest, modern reverse engineering techniques become more sophisticated day by day to recognize sensitive information, for instance library functions, local variables, stack arguments, data types, and many more. Moreover, it may be that in the future, reverse engineers will perhaps be able to generate code similar to that of high-level languages. Hence, this article illustrates how to subvert some authentication mechanisms, such as extracting vital information imposed in the binary file while source coding, by analyzing the generated hex code itself of the target executable. However, the approach we are going to discuss would not be effective on the kind of binaries which source code is either obfuscated or packed.

FREE role-guided training plans

FREE role-guided training plans

Get 12 cybersecurity training plans — one for each of the most common roles requested by employers.

This article will subvert authentication constraints of a binary by analyzing a disassembled hex code of the target binary. So, the researcher must be familiar with hex coding analysis of an executable and moreover, be aware of various sophisticated tools, such as Dumpbin, IDA pro, PE Editor, Win-Hex, etc., which will be very conducive in disassembling. Finally, a moderate level of understanding about assembly language semantics would be very beneficial during extracting vital information from the target.

  • Dumpbin.exe
  • Hiew Editor

The target binary

In this section, we will write the target binary itself because we will perform the objective only by means of a custom created VC++ executable, instead of performing on licensed software, because our intent should neither practice offensive reverse engineering nor endorse breaking any software protection mechanism. Therefore, the following source code will be compiled into a console based executable which asks first for the correct security key in the form of a password to proceed into the system. The user strictly provides only three attempts to enter a correct pass key, otherwise system will debar him.

Listing 1:

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

#include <stdio.h>

#include <string.h>#define SIZE 100

#define PASSWORD ********int main ()

{int count=0;

char buff [SIZE]=" ";

char passwd[ ]=PASSWORD;printf ("nWelcome to Console!!n[You may have only 3 unsuccessful login attempts!]n");

for (;;)

{

printf ("Attempt =%d",count+1);

printf ("nEnter the Password:");fgets (&buff [0], SIZE,stdin);

if (strcmp(&buff[0] , &passwd[0]))

{

printf ("Invalid Password: Try Againn");

}

else

{

break;

}

if (++count>2)

{

printf ("nAccess Denied");

return -1;

}

}

printf ("Congratulations!!: Valid Credentialsn");

}

However, we have concealed the correct password key in the source code to create a real-time impression of breaking a software protection constraint, where even the author or audience of this article doesn't know the password. In fact, mentioning the source of the target binary here is redundant in this scenario, since we are learning one of the subverting mechanisms where we don't have the access to the source code. Even so, the source code might be helpful for those viewers who are not proficient enough in developing their own application to apply the tactics as discussed in this paper.

After compiling this source code through any compiler like VC++.NET, or Borland C++ etc., the final console based executable is generated as follows, where it demands the password first, to access ahead of features. However, I have provided the source code of this binary but here, forget everything, it is just offered for researcher convenience. Imagine that the user gets only the final executable, and when he tries to run this console based application without having the actual pass key, he eventually wouldn't be able to go ahead as follows;

Figure 1: Password hit and trial in Target Binary

Suppose you don't possess the actual source code of this application for any reason, and unfortunately, you lost the pass key. How then would you utilize the features of this application, since critical data is at risk and your business is halted altogether in the absence of a pass key? In this critical situation, Dumpbin.exe utility could be the real savior, which is capable of "disassembling" the binary into hex code, so that crucial information can be obtained through analysis of the hex code, in case the source code is not obfuscated.

Binary hex code analysis

Here, I am not claiming 100% efficiency or accuracy of this approach, but suppose the referenced password is stored somewhere in the program, and isn't cryptographed in some artful manner. Unfortunately, then, it can be found by simply looking at the binary code. Inspecting at all the text strings, especially those that look like a password, we'll quickly find the required password and easily "open" the application next level.

Binary hex code analysis by dumping its contents is a significant initial step in reverse engineering, because understanding the internal contents of the target executable is conducive, in terms of gaining an overview of what the program does and which other components it interacts with. There are numerous executable-dumping tools available, for example DUMPBIN.EXE utility which is a great tool for working from a command shell—it can dump all sorts of valuable evidence about a binary, imports and exports, section information, disassembly of the code and many more—you name it, DUMPBIN can probably do it. Overall, it allows you to examine the contents of a Microsoft PE/COFF file.

Command 1: Dumpbin.exe

C:>dumpbin.exe

Microsoft (R) COFF/PE Dumper Version 10.00.30319.01

Copyright (C) Microsoft Corporation. All rights reserved.

usage: DUMPBIN [options] [files]

Note

Hereby, we shall explore or try to obtain significant information from the target binary by applying the DUMPBIN utility's various underlying options.

Dependency on external lib

DUMPBIN is shipped with VC++ in Microsoft Visual Studio, and combines the functionality of the Microsoft development tools including LIB, LINK, and EXEHDR. Thus, DUMPBIN can parse a suspect binary to offer crucial information about the file format and structure, embedded symbolic information, as well as the library files required by the program. To identify an unknown binary file's dependencies, query the target file with DUMPIN, using the "/DEPENDENTS" option as;

> dumpbin /dependents PwdAnalysis.exe

Command 2: Binary dependents

Microsoft (R) COFF/PE Dumper Version 10.00.30319.01

Copyright (C) Microsoft Corporation. All rights reserved.

Dump of file PwdAnalysis.exe

File Type: EXECUTABLE IMAGE

Image has the following dependencies:

MSVCR100D.dll

KERNEL32.dll

Binary header information

The DUMPBIN /headers option displays only the header information pertains to COFF header files and section header files. Here's the headers detail for the PwdAnalysis executable file as:

> dumpbin /headers PwdAnalysis.exe

Command 3: Binary headers

FILE HEADER VALUES

14C machine (x86)

7 number of sections

54BE4E57 time date stamp Tue Jan 20 18:17:19 2015

0 file pointer to symbol table

0 number of symbols

E0 size of optional header

102 characteristics

Executable

32 bit word machine

OPTIONAL HEADER VALUES

10B magic # (PE32)

10.00 linker version

3600 size of code

3C00 size of initialized data

0 size of uninitialized data

11113 entry point (00411113) @ILT+270(_mainCRTStartup)

1000 base of code

1000 base of data

400000 image base (00400000 to 0041BFFF)

1000 section alignment

200 file alignment

5.01 operating system version

0.00 image version

5.01 subsystem version

0 Win32 version

1C000 size of image

400 size of headers

0 checksum

3 subsystem (Windows CUI)

8140 DLL characteristics

Dynamic base

NX compatible

Terminal Server Aware

...

Code segments enumeration

The DUMPBIN /summary option enumerates all the code segments information employed in the binary. However, some of them are generated by default.

> Debug>dumpbin /summary PwdAnalysis.exe

Command 4: Code segments detail

Dump of file PwdAnalysis.exe

File Type: EXECUTABLE IMAGE

Summary

1000 .data

1000 .idata

2000 .rdata

1000 .reloc

1000 .rsrc

4000 .text

10000 .textbss

It's totally up to the hacker's or researcher's intellect which section they pick up to analyze, since these segments contains very helpful data. The PwdAnalysis.exe file contains 7 underlying code segments. Each one contains significant data and has distinguishable importance as;

Segments Description

.text It contains the executable instruction codes and is shared among every process running the same binary.

.bss It holds un-initialized global and static variables. The size that BSS will require at runtime is recorded in the object file, but the BSS doesn't take up any actual space in the object file.

.data It usually has READ/WRITE permissions, contains the initialized global and static variables and their values.

.reloc It keeps information required for relocating the image while loading.

rdata It contains constants and string literals.

Disassembling binary code

The DUMPBIN utility /disasm command line option produces a disassembled listing of the object file in assembly language syntax much like as IDA pro. The /disasm option is used to investigate compiled programs, and can be applied when analyzing "pseudo-compiled" code. If you look closely at disassembled code, you'll easily figure out the flow of execution as well as identify couple stored strings values as;

> dumpbin /DISASM PwdAnalysis.exe

Command 5: Disassembled code of Binary

Password disclosing by examining raw data

A binary file typically contains essential string reference values which are very conducive to figure out the flow of execution, as well as conducive while cracking. Let's assume the reference password stored in the raw data section, hence, obtain the raw data section information by /SECTION:.rdata along with /RAWDATA:BYTES as following;

> dumpbin /RAWDATA:BYTES /SECTION:.rdata PwdAnalysis.exe > analysis

Figure 2: Analysis file dump in Hex Editor

Here in the aforesaid figure, we have successfully identified significant pass key information from raw data as 'kmaraj' in hex code form too.

Obtaining precise information

Although dumpbin.exe with /All option produces considerable output, the problem with this approach is that an EXE file contains all the routines from the language's standard library that the linker has combined into the application. Therefore, such extra information makes the job tedious by creating an overwhelming amount of confusion while analyzing compiler output. Fortunately, you can step aside all the unnecessary information—run DUMPBIN on your object (OBJ) files rather than your executable files. Here is the output of DUMPBIN with the /All option when you supply *.obj as the command-line parameter:

> dumpbin /All PassAuth.obj > analysis

The following result shows only the underlying strings values contained in the binary with their memory address.

Figure 3: Significant information in OBJ

Further, we can easily detect the original pass key along with other necessary information while modifying the hex values of the corresponding memory segments as;

Figure 4: Password in OBJ file

Adding custom code segments

We can slightly hinder the way of the disassembler by not displaying the underlying string reference values in the raw data section, since typically this section is the prime matter of interest. Instead, you can add custom code segments and place vital information over there. Here, we are creating custom .Secure code to protect password information being display into raw bytes as;

Listing 2:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#include <stdio.h>

#include <string.h>#define SIZE 100

#define PASSWORD *********

#pragma data_seg (".Secure")

char passwd[ ]=PASSWORD;

#pragma data_seg ()

#pragma comment(linker, "/SECTION:.Secure,RWS")

int main ()

{

int count=0;

char buff [SIZE]=" ";

}

Now, there is no password information displaying in the data section except another string reference and hacker's attack has been retarded. In fact, we have shielded the crucial information by placing it into custom segments.

> dumpbin /RAWDATA:BYTES /SECTION:.rdata PwdAnalysis.exe > analysis

Figure 5: Password discovering after adding code segments

But wait!!!!!! Don't jump to conclusions so early. You can still obtain such information. First, ensure with the list of sections in the file by displaying them through DUMPBIN. Here, as you can observe in the results, there is an extra code segment .Secure created. Maybe it contains something interesting.

Figure 6: .Secure code segment

Now, pay your attention to the .Secure section. Mention it in the /Section option in the DUMPBIN while displaying raw data bytes as;

> dumpbin /RAWDATA:BYTES /SECTION:.Secure PwdAnalysis.exe

Bingo!! There's the password! And we thought we hid it. It's certainly possible to put confidential data into a section of no-initialized data (.bss), the service RTL section (.rdata), or even into the code section (.text). Because typically not everyone will peep there for the vital information, and such allocation won't disturb the functioning of the program.

Figure 7: Password in .Secure block

If the password could have been written in Unicode somewhere in the source code, or it was ciphered through any cryptic algorithm, the search would be somewhat more complicated, since not all such utilities support this encoding. But it'd be rather native to hope that this obstacle will stop a hacker for long. So, we have obtained the password only by means of DUMPBIN utility. On behalf of this value, you can enter into the application's next level as following;

Figure 8: Output

D:tempPwdAnalysisDebug>PwdAnalysis.exe

Welcome to Console!!

[You may have only 3 unsuccessful login attempts!]

Attempt=1

Enter the Password:kmaraj

Congratulations!!: Valid Credentials

Patching binary

As yet in the previous section, we found the password by examining the raw bytes, in pursuit of stored vital string reference values in the .Secure code section. But, how tiresome it is to enter the password each time you start the program! What if the program accepted any password, or there was no need to enter any password.

Let's consider the .Secure data section once again where the password is stored. We just need to find out the location of the password in memory. Its address will be stored by the pointer.

Figure 9: Getting offset of password

Here, we can easily conclude that the password is located at the 0x419000, so the pointer to it also must be equal to 0x419000. Let's search the disassembled code at 0x419000 using text editor, you found something interesting as;

Figure 10: Reference of 0x419000 methods

Note

Next, focus to understand the goal of the 0x04110A5 function. It's apparent that this function checks the password.

Figure 11: 0x04110A5 method

Further, the TEST EAX, EAX instruction checks if value returned by the function equals zero. If it does, the following JZ instruction jumps to line 0x041149B which led us to the "Invalid password" string as;

Figure 12: TEST instruction

We are almost there. There are two approaches to foil the password protection. Either we replace TEST EAX, EAX with XOR EAX, EAX instruction, and then EAX register will always contain zero, you will surely enter to next level in the program, no matter what password is entered. So, in the HIEW, go to 0x041147E, press F3 for edit, then hit ENTER and change the instruction TEST to XOR. After that, don't forget to save the changes by F9 key.

Figure 13: TEST to XOR

Or, if we replace the JZ instruction with JNE, the program will reject the real password as invalid, and all incorrect passwords will be accepted as valid.

Figure 14: JZ instruction

Here again, go to 0x41149C, press F3 for edit, and then hit ENTER and change the instruction JZ to JNE. After that, don't forget to save the changes with F9.

Figure 15: JZ to JNE

Finally, restart the program and enter anything as a password and see the result. The password protection has fallen as following;

Figure 16: Patched EXE

Conclusion

This article provided a detail overview about disassembling binary code via DUMPBIN utility, and demonstrated its various underlying switches, for instance /DISASM, /Summary etc., which are very beneficial while producing crucial information. However, there are overwhelming tactics of bypassing and code de-compilation of the native binary, especially by using IDA Pro, WinDbg, SoftICE etc. But this article describes the process of obtaining the password information very simply if there are strings somewhere in the source code in an unencrypted form. Finally, by analyzing the code instruction using HIEW, which contains password matching related code, we have subverted the password protection constraints permanently. Thereafter, it does not matter what the pass key the user enters.

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.

Sources

  • Book Reference: Identifying Malicious Code through Reverse Engineering
  • C-programming 
  • Book chapter: Practical Reverse Engineering
  • Book chapter: write_great_code_volume_2
AJ Kumar
AJ Kumar

AJ Kumar is a Cyber security evangelist, has a great passion for open source programming, IT security, bug detection, penetration testing, and assembly language on diverse platforms including Windows and Linux. He can be reached via ajkumarhv[at]gmail[dot]com;