wbenny

main.cpp

Feb 1st, 2019
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.31 KB | None | 0 0
  1. #include <ntdll_windows.h>
  2. #include <ntdll.h>
  3.  
  4. // extern "C"
  5. // UINT_PTR
  6. // NTAPI
  7. // MwGenericCall(
  8. //   ULONG SyscallNumber,
  9. //   ULONG ArgumentCount,
  10. //   va_list ArgumentList
  11. //   );
  12.  
  13. #pragma section(".text")
  14. __declspec(allocate(".text"))
  15. UCHAR MwSyscallCode[] = {             //
  16.                                   // ;
  17.                                   // ; Save r12 to the shadow space.
  18.                                   // ; This register will be held as a temporary
  19.                                   // ; stack pointer for the syscall.
  20.                                   // ;
  21.   0x4C, 0x89, 0x64, 0x24, 0x08,   // mov     qword ptr [rsp + 8], r12
  22.                                   //
  23.                                   // ;
  24.                                   // ; eax = SyscallNumber
  25.                                   // ; r10 = ArgumentCount
  26.                                   // ; r11 = ArgumentList
  27.                                   // ; r12 = ArgumentList - sizeof(PVOID)
  28.                                   // ;       (space for return address)
  29.                                   // ;
  30.                                   //
  31.   0x8B, 0xC1,                     // mov     eax,  ecx
  32.   0x44, 0x8B, 0xD2,               // mov     r10d, edx
  33.   0x4D, 0x8B, 0xD8,               // mov     r11,  r8
  34.   0x4D, 0x8D, 0x63, 0xF8,         // lea     r12,  qword ptr [r11 - 8]
  35.                                   //
  36.                                   // ;
  37.                                   // ; Assign first 4 arguments (rcx, rdx, r8, r9)
  38.                                   // ; from the ArgumentList.
  39.                                   // ;
  40.   0x41, 0x83, 0xFA, 0x01,         // cmp     r10d, 1
  41.   0x49, 0x0F, 0x43, 0x0B,         // cmovae  rcx, qword ptr [r11 +  0]
  42.                                   //
  43.   0x41, 0x83, 0xFA, 0x02,         // cmp     r10d, 2
  44.   0x49, 0x0F, 0x43, 0x53, 0x08,   // cmovae  rdx, qword ptr [r11 +  8]
  45.                                   //
  46.   0x41, 0x83, 0xFA, 0x03,         // cmp     r10d, 3
  47.   0x4D, 0x0F, 0x43, 0x43, 0x10,   // cmovae  r8,  qword ptr [r11 + 16]
  48.                                   //
  49.   0x41, 0x83, 0xFA, 0x04,         // cmp     r10d, 4
  50.   0x4D, 0x0F, 0x43, 0x4B, 0x18,   // cmovae  r9,  qword ptr [r11 + 24]
  51.                                   //
  52.                                   // ;
  53.                                   // ; The syscall handler expects the first
  54.                                   // ; parameter in the r10 register.
  55.                                   // ;
  56.   0x4C, 0x8B, 0xD1,               // mov     r10, rcx
  57.                                   //
  58.                                   // ;
  59.                                   // ; Stack pivot, syscall, restore stack.
  60.                                   // ;
  61.   0x4C, 0x87, 0xE4,               // xchg    r12, rsp
  62.   0x0F, 0x05,                     // syscall
  63.   0x4C, 0x87, 0xE4,               // xchg    r12, rsp
  64.                                   //
  65.                                   // ;
  66.                                   // ; Restore r12 register from the shadow space.
  67.                                   // ;
  68.   0x4C, 0x8B, 0x64, 0x24, 0x08,   // mov     r12, qword ptr [rsp + 8]
  69.                                   //
  70.   0xC3,                           // retn
  71. };                                //
  72.  
  73. typedef UINT_PTR (NTAPI* GENERIC_CALL_FN)(
  74.   _In_ ULONG SyscallNumber,
  75.   _In_ ULONG ArgumentCount,
  76.   _In_ va_list ArgumentList
  77.   );
  78.  
  79. GENERIC_CALL_FN MwGenericCall = (GENERIC_CALL_FN)&MwSyscallCode;
  80.  
  81. static const unsigned char ASM_MOV_EAX_IMM = 0xb8; // followed by DWORD
  82. static const unsigned char ASM_RET = 0xc3;
  83. static const unsigned char ASM_MOV_R10_RCX[] = { 0x4c, 0x8b, 0xD1 };
  84. static const unsigned char ASM_SYSCALL[] = { 0x0f, 0x05 };
  85.  
  86. static const unsigned char ASM_SYSCALL_STUB[] = {
  87.   0x4c, 0x8b, 0xD1, // mov r10, rcx
  88.   0xb8              // mov eax, imm32 - follows DWORD
  89. };
  90.  
  91. NTSTATUS
  92. NTAPI
  93. MwDisasmGetSyscallNumber(
  94.   VOID* FunctionAddress,
  95.   ULONG* SyscallNumber
  96.   )
  97. {
  98.   NTSTATUS Status = STATUS_UNSUCCESSFUL;
  99.  
  100.   if ((*(PULONG)FunctionAddress) == (*(PULONG)ASM_SYSCALL_STUB))
  101.   {
  102.     *SyscallNumber = *(ULONG*)((BYTE*)FunctionAddress + sizeof(ASM_SYSCALL_STUB));
  103.  
  104.     Status = STATUS_SUCCESS;
  105.   }
  106.  
  107.   return Status;
  108. }
  109.  
  110. NTSTATUS
  111. NTAPI
  112. MwGetFunctionAddress(
  113.   VOID* ImageBase,
  114.   const CHAR* FunctionName,
  115.   VOID** FunctionAddress,
  116.   ULONG* SyscallNumber
  117.   )
  118. {
  119.   TEB* Teb = NtCurrentTeb();
  120.  
  121.   LIST_ENTRY* ModuleListHead = &Teb->ProcessEnvironmentBlock->Ldr->InLoadOrderModuleList;
  122.   LIST_ENTRY* ModuleListNextEntry;
  123.  
  124.   BYTE* NtdllBase;
  125.  
  126.   for (
  127.     ModuleListNextEntry = ModuleListHead;
  128.     ModuleListNextEntry->Flink != ModuleListHead;
  129.     ModuleListNextEntry = ModuleListNextEntry->Flink
  130.     )
  131.   {
  132.     LDR_DATA_TABLE_ENTRY* LdrEntry = (LDR_DATA_TABLE_ENTRY*)ModuleListNextEntry->Flink;
  133.     if (!wcscmp(LdrEntry->BaseDllName.Buffer, L"ntdll.dll"))
  134.     {
  135.       NtdllBase = (BYTE*)LdrEntry->DllBase;
  136.       break;
  137.     }
  138.   }
  139.  
  140.   IMAGE_DOS_HEADER* DosHeader = (IMAGE_DOS_HEADER*)NtdllBase;
  141.   IMAGE_NT_HEADERS* NtHeader = (IMAGE_NT_HEADERS*)(NtdllBase + DosHeader->e_lfanew);
  142.   IMAGE_DATA_DIRECTORY* ExportDataDirectory = (IMAGE_DATA_DIRECTORY*)&NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  143.   IMAGE_EXPORT_DIRECTORY* ExportDirectory = (IMAGE_EXPORT_DIRECTORY*)(NtdllBase + ExportDataDirectory->VirtualAddress);
  144.  
  145.   DWORD* FunctionPtrRvaArray = (DWORD*)(NtdllBase + ExportDirectory->AddressOfFunctions);
  146.   DWORD* FunctionNameRvaArray = (DWORD*)(NtdllBase + ExportDirectory->AddressOfNames);
  147.   USHORT* FunctionOrdinalRvaArray = (USHORT*)(NtdllBase + ExportDirectory->AddressOfNameOrdinals);
  148.  
  149.   int FunctionNameRvaArraySize = ExportDirectory->NumberOfNames;
  150.  
  151.   CHAR* ExportFunctionName;
  152.   VOID* ExportFunctionPtr;
  153.  
  154.   for (int i = 0; i < FunctionNameRvaArraySize; i++)
  155.   {
  156.     ExportFunctionName = (CHAR*)(NtdllBase + FunctionNameRvaArray[i]);
  157.     ExportFunctionPtr = (VOID*)(NtdllBase + FunctionPtrRvaArray[FunctionOrdinalRvaArray[i]]);
  158.  
  159.     if (!strcmp(ExportFunctionName, FunctionName))
  160.     {
  161.       MwDisasmGetSyscallNumber(ExportFunctionPtr, SyscallNumber);
  162.       *FunctionAddress = ExportFunctionPtr;
  163.  
  164.       return STATUS_SUCCESS;
  165.     }
  166.   }
  167.  
  168.   return STATUS_UNSUCCESSFUL;
  169. }
  170.  
  171. NTSTATUS
  172. NTAPI
  173. MwCallNtdll(
  174.   const CHAR* FunctionName,
  175.   ULONG ArgumentCount,
  176.   ...
  177.   )
  178. {
  179.   VOID* FunctionAddress;
  180.   ULONG SyscallNumber;
  181.   MwGetFunctionAddress(NULL, FunctionName, &FunctionAddress, &SyscallNumber);
  182.  
  183.   va_list ArgumentList;
  184.   va_start(ArgumentList, ArgumentCount);
  185.  
  186.   UINT_PTR Result = MwGenericCall(SyscallNumber, ArgumentCount, ArgumentList);
  187.  
  188.   va_end(ArgumentList);
  189.  
  190.   return (NTSTATUS)Result;
  191. }
  192.  
  193. //
  194. // Variadic macro rape.
  195. //
  196.  
  197. #define MW_MACRO_EVAL(...)                                                    __VA_ARGS__
  198. #define MW_MACRO_EXPAND(expr)                                                 expr
  199. #define MW_VA_NUM_ARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...)  N
  200. #define MW_VA_NUM_ARGS(...)                                                   MW_MACRO_EXPAND(MW_VA_NUM_ARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
  201.  
  202. #define MW_CALL_WITH_NUM_ARGS(FunctionName, ArgumentCount, ...)               MwCallNtdll(FunctionName, ArgumentCount, __VA_ARGS__)
  203.  
  204. #define MW_CALL_VA_STR(FunctionName, ...)                                     MW_CALL_WITH_NUM_ARGS(FunctionName, MW_VA_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
  205. #define MW_CALL_VA(FunctionName, ...)                                         MW_CALL_WITH_NUM_ARGS(#FunctionName, MW_VA_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
  206. #define MW_CALL_STR(FunctionName, Args)                                       MW_CALL_VA_STR(FunctionName,  MW_MACRO_EVAL Args)
  207. #define MW_CALL(FunctionName, Args)                                           MW_CALL_VA_STR(#FunctionName, MW_MACRO_EVAL Args)
  208.  
  209. #define NtCall MW_CALL
  210.  
  211. void NtMain()
  212. {
  213.   NTSTATUS Status;
  214.  
  215.   HANDLE SectionHandle;
  216.   LARGE_INTEGER MaximumSize;
  217.   MaximumSize.QuadPart = 4096;
  218.   Status = NtCall(NtCreateSection, (&SectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL));
  219.  
  220.   PVOID BaseAddress = NULL;
  221.   SIZE_T ViewSize = 4096;
  222.   Status = NtCall(NtMapViewOfSection, (SectionHandle, NtCurrentProcess(), &BaseAddress, 0, 4096, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE));
  223.  
  224.   RtlCopyMemory(BaseAddress, "HELLO", 6);
  225.   NtTestAlert();
  226. }
Advertisement
Add Comment
Please, Sign In to add comment