Exemplo n.º 1
0
    def find_instruction_length(self,address,num_instructions):
        """
        This is a helper function to assist in determining the size
        of a set of instructions. It's really just a fancy wrapper for
        the disasmForward* family of functions, but it aims to prevent 
        writing these while loops repeatedly in your scripts.
        
        @type    address:    DWORD
        @param   address:    The address of where to start the size calculation.
        @type    num_instructions:    Integer
        @param   num_instructions:    This is the number of instructions from the starting point you wish to include.
        
        @raise    mfx:        An exception is raised if this function fails.
        @rtype:   Integer
        @return:  Returns the size of the instructions as an integer.
        """
        
        # BoB: Get the size of the first 2 instructions
        count            = 1
        instruction_size = 0
        
        # You're being silly if you are using this function to a length
        # calculation. Use imm.disasm(address).opsize to get a length instead
        if num_instructions <= 1:
            raise mfx("[*] You silly goose, use imm.disasm(address).opsize for a single instruction length.")

        while count <= num_instructions:
    
            try:
                instruction_size += self.imm.disasmForwardSizeOnly(address,nlines=count-1).opsize
            
            except TypeError:
                raise mfx("[*] Obtaining instruction size failed. Please make sure this is a sane address.")
        
            count += 1

        return instruction_size 
Exemplo n.º 2
0
    def check_remote_debugger_present(self):
        """
        Patches the instructions in the beginning of the
        CheckRemoteDebuggerPresent() function call.
        
        @rtype: Boolean
        @return: True if the patch to CheckRemoteDebuggerPresent() succeeds.
        """
        func_address = self.imm.getAddress("kernel32.CheckRemoteDebuggerPresent")

        if func_address <= 0:
            self.imm.Log("[*] No CheckRemoteDebuggerPresent() function.")

        self.imm.Log("[*] Patching CheckRemoteDebuggerPresent.", address=func_address)

        # Patch instructions in to bypass the call
        patch_code = self.imm.Assemble(
            " \
            Mov   EDI, EDI                                    \n \
            Push  EBP                                         \n \
            Mov   EBP, ESP                                    \n \
            Mov   EAX, [EBP + C]                              \n \
            Push  0                                           \n \
            Pop   [EAX]                                       \n \
            Xor   EAX, EAX                                    \n \
            Pop   EBP                                         \n \
            Ret   8                                           \
        "
        )

        bytes_written = self.imm.writeMemory(func_address, patch_code)

        if bytes_written == 0:
            raise mfx("[*] Could not patch CheckRemoteDebuggerPresent()")

        return True
