Jektor – A Windows User-Mode Shellcode Execution Tool That Demonstrates Various Techniques That Malware Uses

This utility focuses on shellcode injection techniques to demonstrate methods that malware may use to execute shellcode on a victim system

  • Dynamically resolves API functions to evade IAT inclusion
  • Includes usage of undocumented NT Windows API functions
  • Supports local shellcode execution via CreateThread
  • Supports remote shellcode execution via CreateRemoteThread
  • Supports local shellcode injection via QueueUserAPC
  • Supports local shellcode injection via EnumTimeFormatsEx
  • Supports local shellcode injection via CreateFiber

AVvXsEjPUZh2bM19bMCKno 1keHzqqPnKYezjowGFMC2ewBdWzsbBM4bs3dPRE1v1xDxcUU8UYUab Smy9G3Y8i3a8MMxncLPM3kvnuLZfpOa3gBH2et1DJM8OEsjlnIkGomA2veDCXjR27kBLp w7bflqmkHWRbatOalXMtELeXdHAMqtO5kqGxDlw8knt4cw=w640 h142

 

Anti-virus detection?:

Pre-pending a set of NOPs to a Msfvenom XOR encrypted shellcode payload while using dynamic function address resolutions seems to bypass Windows Defender.

IAT Import Evasion

Jektor makes use of dynamic function address resolutions using LoadLibrary and GetProcessAddress to make static analysis more difficult.

Important functions such as VirtualAlloc are not directly called which makes debugging and dumping the shellcode through breakpoints more difficult.

Local shellcode execution via CreateThread

On Windows when you want to create a new thread for the current process you can call the CreateThread function, this is the most basic technique for executing malicious code or shellcode within a process. You can simply allocate a region of memory for your shellcode, move your shellcode into the allocated region, and then call CreateThread with a pointer to the address of the allocated region. When you call CreateThread you pass the lpStartAddress parameter which is a pointer to the application-defined function that will be executed by the newly created thread.

AVvXsEi5aCFiSkNy6dbLXcFZUdzQJ7KnBA 1QTHD2 jUkDd WYEw9M75sXelBgJ0qxAUsUasZyBQyt0q DPEpQD5Rt2ETwhHj7lMkk65NE7a2 foooMZAPgLa1H6M6ChhT02dQD4CS8luCbiIZgiHC8Qf2jpGUuiaVIIzAO4WBRphdnqxFJemfOrO5g9ClnjPQ=w640 h120
  1. Allocate a region of memory big enough for the shellcode using VirtualAlloc
  2. Move the globally defined shellcode buffer into the newly allocated memory region with memcpy/RtlCopyMemory
  3. Create a new thread that includes the base address of the allocated memory region with CreateThread
  4. Wait for the new thread to be created/executed with WaitForSingleObject to ensure the payload detonates

After the memory region for the shellcode payload is allocated as RWX and the payload is moved into it, you can easily discover this region of memory by looking for any region of memory in the process that is marked as RWX, then if you inspect it you can seen the shellcode payload was moved into it, highlighted below are the first five bytes of the shellcode payload that executes a calculator on the victim system.

AVvXsEg EdTGMKYV9pBxORo1L3MXsJw2H0liW0TgMqNRx1sVtkWTbrMtfG5L46vVfgyCI16 xm6gF9mmziuf5D5ZFIGsE0PIogCmRQnAeWhX0iSQRvayfzQlrBeGFGoVgToq7UObdUA7NtOw Li XMmUVEa0kVET6FHB4RLaysLZYvZHFpCWVg1OJeWyprZSSw=w640 h396

Hunting for RWX regions of memory is a quick way to identify potentially malicious activity on your system.

AVvXsEiIPWgZ2IELwpxKLe5Gdk Nk8KLLC0sAEExG6aEEGwnI1Zr2yr JNQJ6 ElfirO38UMtKr24JWY mumidrDXr OV4t9fFu7KuS11HAycfL6Nkx9fBPv 8pzSmupYchiWXvJ0t1oaGccH j238wlJ9PIYarg1 v4 qBbp YuTQ RXV 2CW9A89JMGHAxg=w640 h38

Remote shellcode execution via CreateRemoteThread

