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.
Learn about breaking passwords
Discover key forensics concepts and best practices related to passwords and encryption. This skills course covers
⇒ Breaking password security
⇒ Breaking windows passwords
⇒ Two-factor authentication
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.
- 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.
#include <string.h>#define SIZE 100
#define PASSWORD ********int main ()
char buff [SIZE]=” “;
char passwd[ ]=PASSWORD;printf (“\nWelcome to Console!!\n[You may have only 3 unsuccessful login attempts!]\n”);
printf (“\Attempt =%d”,count+1);
printf (“\nEnter the Password:”);
fgets (&buff , SIZE,stdin);
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
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
usage: DUMPBIN [options] [files]
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:
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
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
3 subsystem (Windows CUI)
8140 DLL characteristics
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
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;
|.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;
#define SIZE 100
#pragma data_seg (“.Secure”)
char passwd[ ]=PASSWORD;
#pragma data_seg ()
int main ()
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
Welcome to Console!!
[You may have only 3 unsuccessful login attempts!]
Enter the Password:kmaraj
Congratulations!!: Valid Credentials
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
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
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.
 Book Reference: Identifying Malicious Code through Reverse Engineering
 Book chapter: Practical Reverse Engineering
 Book chapter: write_great_code_volume_2