Saturday, March 8, 2014

Malware Analysis 2 - Analysis in Virtual Machines


A safe environment helps us to investigate the malware without exposing our machine or other machines on the network to unexpected and unnecessary risk. Malware can also be analyzed using individual physical machines on air-gapped networks. These are isolated networks with machines disconnected from the Internet or any other networks to prevent the malware from spreading.

The lack of Internet connection is a major disadvantage as many piece of malware depend on a live Internet connection for updates, command and control and other features. Another disadvantage of physical machines is that malware can be difficult to remove.
The main advantage of using physical machines is that malware can sometimes execute differently on virtual machines, As you're analyzing a malware on a virtual machine, some malware can detect that its being run on a virtual machine and it will behave differently. Because of the risks and disadvantages that come with using physical machines, virtual machines are commonly used for dynamic analysis.

The Structure Of A Virtual Machine
A guest OS is installed within the host OS on a virtual machine, and the OS running in the virtual machine is kept isolated from the host OS. Malware on a VM cannot harm the host OS. And if the malware damages the host OS, you can simply reinstall the OS in the VM or return the VM to a clean state.

Creating Your Malware Analysis Machine

Apart from disconnecting the VM from the internet there are a few other options

Host-Only Networking
Host-only networking, a feature that creates a separate private LAN between the host OS and the guest OS, is commonly used for malware analysis. A host-only LAN is not connected to the Internet, which means that the malware is contained within the VM but allowed some network connectivity.

When host-only networking is enabled, VMware creates a virtual network adapter in the host and virtual machines, and connects the two without touching the host's physical network adapter. The host's physical network adapter is still connected to the Internet or other external network. 



Using Multiple VMs
This requires multiple VMs linked by a LAN but disconnected from the Internet and host machine, so that the malware is connected to a network, but the network isn't connected to anything important.

In this configuration, one VM is set up to analyze malware, and the second machine provides services. The two VMs are connected to the same VMNet virtual switch. IN this case, the host machine is still connected to the external network but not to the machine running the malware.







Using Your Malware Analysis Machine

To exercise the functionality of the subject malware as much as possible, all network services which the malware relies on must be simulated. e.g. malware commonly connects to an HTTP server to download additional malware. TO observe this, you'll need to give the malware access to a DNS server to resolve the server's IP address, as well as an HTTP server to respond to requests. With our custom configuration, the machine providing services should be running the services required for the malware to communicate.

Connecting Malware to the Internet
Perform some analysis first and connect only if you are comfortable with the risks.

The most common way to connect a VM to the Internet is a bridged network adapter, which allows the VM to be connected to the same network interface as the physical machine. Another way to connect malware running on a VM to the Internet is use VMware's NAT mode.

NAT mode shares the host's IP connection to the Internet. The host acts like a router and translates all requests from the VM so that they come from the host's IP address. This mode is useful when the host is connected to a network, but the network configuration makes it difficult, if not impossible to connect the VM's adapter to the same network.

Connecting and Disconnecting Peripheral Devices
Most devices can be connected either to the physical machine or the VM, but not both.
If you connect a USB device to a machine while the VM window is active, VMware will connect the device to the guest and not the host, which may be undesirable, considering the growing popularity of worms spreading through USB devices. To modify this setting, choose VM > Settings > USB Controller and uncheck the Automatically Connect new USB devices checkbox to prevent them from being connected to the VM.

Taking Snapshots
VMware's VM snapshots allow you to save a computer's current state and return to that point later, similar to a Windows restore point. It's like a built-in undo feature which saves you the hassle of re-installing the OS. After you have installed the OS and installed the tools, take a snapshot and this serves as you base snapshot.
You can also branch your snapshots to take different paths. For example:
1. While analyzing sample 1, you are frustrated and want to try another sample.
2. You take a snapshot of the malware analysis of sample 1
3. You return to the base image
4. You begin to analyze sample 2
5. You take a snapshot to take a break
When you return, you can access either snapshot at any time.

Transferring Files from a Virtual Machine
One drawback of using snapshots is that any work undertaken on the virtual machine is lost when you revert to an earlier snapshot. You can, however, save your work before loading the earlier snapshot by transferring any files that you want to keep to the host OS using VMware's drag and drop feature. Another way to transfer is VMware's shared folders. A shared folder is accessible from both the host and the guest OS, similar to a shared Windows folder.


The Risk of Using VMware for Malware Analysis
Some malware can detect when its running within a virtual machine, and many techniques have been published to detect just such a situation. 

  

Friday, March 7, 2014

Malware Analysis 1 - Basic Static Techniques


Static Analysis - process of analyzing the code or structure of a program to determine its function. The program itself is not run.
Antivirus Scanning: A Useful First Step

