Home Injecting an XOR Encoded Shellcode Backdoor Into PE Files Automatically

Injecting an XOR Encoded Shellcode Backdoor Into PE Files Automatically

As a point to further enhance my skills in Python along with an excuse for practicing exploit development the Frampton tool was built to initially provide information and basic handling of Portable Executable files to identify ‘Code Caves’ for manual injection. There are numerous tools available online to perform these actions, but of course where is the fun in just using these as-is?


The Frampton tool, named for PEter Frampton (I don’t know why, it seemed funny at the time), has the basic functionality that you’d expect from a toolset like this, with a few more inclusions:

  • Identifying code caves to the specified size of the target shellcode
  • Disabling ASLR in the PE file automatically to handle certain features
  • An auto-XOR encoder to encode the shellcode in memory before injecting this to the output file
  • Multi-encoder to auto generate different XOR keys for N number of XOR loops.
  • x64 PE file handling, which I’m not sure that many other tools offer.


The tool is pretty straight forward; you specify the input PE file and optionally the shellcode to inject. If you don’t specify an input shellcode via the command line the default is to utilise a basic bind shell on TCP:4444.

If you don’t specify an output file, the default output is created with the input file name suffixed with ‘_backdoor.exe’.

When the tool is run with the encoder or multiple encoder options, a single or multiple XOR keys are auto-generated and the input shellcode is encoded before being injected into the new output file.

How it works

The steps behind the tool are fairly simple at a high level:

  • The tool uses the pefile module to read the ImageBase address.
  • Next, the entry point address of the PE file is stored via AddressOfEntryPoint.
  • Form here, the code cave minimum size is calculated, taking into account any necessary padding from the specified (or default) shellcode.
  • From this, if an encoder (or multiple iterations) is specified, then the minimum code cave size is adjusted based upon the estimated final size
  • If ASLR is enabled on the image, then this is automatically disabled for the new output file.

The PE file is then searched for a code cave. Essentially this is comrpised of:

  • Reading through the input file starting at the ImageBase.
  • Identifying the number of Section Headers within the file via NumberOfSections.
  • Looping through these section headers and identifying where there are numerous instances of null bytes.
  • Where there are sufficient null bytes for the size of the specified shellcode these are listed out.
  • When a sufficiently sized code cave is identified, the tool stores the VirtualAddress and raw address (PointerToRawData) of the code cave.

Next is the injection, which is only performed if the information argument is not specified (i.e. the default is to inject into a new file). This is handled as follows:

  • The new entry point for the backdoored file is then set as the Virtual Address as listed above. This saves time from trying to add JMPs or CALLs and recreating execution flow (although this is done, later).
    • Some magic is done in the background to handle ASLR and misaligned entrypoints. To be honest with you it’s been a while since I originally wrote this tool, so we’re learning this together at this point.
  • If an encoder, or a multi-encoder option is set, then the tool will generate the XOR key(s).
    • The input (or default) shellcode will then be XOR’d in memory using these keys.
    • To later use the PE file and have the XOR’d shellcode auto-decode in memory, the start and end addresses for each section loop are calculated based upon the size of the shellcode, number of keys, etc.
  • Once the final shellcode has been generated, the original program execution flow is restored by creating a JMP back to the original entry point address.
  • The output file is then written and can be executed as intended.

This post is licensed under CC BY 4.0 by the author.