Exemplo n.º 3
0
    def zw_query_information_process(self):
        """
        This patches ntdll.ZwQueryInformationProcess to hide that
        there is a debugger present. This essentially patches the 
        ProcessDebugPort in the ProcessInformationClass parameter.
        
        @rtype:    Boolean
        @return:   Returns True if the patch was successful, False if it failed.
        """
        function_address = self.imm.getAddress("ntdll.ZwQueryInformationProcess")

        if function_address <= 0:
            self.imm.Log("[*] No ZwQueryInformationProcess to patch.")
            return True

        self.imm.Log("[*] Patching ntdll.ZwQueryInformationProcess.")

        is_patched = False

        instruction_length = self.patch_utils.find_instruction_length(function_address, 2)

        # Now let's test to see if the function has been patched already
        fake_code = (
            self.imm.readMemory(function_address, 1)
            + self.imm.Assemble("DD 0x12345678")
            + self.imm.readMemory(function_address + 5, 1)
        )

        if fake_code == self.imm.Assemble("Push 0x12345678\n Ret"):

            # It's been patched already
            is_patched = True

            # Find the address where the patch points to
            address = self.imm.readLong(function_address + 1)

            # Find the length of the two instructions
            instruction_length = self.patch_utils.find_instruction_length(address, 2)

        # If the function hasn't been patched already then
        # allocate a page for our detour code and write the
        # first two original instructions
        if is_patched == False:

            # Allocate our detour page
            stub_address = self.imm.remoteVirtualAlloc()

            # Write the instructions
            bytes_written = self.imm.writeMemory(
                stub_address, self.imm.readMemory(function_address, instruction_length)
            )

            if bytes_written < instruction_length:
                raise mfx("[*] ZwQueryInformation Patch failed - couldn't write to memory page.")

        patch_body = (
            " \
            CMP DWORD [ESP+8], 7        \n    \
            DB 0x74, 0x06               \n    \
                                        \n    \
            PUSH 0x%08x                 \n    \
            RET                         \n    \
                                        \n    \
            MOV EAX, DWORD [ESP+0x0C]   \n    \
            PUSH 0                      \n    \
            POP [EAX]                   \n    \
            XOR EAX, EAX                \n    \
            RET 14"
            % (function_address + instruction_length)
        )

        patch_body = self.imm.Assemble(patch_body)

        # Write the patch code after the first two original instructions
        bytes_written = self.imm.writeMemory(stub_address + instruction_length, patch_body)

        if bytes_written < len(patch_body):
            raise mfx("[*] ZwQueryInformationProcess - couldn't write primary patch code to memory.")

        # If it hasn't been patched already then write the detour
        # jmp as a PUSH/RET combo
        if is_patched == False:

            detour_jmp = self.imm.Assemble("PUSH 0x%08x\n RET" % stub_address)

            bytes_written = self.imm.writeMemory(function_address, detour_jmp)

            if bytes_written < len(detour_jmp):
                raise mfx(
                    "[*] ZwQueryInformationProcess - couldn't write the detour combo at original function address."
                )

        return True
Exemplo n.º 4
0
    def patch_peb(self, peb_flag=None):
        """
        Various patches for the PEB. Use the Flag
        variable to select particular fields in the 
        PEB that you wish to patch.
        
        @type  peb_flag:  String
        @param peb_flag:  (Optional) Specific flag you wish to patch. 
        Values can be one of (case IN-sensitive)::
        
        
            BeingDebugged
            ProcessHeap
            NtGlobalFlag
            LDR_DATA
        
          
        @rtype: Boolean
        @return:    Returns True if the patch was successful.
        """
        try:
            peb_address = self.imm.getPEBaddress()
            peb = self.imm.getPEB()
        except:
            raise mfx("[*] Could not obtain PEB address.")

        # Patch the IsDebugged member
        if peb_flag is None or peb_flag.lower() == "beingdebugged":
            offset = peb_address + 0x02
            self.imm.Log("[*] Patching PEB.BeingDebugged", address=offset)

            # Zero out the flag, BoB's original patch assembled a DB 0 into that position
            self.imm.writeMemory(offset, "\x00")

        # Patch the ProcessHeap member
        if peb_flag is None or peb_flag.lower() == "processheap":
            offset = self.imm.readLong(peb_address + 0x18) + 0x10
            self.imm.Log("[*] Patching PEB.ProcessHeap", address=offset)
            self.imm.writeMemory(offset, DWORD_ZERO)

        # Patch the NtGlobalFlag member
        if peb_flag is None or peb_flag.lower() == "ntglobalflag":
            offset = peb_address + 0x68
            self.imm.Log("[*] Patching PEB.NtGlobalFlag", address=offset)
            self.imm.writeMemory(offset, DWORD_ZERO)

        # JMS: Patch the PEB_LDR_DATA struct by replaciong 0xFEEEFEEE
        # with zeros
        if peb_flag is None or peb_flag.lower() == "ldr_data":

            # Grab the memory page where the LDR_DATA struct resides
            # dump it to dirty_memory, and then replace all 0xFEEEFEEE
            page = self.imm.getMemoryPagebyAddress(peb.Ldr[0])
            dirty_memory = page.getMemory()
            clean_memory = dirty_memory.replace("\xEE\xFE\xEE\xFE", "\x00\x00\x00\x00")

            bytes_written = self.imm.writeMemory(page.getBaseAddress(), clean_memory)

            if bytes_written == 0:
                raise mfx("[*] Could not write the memory page to patch PEB.LDR_DATA.")

        return True