A good first step - Run it through multiple antivirus tools. They rely on a database of identifiable pieces of known suspicious code (signatures) as well as behavioral and pattern-matching analysis (heuristics) to identify suspect files.
Problem - Malware writers can easily modify their code, changing their programs signatures and evading anti-virus scanners.

Websites like VirusTotal allow you to upload a file for scanning on multiple antivirus engines and generates a report that provides the total number of engines that marked it as malicious, the malware name and additional information.


Hashing: A Fingerprint for Malware
A common method to uniquely identify malware. The malware when run through a hashing program produces a unique hash that identifies the malware (fingerprint). MD5 or SHA1 used.

e,g, Using the freely available md5deep
C:\>md5deep c:\WINDOWS\system32\sol.exe

Once you have a unique hash you can:
 - use it as a label
 - share with other analysts to help them identify malware
 - search for it online to see if has already been identified

Finding Strings
A program contains strings if it prints a message, connects to a URL, copies a file to a specific location.
Searching through the strings can give us hints about the functionality of the program. e.g. if the program accesses a URL, then you see the URL stored as a string. We can use the Strings program to search an executable for strings which is in ASCII or Unicode format.

Both ASCII and Unicode store characters in sequences that end with a NULL terminator. ASCII strings use 1 byte per character and Unicode uses 2 bytes per character.

e.g. ASCII representation of the string "BAD"

e.g. Unicode representation of the string "BAD"

When Strings searches executables for ASCII and Unicode strings, it ignores context and formatting, so that it can analyze any file type and detect strings across an entire file (this also means that it may identify bytes of characters as strings when they are not). Sometimes it interprets memory addresses, CPU instructions or data as strings incorrectly. Fortunately, most invlaid strings are obvious because they do not represent legitimate text. 


If a string is short and doesnt correspond to words it is mostly meaningless. Here, strings GetLayout and SetLayout are Windows functions used by the Windows graphics library.  Windows function names normally begin with a capital letter and subsequent words are also capital letters.

GDI32.DLL is meaningful because it's the name of a common Windows DLL used by graphics programs. We also see an IP address which most likely the malware will use in some fashion. 

Finally, the last string is an error message. Error messages often give us the most useful information. This message reveals two things: The subject malware sends messages (probably through email) and it depends on a mail system DLL. This suggests that we might want to check email logs for suspicious traffic, and that another DLL might be associated with this malware.

Packed and Obfuscated Malware

Obfuscated programs are ones whose execution the malware author has attempted to hide. Packed programs are a subset of obfuscated programs in which the malicious program is compressed and cannot be analyzed. Both techniques severely limit our attempts to statically analyze the malware.
Packed malware will contain very few strings.

Packing Files
When the packed program is run, a small wrapper program also runs to decompress the packed file and then run the unpacked file. When the packed program is analyzed statically only the small wrapper program can be dissected.

One way to detect packed files is the PEiD program. 

When a program is packed, you must unpack it to perform analysis. The unpacking process is complex but UPX packer is very popular and easy to use for unpacking. To decompress it
upx -d <packed program.exe>

PE File Format

Understanding the format can reveal important information about the malware. See "Dissecting The PE File Format Series" to learn more.

Linked Libraries and Functions
One of the most useful pieces of information about an executable is the list of function it imports. Imports  are functions used by one program that are stored in a different program, such as code libraries that contain functionality common to many programs. Code libraries can be connected to the main executable by linking.
Programmers can link imports to their programs so that they don't beed to re-implement certain functionality in multiple programs. Code libraries can be linked statically, at runtime or dynamically. Knowing how the library code is linked is critical to our understanding of malware because the information we can find in the PE file header depends on how the library code has been linked.

Static, Runtime and Dynamic Linking
Static Linking - least common. All code from the library is copied into the executable, which makes the executable grow in size. When analyzing code, its difficult to differentiate between statically linked code and the executables own code, because nothing in the PE file header indicates that the file contains linked code.
Runtime linking is commonly used in packed or obfuscated malware. Executables that use runtime linking connect to libraries only when that function is needed, not at program start, as with dynamically linked programs.
Several Windows functions allow programmers to import linked functions not listed in the program's file header. Of these, the two most commonly used are LoadLibrary and GetProcAddress. LdrGetProcAddress and LdrLoadDll are also used. LoadLibrary and GetProcAddress allow a program to access any function in any library on the system, which means that when these functions are used, you can't tell statically which functions are being linked to by the suspect program.
Dynamic Linking is the most common. When libraries are dynamically linked, the host OS searches for the necessary libraries when the program is loaded. When the program calls the linked library function, that function executes within the library.
The PE file header stores information about every library that will be loaded and every function that will be used by the program. The libraries used and functions called are often the most important parts of a program, and identifying them is particularly important, because it allows us to guess what the program does. e.g. if it imports UrlDownloadToFile, its an easy guess.