Another technique to create threads for shellcode execution is to call the CreateRemoteThread function, this will allow you to create threads remotely in another process. But the catch is that you will also want to allocate and write the shellcode payload into the remote process as well, since you’ll create a thread remotely that executes the payloads address that’s allocated within that process. In order to allocate the payload remotely, you’ll need to use the VirtualAllocEx function, this function is different from VirtualAlloc in that it can allocate memory regions in remote processes. To do this, Jektor creates a new process with the CREATE_NO_WINDOW flag set using CreateProcessW, this is used to spawn a new hidden notepad process. One the new process is spawned it remotely allocated memory in it and then uses WriteProcessMemory to write the shellcode payload into the allocated memory region. After this it calls CreateRemoteThread to execute the shellcode payload.

  1. Spawn a new process using CreateProcessW with CREATE_NO_WINDOW set
  2. Open a HANDLE to the newly spawed process by PID with OpenProcess and dwProcessId from PROCESS_INFORMATION
  3. Allocate memory remotely in the spawned process for the shellcode with VirtualAllocEx
  4. Write the shellcode payload into the allocated memory region with WriteProcessMemory
  5. Detonate the remotely created shellcode payload with CreateRemoteThread and the HANDLE from OpenProcess
AVvXsEglQ1tph6U1TBVz8AB wWiMp7unRmq2k8C7ebcnfwuc4W7Px1PUXtZzQZBohDGTDF4t96RGxkGVTb5uTQkj6t1cLm jYthz EB5xJq0q5pBDzOjUFs gar3f0I1ao8mA5P7bGXMMq5QTK9HhJRl22TSEeHWpcJm3Y0tByYyrcJs8zxiNkSHsQZxfIxkQ=w640 h198

Local shellcode execution via EnumTimeFormatsEx

  1. Allocate memory locally for the shellcode payload with VirtualAlloc
  2. Move the shellcode payload into the newly allocated region with memcpy/RtlCopyMemory
  3. Detonate the shellcode by passing it as the lpTimeFmtEnumProcEx parameter for EnumTimeFormatsEx
AVvXsEhAzCc4M0dnH4fFo1wMr79EN4Ya5iesvjZBOs 5Ie0R0fT1N9sTqlDGZZ25E9Vv7vitrmTva6ehhzdobRAnngVwFDx8sl38OEjtdY k9gwcSSPJjrVb9km3lR8V5SDnMIPzPT3No0NpkWhkCwrvE7 BkZnoSccrhyt1C4AfDWFuErZT4IhO1L9v5Q8vQ=w640 h62

Local shellcode execution via CreateFiber

  1. Get a HANDLE to the current thread using GetCurrentThread
  2. Convert the main thread to a Fiber using ConvertThreadToFiber
  3. Allocate memory for the shellcode payload with VirtualAlloc
  4. Copy the shellcode buffer into the newly allocated memory region with memcpy
  5. Create a new fiber with the base address of the allocated memory region as the lpStartAddress parameter for CreateFiber
  6. Detonate the shellcode by scheduling the fiber with SwitchToFiber
  7. Perform cleanup by deleting the created fiber with DeleteFiber
AVvXsEjioWHCd4s51R1Od gRiD9rOf2RvKViUG7AlJId2CiR8AarehigESaE59t4hglCsxSZ0aYFaYcPlwo NNJrMLsGyM47aeWmR6RqMiJFkFYMER7D6QKddtan1KioZ v73IxJyC7FqKLg 8tOqA PtaFT6Do2Yyfskb6lprz2FmQuE7fwQ CZuj3alXai7Q=w640 h112

Local shellcode execution via QueueUserAPC

  1. Allocate memory for the shellcode buffer with VirtualAlloc
  2. Get a handle to the current process with GetCurrentProcess
  3. Write the shellcode payload into the newly allocated memory region with WriteProcessMemory
  4. Get a handle to the current thread with GetCurrentThread
  5. Queue a new APC routine pass the address of the allocated memory region as the pfnAPC parameter to QueueUserAPC
  6. Trigger the shellcode payload by calling the undocumented NtTestAlert function which clears the APC queue for the current thread
  7. Perform cleanup by closing the handles to the current thread and current process

AVvXsEgmWrejjU2NkUTiJk5ZkkKLzUwvlLR41ouz5JlCV QqALe2QSptw4 NJBwL2NN ZtDA55q793gBD2rjseMjaUy2K5SjJuVcCcXBRF1C7BZqvcW3xsP3lvplYIP1ts443P2jIF4Ck63A3lb6l vJoryK8REQ0ThGsEUS9Rc60StNaiB0JjmRBzI098QnjQ=w640 h122

 

click here to read full Article

Read More on Pentesting Tools

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: