Malware Analysis Code injection identification [Malware Analysis]

Discussion in 'Malware Analysis' started by Opcode, Sep 20, 2017.

  1. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    Windows 10
    About the above post, someone told me about a PDF from CrowdStrike the other day after I looked into Shims in kernel-mode and made the above post. It is really handy as an educational resource and it helped me learn more about it, you can find it here:
    Andy Ful likes this.
  2. Opcode

    Opcode Level 18
    Content Creator

    Aug 17, 2017
    Windows 10
    NtProtectVirtualMemory information from my reverse-engineering notes on NTOSKRNL.

    1. NtProtectVirtualMemory (NTDLL) is called
    2. System call from NTDLL is performed
    3. KiSystemCallXx is invoked eventually -> eventually KiSystemServiceRepeat. The whole purpose of these routines is to locate the address of NtProtectVirtualMemory from the KeServiceDescriptorTable (and NtProtectVirtualMemory is not exported by NTOSKRNL therefore an Export Address Table Scan/MmGetSystemRoutineAddress won't work to find the address)
    4. MiMakeProtectionMask
    5. KiStackAttachProcess is called (non-exported variant of KeStackAttachProcess)
    6. Now the Windows Kernel is executing code under the context of the target process from within the NtProtectVirtualMemory routine.
    7. MmProtectVirtualMemory is called however depending on an conditional statement, another routine called VslDebugProtectSecureProcessMemory will be used instead
    8. KiUnstackDetachProcess (non-exported variant of KeUnstackDetachProcess) 9. Another conditional statement -> MiMakeProtectionMask

    The Process Handle (HANDLE) which is passed in will be referenced as an object (PEPROCESS). This is done via ObpReferenceObjectByHandleWithTag (non-exported). This is cleaned up with ObfDereferenceObjectWithTag at the end. The conditional statement regarding MmProtectVirtualMemory and VslDebugProtectSecureProcessMemory involves the PEPROCESS object, therefore I assume it's to do with a value found under the EPROCESS structure (which is an opaque structure therefore we cannot access it normally).

    LOBYTE(PreviousModeByte) = *(_BYTE )(MK_FP(GS, 392i64) + 0x232i64);
    That part of code is for checking the PreviousMode for the current thread (KPROCESSOR_MODE -> PreviousMode -> found under the ETHREAD structure which is also opaque and cannot be normally accessed). The PreviousModeByte variable gets the value from the PreviousMode field. The 0x232i64 is the offset for where the PreviousMode entry is for my environment, which would be: Base Address of the ETHREAD for the current thread + 0x232 (offset) = entry for PreviousMode destination in memory. As I've seen other places before, the PreviousMode controls whether user-mode or kernel-mode addresses can be used, because the Windows Kernel treats it as trust integrity level. Therefore, this restriction is enforced to prevent a User-Mode caller from using the Native API with a kernel-mode address. The PreviousMode is changed depending on OS version/patch update.

    Here's some notes from NtSuspendProcess notes I've made awhile back.
    1. Check the PreviousMode
    2. Reference by object from the HANDLE (acquire PEPROCESS from the HANDLE)
    3. If the PEPROCESS is successfully acquired (NTSTATUS == STATUS_SUCCESS) then call PsSuspendProcess.
    4. Cleanup the PEPROCESS object.
    5. Return the NTSTATUS returned by PsSuspendProcess.

    1. Setup the critical region
    2. Check the RundownProtect entry in the EPROCESS structure
    3. Enumerate the threads of the process with PsGetNextProcessThread
    4. For each thread, calls PsSuspendThread
    5. Release the rundown protection
    6. Leave critical region
    7. Return the NTSTATUS code

    1. KeSuspendThread

    1. KiSuspendThread
    Zhou He and Andy Ful like this.
  3. Andy Ful

    Andy Ful Level 21

    Dec 23, 2014
    Windows 10
    I think sometimes: why everything in Windows has to be so complicated. ;)
    Opcode likes this.