Exploring Dynamically Linked Functions with Dependency Walker
Dependency Walker lists the dynamically linked functions in an executable.


The left pane shows the DLLs being imported. When you click on one of them, the upper right pane shows the imported functions of that DLL. The middle right pane (4) lists all functions in that DLL that can be imported. We see that the executables can be imported by name or by ordinal. When importing a function by ordinal, the name of the function never appears in the original executable and it can be harder to analyze it. In this case, you can find out the function being imported by looking at the middle pane.


Imported Functions
The PE header will include information about specific functions used by an executable. The name of these Windows functions can give us a good idea about what the executable does.

Exported Functions
Like imports, DLLs and EXEs export functions to interact with other programs and code. Typically, a DLL implements one or more functions and exports them for use by an executable that can then import and use them.
The exported functions can be found in the PE. Exported functions are commonly found in DLLs. The exported functions are generally named meaningfully but it can have any name its name. So, the name of the exported functions are of limited use when analyzing malware. 


Static Analysis in Practice

PotentialKeylogger.exe
We see that this executable imports the following functions.































You see a huge list of imported functions but only some of them are useful. 
The imports from kernel32.dll tells us that this software can open and manipulate processes and files. The functions FindFirstFile and FindNextFile can be used to navigate through directories.
The imports from user32.dll have a lot of GUI based functions which suggests that this program might have a GUI (it may not necessarily be displayed to the user).
The function SetWindowsHookEx is commonly used in spyware and is the most common way that key loggers receive keyboard inputs. This function has some legitimate uses but if you suspect a malware and see this, you are probably looking at key-logging functionality.
The function RegisterHotKey is also interesting. It registers a hot key so that whenever the user presses the hot key combination the application is notified.
The imports from GDI32.dll are graphics related and confirm that this probably has a GUI.
The imports from shell32.dll tells us that this program can launch other programs, another common functionality of malware.
The imports from Advapi32.dll tells us that this program uses the registry which also tells us that we should look for strings that look like registry keys. Registry keys look a lot like directories. In this case we found Software\Microsoft\Windows\CurrentVersion\Run which controls the programs that are automatically run when Windows starts up.

This also has a few exports: LowLevelKeyboardProc and LowlevelMouseProc.
Microsoft documentation - "The LowLevelKeyboardProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function." In other words, this function is used with SetWindowsHookEx to specify which function is called when a specific event occurs - in this case, a low-level keyboard event. We were able to get this info as in this case the programmer used the same name as the export.

PackedProgram.exe - A Dead End
If a program is packed you will see very few imported functions and prevents us from learning more through static analysis.

The PE File Headers and Sections
Understanding the PE header and the information obtained from it is very useful to understand certain malware functionality. See the PE File Format series for more information.


Thursday, March 6, 2014

Dissecting the PE File Format - 12

PACKERS

In this post I will cover the effects of a simple packer and 2 ways of patching a packed executable - either by unpacking first or in-line patching. I use UPX1.25 since this is an executable compressor and doesn't use advanced protection mechanisms

First, we scan our app with PEiD

Next, we pack our app with UPX. This is a command line utility so we open a DOS box where our app is an type upx <filename.exe>


We notice the file down from 225kb to 91kb and in PEID we see this:


PEBrowse Pro shows that there are only 3 sectons UPX0, UPX1 and .rsrc.  The resource section now contains the import directory but for each DLL there are only two imported functions - the others have disappeared.


Note the .rsrc section has retained the original name even though the others have changed. Interestingly this dates back to a bug in the LoadTypeLibEx function in oleaut32.dll in win95 in which the string ".rsrc" was used to find and load the resource section. This created an error if the section was renamed. Although this bug has been fixed it seems most packers do not rename the rsrc seciton for compatibility reasons.

By opening the app in LordPE editor and pressing the compare button we can open an original copy of our app and see the changes made to the headers.

Open the app in Olly. Click OK on the warning which tells you that the executable is probably packed and we land at the entry point.


UPX has compressed our app and appended the code with a stub containing the decompression algorithm. The entry point of this app has been changed to the start of the stub and after the stub has done its job, execution jumps to the original entry point to start our now unpacked program.

The rationale for dealing with this is to let the stub decompress the app in memory and then dump the memory region to a file to get the unpacked copy of the app. However, the app will not run straight away because the dumped file will have its sections aligned to memory page boundaries rather than file alignment values, the entry point still points to the decompression stub and the Import Directory is also wrong.

Note at our entry point in Olly we have Pushad. This stands for push all double and instructs the CPU to store the contents of all the 32 bit registers on the stack staring with EAX and ending with EDI. Following this, the stub does its job and then ends with a POPAD instruction before jumping to the OEP. POPAD copies the contents of the register back from the stack. This means that the stub will have restored everything back the way it was and exited without trace before running the app. Since this method is ideal in this situation, it is common to other simple packers.

From the time of the first PUSHAD instruction, the contents of the stack at that level must remain untouched until accessed by the final POPAD. If we put a hardware breakpoint on the first 4 bytes of the stack at the time of the PUSHAD Olly will break when the same 4 bytes are accessed by the POPAD instruction and we will be right in front of the jump to OEP.

First, press F7 to execute the PUSHAD instruction. Next we place the breakpoint. The ESP register always contains the top of the stack so, rightclick on ESP and select follow in dump - this puts the stack in hexdump window.


Now highlight the DWORD of the stack, rightclick and select breakpoint, hardware on access, DWORD:


Next, run the app by pressing F9 and Olly breaks directly before the jmp to OEP. The OEP shown here ahs ImageBase 400000h added to it so to make it an RVA we subtract it which leaves us with 2ADB4h


If you want to cheat, for some packers simply scroll to the end of the code in the CPU window in Olly and just before all the zero padding starts you will see the POPAD instruction.

Next, we single step once so we are the OEP and dump the app using Ollydump plugin. Just click on plugins, Ollydump and select dump debugged process. In the next box we will deselect fix raw size and rebuild imports to illustrate some points of interest:


Note that OllyDump has already worked out the base address an size of image and has offered to correct the entry point for us. Press dump and save the file.

Unfortunately we see that something is wrong because our file has lost its icon and if we try to run it we get an error.

This is because of the alignment issues mentioned earlier - the filesize has also increased as a result. Open the app in LordPE and look at the sections. The raw offset and the raw size values are wrong. We will have to make the Raw values equal to the virtual values for each section for the app to work. Rightclick the UPX0 section and select edit header.

Now make RawOffset equal VirtualAddress and RawSize equal VirtualSize. Repeat for the other sections, save and exit (this is what fix raw sizes checkbox in Olly means). now the icon has returned and we get a different error when we try to run it. "The application failed to initialize properly." This is because the imports still need rebuilding.

To do this, we use ImpRec. It needs to attach to a running process and also needs the packed file to find imports. Start ImpRec and follow these steps:

1. select basecalc.exe in the box at the top (it should still be running in Olly.) 
2. Next enter our OEP (2ADB4) in the appropriate box 
3. Press the "IAT AutoSearch" button and click OK on the messagebox 
4. Press the "Get Imports" button 
5. Press "Show Invalid" - in this case there are none 
6. Press "Fix Dump" and select basecalc_dmp.exe in the open dialogbox 
7. Exit.


ImpRec will save a fixed copy of our dumped file appended with "_". So run and test it. If we examine the file, we see an extra section named "mackt" - this is where ImpRec puts the new import data. 

Since UPX is purely a compressor, it has taken the existing import data and stored it in the resource section without encrypting or damaging it. This is why ImpRec finds all valid imports without resorting to tracing or rebuilding - it has taken the import directory from the packed executable in memory and transferred it to the new section in the unpacked executable.

PEiD now shows Borland Delphi instead of UPX.

These are the steps necessary to unpack an executable packed with a simple compressor. More advanced packers add various protection schemes to this e.g. antidebugging and anti-tampering tricks, encryption of code and IAT, stolen bytes, API redirection etc. which are beyond the scope of this post.

If it is necessary to patch a packed executable, it may be possible to avoid unpacking it first by using a technique called "inline-patching". This involves patching the code at runtime in memory after the decompression stub has done its work and then finally jumping to the OEP to run the app. In other words we wait until the app is unpacked in memory, jump to patching code we have injected, then finally jump back to the OEP.

To illustrate this we will inject code in the packed executable to pop up a messagebox and let us know when the app is unpacked in memory. Clicking OK will then jump to the OEP and the app will run normally.

The first task is to find some free space for our code so open the packed app in the hex editor and look for a suitable "cave". Free space at the end of a section is better as it is less likely to be used by the packer and is extensible by enlarging the section if necessary. You can see how efficient UPX is - there is hardly any free space - but a small cave exists here. Now add the text "Unpacked" and "Now back to OEP" in the ASCII column of the hex editor as shown:


This will mark our spot for the patch in Olly without having to worry about calculating RVAs. Save changes and open the app in Olly. Rightclick in the hex window and select search for binary string. Now enter "Unpacked" and note the VA of the two strings. In the CPU window, right click and select go to expression. Enter the address of the first string and you will see the two strings in hexadecimal form. Olly has not analyzed this properly so it displays nonsense code next to it. Highlight the next free row underneath and press spacebar to assemble the following instructions.

PUSH 0
PUSH 440C30 [address of first string]
PUSH 440C40 [address of second string]
PUSH 0
CALL MessageBoxA
JMP 42ADB4


Make a note of the address of our first PUSH instruction - 440C4E. Our code should look like this


Now rightclick and select copy to executable, selection. In the new window rightclick and select save file etc. If we check in the hexeditor we see that our code has been added.

Finally we need to change the JMP at the end of theUPX stub to go to our code. Find it as shown earlier, double click the JMP instruction to assemble and change the address to 440C4E. Save changes again and run app to test it.


This ends the entire PE File Format Series :-)













Dissecting the PE File Format - 11

Adding Import To an Executable


This is most often used in the context of patching a target app where we dont have the APIs we need. To recap, the minimum information needed by the loader to produce a valid IAT is:


1. Each DLL must be declared with an IMAGE_IMPORT_DESCRIPTOR(IID), remembering to close the Import Directory with a null-filled one.
2. Each IID nneds at least Name1 and FirstThunk fields, the rest can be set to 0 (setting OriginalFirstThunk = FIrstThunk i.e. duplicating the RVAs also works)
3. Each entry of the FIrstThunk must be an RVA to an Image_Thunk_Data (the IAT) which in turn further contains an RVA to the API name. The name will be a null-terminated ASCII string of variable length and preceded by 2 bytes (hint) which can be set to 0.
4. if IIDs have been added then the isize field of the import table in the Data Directory may need changing. The IAT entries in the Data Directory need not be altered.

Writing new import data in a hex editor and then pasting into your target can be very time-consuming. There are tools which can automate this (SnippetCreator, IIDKing etc) but to understand the concept its best to do it manually. The main task is to append a new IID onto the end of the import table - you need 20 bytes for each DLL used, not forgetting 20 bytes for the null-terminator. In nearly all cases there will be no space at the end of the existing import table so we will make a copy and relocate it somewhere there is space.

Step 1 - Create space for a new IID

This involves the following steps:

  1. Move all the IIDs to a location where there is plenty of space. This can be anywhere; at the end of the current .idata section or an entirely new section. 
  2. Update the RVA of the new Import Directory in the Data Directory of the PE header.
  3. If necessary, round up the size of the section where you've put the new Import table so everything is mapped in memory (e.g. VirtualSize of the .idata section rounded up 1000h)
  4. Run it and if it works we move on to step 2. if it doesn't check the injected descriptors are mapped in memory and that the RVA of the import directory is correct.
NOTE - The IIDs, FirstThunk and OriginalFirstThunk contain RVAs - RELATIVE ADDRESSES - which means you can cut and paste the Import Directory (IIDs) wherever you want in the PE file (taking into account the destination has to be mapped into memory) and simply changing the RVA (and size if necessary) of the Import Directory in the Data Directory will make the app run perfectly.

Back to the hex editor, the first IID and the null terminator are outlined in red and you see that there is no space after the null IID.



However, there is a large amount of space at the end of the .idata section before .rdata starts. We will copy and paste the existing IIDs shown above to offset 2C500h at this new location:

 
















To convert the new offset to an RVA

VA = Raw Offset - RawOffsetOfSection + VirtualOffsetOfSection
 = 2C500 - 2AC00 + 2D000 = 2E900h

So change the virtual address of the import table in the data directory from 2D000 to 2E900. Now edit the .idata section header and make virtual size equal to RawSize so the loader will map the whole section in. Run the app to test it.


Step 2 - Add the new DLL and function details

This involves the following steps:
  1. Add null-terminated ASCII string of the names of your DLL and function to a free space in the .idata section. The function name will actually be an Image_Import_By_Name structure preceded by a null word (the hint field)
  2. Calculate the RVAs of the above strings
  3. Add the RVA of the DLL name to the Name1 field of your new IID
  4. Find another DWORD sized space and put in it the RVA of the hint/function name. This becomes the Image_Thunk_Data or IAT of our new DLL.
  5. Calculate the RVA of the above Image_Thunk_Data DWORD and add it tot he FirstThunk field of your new IID.
  6. Run the app to test and your new API is ready to be called.
In order to fill our new IID we need at the very least Name1 and FirstThunk fields (the others can be nulled). The Name1 field contains the RVA of the name of the DLL in null-terminated ASCII. The FirstThunk field contains the RVA of an Image-Thunk Data Structure which in turn contains yet another RVA of the name of the function in null-terminated ASCII. The name is preceded by 2 bytes (Hint) which can be set to zero.

For e.g. we want to use the function LZCopy which copies a source file to a destination file. if the source file is compressed with the Microsoft File Compression Utility, this function creates a decompressed destination file. If the source file is not compressed, this function duplicates the original file.

This function resides in lz32.dll which is not currently used by our app. Therefore we first need to add strings for the names "Lz32.dll" and "LZCopy". We scroll upwards in the hex editor from the new import table towards the end of the preexisting data and add the DLL name then the function name onto the end. Note the null bytes after each string and the null WORD before the function name.


















Now we need to calculate the RVAs of these:

RVA = RawOffset - RawOffsetOfSection + VirtualOffsetOfSection + ImageBase

RVA of DLL Name - 2c420 - 2ac00 + 2d000 = 2E820 (20 E8  02 00 in reverse)
RVA of Function name - 2c430 - 2ac00 + 2d000 = 2E830 (30 E8 02 00 in reverse)

The first one can go into the name1 field of our new IID but the second must go into an Image_Thunk_Data structure, the RVA of which we can put into the FirstThunk field (and OriginalFirstThunk) of our new IID. We will put the Image_Thunk_Data structure below the function name string at the offset 2C440 and calculate the RVA which we will put in the FirstThunk

RVA of Image_Thunk_Data = 2C440 - 2AC00 + 2D00 = 2E840 (40 E8 02 00 in reverse)

If we fill the data in the hexeditor:

Finally save changes, run the app to test and re-examine the imported functions in PEBrowse

In order to call the new function, we can use the following code:

CALL DWORD PTR [XXXXXXX] where XXXXXXXX = RVA of Image_Thunk_Data + ImageBase

Final Note: Even if we had added a function used by a DLL which was already in use e.g. kernel32.dll we would still need to create a new IID for it to enable us to create a new IAT at a convenient location as above.


In the next pose we talk about packers.


Monday, March 3, 2014

Dissecting the PE File Format - 10

Adding Code to a PE File


It might be necessary to add code to a program  to either crack a protection scheme or to add functionality.  There are 3 main ways to add code to an executable:

1. Add to an existing section when there is enough space for your code
2. Enlarge an existing section when there is not enough space
3. Add an entirely new section

Add to an existing section


We need a section in the file that is mapped with execution privileges in memory so simplest is to try the CODE section. We then need an area in the section occupied by 00 byte padding. This is the concept of "caves". To find a suitable cave, look at the CODE section details in LORDPE:



Here we see that the VirtualSize is slightly less than SizeOfRawData. The virtual size represents the amount of actual code. The size of the raw data defines the amount of space taken up in the file sitting on your hard disk. Note that the virtual size in this case is lower than that on the hard disk. This is because compilers often have to round up the size to align a section on some boundary. In the hexeditor at the end of the code section we see:


This extra space is totally unused and not loaded into memory. We need to ensure that the instructions we place there will be loaded into memory. We do this by altering the size attributes. Right now the virtual size of this section is only 29E88, because that is all the compiler needed. We need a little more, so in LordPE change the virtual size of the code section all the way up to 29FFF which is the max size we can use (the entire raw size is only 2A000). To do this rightclick  the CODE line and select edit header, make the changes click save and enter.

Once that is done, we have suitable place for our patch code. The only thing we have changed is the VirtualSize DWORD for the CODE section in the Section Table. This could have also been done manually with a hex editor.

Next, we add a small ASM stub that hijacks the entry point and then just returns execution to the original Entry Point. We will do this in Olly.

First we note that the entry point is 0002ADB4 and ImageBase is 400000. When we load the app in Olly the EP will therefore be 0042ADB4. We will add the following lines and then change the entry point to the first line of code:
MOV EAX,0042ADB4 ; Load in EAX the Original Entry Point (OEP) 
JMP EAX ; Jump to OEP 

We will put them at 0002A300h as seen in the hexeditor above. To convert this raw offset to an RVA for use in Olly use the following formula:
RVA = raw offset - raw offset of section + virtual offset of section + ImageBase
 = 2A300h - 400h + 1000h + 400000h = 42AF00h

So load the app in Olly and jump to our target section (press Ctrl + G and enter 42aF00). Press space and type in the first line of assembly and click assemble. The next line should now be highlighted and do the same here.








Now rightclick, select copy to executable and all modifications. Click copy all then a new window will open. Rightclick in the new window and select save file. Now back in LordPE or a hex editor, change the entry point to 2AF00. Now run the app to test it and reopen in Olly to see your new entry point.


Enlarging an Existing Section:
If there is not sufficient space in the text section, you have to extend it. This poses a number of problems.

1. If the section is followed by other sections then you will need to move the following sections to make room.
2. There are various references within the file headers that will need to be adjusted if you change the file size. 
3. References between various sections (such as references to data values from the code section) will all need to be adjusted. This is impossible to do without recompiling and relinking the original file. 

Most of these problems can be avoided by appending to the last section of the exe file. It is not relevant what that section is as we can make it suit our needs by changing the Characteristics field in the Section Table either manually or with LordPE.

First we locate the final section and make it readable and executable. As we said earlier, the code section is ideal for a patch because its characteristics flags are 60000020 which means code, executable and readable. However, if we are to put code and data into this section we could get a page fault since it is not writeable. To alter this we would need to add the flag 80000000 which gives a new value E0000020 for code, executable, readable and writeable.

Likewise if the final section is .reloc then the flags will be 42000040 for initialized data, discardable and read-only. In order to use this section we must add code, executable and writeable and we must subtract discardable to ensure that the loader maps this section to memory. This gives us a new value of E0000060.

This can either be done manually by adding up flags and editing the Characteristics field of the Section header with the hexeditor or LordPE will do it. In our example, the last section is resources.





































This gives us a final characteristic value of F0000060. Above we see the raw size (on disk) of this section is 8E00 bytes but all of this seems to be in use (the VirtualSize os the same). Now edit these and ad  100h bytes to both to extend the section. The new value is 8F00h. There are some other important values which need to be changed. The SizeOfImage field in the PE header needs to be increased by the same amount from 3CE00 to 3CF00.

There are 2 other fields not shown in LordPE which are less critical; SizeOfCode and SizeOfInitializedData in the OptionalHeader. The app will still run without these being altered but you may wish to change them for completeness. We will have to do it manually. Both are DWORDs at offset 1C and 20 from the start of the PE header.







The values are 0002A000 and 0000DE00 respectively. Add 100h on to these. With reverse bytes the values are: 00 A1 02 00 and 00 00 DF 00. Finally copy and paste 100h of 00 bytes onto the end of the section and save changes. Run the file to test for errors.

Adding a new section
In some circumstances you may need to make a copy of an exiting section to defeat self-checking procedures (such as SafeDisk) or make a new section to hold code when proprietary information has been appended to the end of the file.
The first job is to find the NumberOfSections field in the PE header and increase it by 1. Again, most of these changes can be done by LordPE or manually with an hexeditor. Now, in the hexeditor paste 100h of 00 bytes onto the end of the file and make a note of the offset of the first new line. In our case it is 00038200h. This will be the start of our new section and will go in the RawOffset field of the section header. While we are here, it is probably a good time to increase SizeOfImage by 100h bytes.

Next we need to find the section headers beginning at the offset F8 from the PE header. It is not necessary for these to be terminated by a header fill of zeros. The number of headers is given by NumberOfSections and there is usually some space at the end before the sections themselves start (aligned to the FileAlignment value). Find the last section and add a new one after it.


The next thing we need to do is decide which Virtual offset / Virtual Size / Raw Offset and Raw Size our section should have. To decide this, we need the following values:

Virtual offset of formerly last section (.rsrc): 34000h 
Virtual size of formerly last section (.rsrc): 8E00h 
Raw offset of formerly last section (.rsrc): 2F400h 
Raw size of formerly last section (.rsrc): 8E00h 
Section Alignment: 1000h 
File Alignment: 200h 

The RVA and the raw offset of our new section must be aligned to the above boundaries. The Raw Offset of the section is 38200h as we said above (which luckily fits with FileAlignment). To get the VirtualOffset of our section we have to calculate this: VirtualAddress of .rsrc + VirtualSize of .rsrc = 3CE00h. Since our SectionAlignment is 1000h we must round up to the nearest 1000 which makes 3D000h. So lets fill the header of our section.

The first 8 bytes will be Name1 (max. 8 chars e.g. "NEW" will be 4E 45 57 00 00 00 00 00 (byte order not reversed) 
The next DWORD is VirtualSize = 100h (with reverse byte order = 00 01 00 00) 
The next DWORD is VirtualAddress = 3D000h (with reverse byte order = 00 D0 03 00) 
The next DWORD is SizeOfRawData = 100h (with reverse byte order = 00 01 00 00) 
The next DWORD is PointerToRawData = 38200h (with reverse byte order = 00 82 03 00) 
The next 12 bytes can be left null 
The final DWORD is Characteristics = E0000060 (for code, executable, read and write as discussed above) 


Save changes, run to test for errors and examine in LordPE




Dissecting the PE File Format - 9

Navigating Imports On Disk

 In the hex editor, we navigate the import table. The RVA of the import directory is stored in the DWORD 80h bytes from the PE header which in our example is offset 180h and the RVA is 2D000H (as in the Data Directory post). We now have to convert that RVA to a raw offset to peruse the correct area of our file on disk. Check the Section Table to see which section the address of the import directory lies in. In our case, the Import Directory starts at the beginning of the .idata section and we know that the section table holds the raw offset in the PointerToRawData field. In our example, the offset is 2AC00h









The difference between the RVA and the Raw offset is 2D000h - 2AC00h = 2400h. Make a note for this as it will be used for converting further offsets.

At offset 2AC00 we have the import directory - an array of IMAGE_IMPORT_DESCRIPTORS each of 20 bytes and repeating for each import library (DLL) until terminated by 20 bytes of zeroes. 















Each group of 5 dwords represent 1 IMAGE_IMPORT_DESCRIPTOR. The first shows that in this PE file OriginalFIrstThunk, TimeDateStamp and ForwarderChain are set to 0. Eventually we come to a set of 5 DWORDS all set to 0 (highlighted in red) signifying the end of the array. We see that we are importing from 8 DLLs. 

NOTE - The OriginalFirstThunk fields in our example are all set to zero. This is common for executables made with the Borland compiler and linker and is noteworthy for the following reason. In a packed executable the FirstThunk pointers will have been destroyed but can sometimes be rebuilt by copying the duplicate OriginalFirstThunks, There is a utility called First_Thunk Rebuilder which will do this. However, with Borland created files this is not possible because the OriginalFirstThunks are all zeros and there is no INT.

Back to our example above, the Name1 field of the first IMAGE_IMPORT_DESCRIPTOR contains the RVA 00 02  DF 30h (NB Reverse Byte Order). Convert this to a raw offset by subtracting 2400h (remember above) and we have 2b130h. If we look at our PE file we see the name of out DLL.


To continue, the FirstThunk field contains the RVA 00 02 D0 B4h which converts to Raw Offset 2ACB4h. Remember, this si the offset to array of DWORD-size IMAGE_THUNK_DATA structures - the IAT. This will either have its most significant bit set and the lower part will contain the ordinal number of the imported function, or if the MSB is not set it will contain yet another RVA to the name of the function (IMAGE_IMPORT_BY_NAME)

In our file, the DWORD at 2ACB4h is 00 02 D5 3E







This is another RVA which converts to Raw Offset 2B13E. This time it should be a null-terminated ASCII string. In our file, we see








So, the name of the first API imported from kernel32.dll is DeleteCriticalSection. You may notice the two  zero bytes before the function name. This is the hint element which is often set to  00 00.

All of this can be verified using PEBrowse Pro to parse the IAT as shown:
























If the file has been loaded into memory, dumped and examined with the hex editor then the DWORD at RVA 2D0B4h which contained 3E D5 02 00 on disk would have been overwritten by the loader with the address of DeleteCriticalSection in kernel32.dll







Allowing for reverse byte order this is 7C91188A
NOTE:  functions in system DLLs always tend to start at addresses 7xxxxxx and stay the same each time the program is loaded.  However, they tend to change if you reinstall your OS and differ from one computer to another.

The addresses also differ according to OS, for example: 
OS                           Base of kernel32.dll 
Win XP SP1                  77E60000H 
Win XP SP2                  7C000000H 
Win 2000 SP4                79430000H 

Windows updates also sometimes change the base location of system DLLs. 

















Navigating Imports in Memory

Load the example in Olly and look at the memory map







Note the address of the idata section is 42D000 which corresponds to the RVA 2D000 shown at the top of this post as VOffset.  This size has been rounded up to 200 to fit memory page boundaries.

The main (CPU) window of Olly will only show the IAT if it lies in the executable CODE section, however in most cases it will be in its own section e,g, idata. You can view the IAT in Olly's hex-dump by right clicking the appropriate section in memory map and selecting Dump in CPU. Now rightclick in the hex window and select Long>Address and you will see the IAT in a readable list. 



















This makes finding the beginning and the end of the IAT easy and is useful when using ImpREC as the IAT AutoSearch function can be inaccurate. It is good to be able to check the beginning and endpoint to avoid having to type in a large size value which will give many false negatives.

The names window (ctrl + N) will show you imported functions:

Rightclicking any of these and selecting find references to Import will show you the jump thunk stub and the instances in the code where the function is called (only 1 in this case)

Note: In the comment column you will see that Olly has determined that the kernel32.dll function DeleteCriticalSection is actually forwarded to RtlDeleteCriticalSection in ntdll.dll 
Rightclicking and selecting Follow Import in Disassembler will show you the address in the appropriate DLL where the function's code starts e.g. starts at 7C91188A in ntdll.dll

If we look at the call to DeleteCriticalSection at 00401B12 we see:


This is really "CALL 00401314" but Olly has already substituted the function name for us. 401314 is the address of the jump stub pointing to the IAT. Note it is a part of the jump thunk table described previously:

This is really "JMP DWORD PTR DS:[0042D0B4]" but again Olly has substituted the symbolic name for us. Address 0042D0B4 contains the Image_Thunk_Data Structure in the IAT which has been overwritten by the loader with the actual address of the function in kernel32.dll: 7C91188A. This is what we found earlier by rightclicking and selecting follow Import in Disassembler and also from the dumped file above.

In the next post we talk about Adding Code to a PE File