Shield from DLL Injection

Posted by Hide­
2007.07.09 23:56 Security/Reversing

CreateRemoteThread(). SetWindowsHookEx(), SetThreadContext()을

이용한 DLL injecting 공격을 차단할 수 있다고 합니다.

Yet, this method only blocks out 80% of DLL-injecting tools that uses CreateRemoteThread(). Other method such as SetWindowsHookEx(), SetThreadContext() or code caving will work. That will take different approach to deal with.

No kernel is hurt during creation of this code. :)

; ======================================================================= ;
.model flat,stdcall
option casemap:none


includelib kernel32.lib

includelib user32.lib

        ; code signature for kernel32.BaseThreadStartThunk()
        Signature                 BYTE 033h, 0EDh, 053h, 050h, 06Ah, 000h, 0E9h
        ; 7C810659 >  33ED            XOR     EBP, EBP
        ; 7C81065B    53              PUSH    EBX
        ; 7C81065C    50              PUSH    EAX
        ; 7C81065D    6A 00           PUSH    0
        ; 7C81065F  ^ E9 E8AFFFFF     JMP     7C80B64C                ; kernel32.BaseThreadStart
        ; strings
        szBusted                        BYTE "Busted", 0
        szkernel32                        BYTE "kernel32.dll", 0
        szLoadLibraryA                        BYTE "LoadLibraryA", 0
        szFreeLibrary                        BYTE "FreeLibrary", 0
        szExitProcess                        BYTE "ExitProcess", 0
        ; address
        Addr_LoadLibraryA                DWORD ?
        Addr_FreeLibrary                DWORD ?
        Addr_ExitProcess                DWORD ?
        Addr_BaseThreadStart                DWORD ?
        Addr_BaseThreadStartThunk        DWORD ?
        ; you know
        hModule                                DWORD ?
        lpflOldProtect                        DWORD ?
        SigSeek_FindCode proc uses ebx ecx edx esi edi dwStart:DWORD, dwEnd:DWORD, lpSig:DWORD, dwSize:DWORD
                ; EBX = dwSize
                ; EDX = dwEnd - dwSize
                ; load the arguments into register
                mov ebx, dwSize
                mov edx, dwEnd
                sub edx, ebx
                ; scan for specified signature
                mov ecx, ebx
                mov esi, dwStart
                mov edi, lpSig
                        ; compare the string
                        repe cmpsb
                        .if zero?
                                ; found the signature, return the address
                                mov eax, ebx
                                sub eax, ecx
                                sub esi, eax
                                mov eax, esi
                                jmp @f
                        ; restore ECX, ESI, EDI registers
                        mov eax, ebx
                        sub eax, ecx
                        sub esi, eax
                        sub edi, eax
                        mov ecx, ebx
                        ; move to next byte
                        add esi, 1
                .until (esi == edx)
                ; return FALSE
                xor eax, eax
        SigSeek_FindCode endp
        Does_Something_Smell_Fishy proc lpStartAddress:DWORD
                LOCAL lpMemInfo        : MEMORY_BASIC_INFORMATION
                ; is the start address pointing to some fishy address ?
                mov eax, lpStartAddress
                .if (eax == Addr_LoadLibraryA) || (eax == Addr_FreeLibrary) || (eax == Addr_ExitProcess)
                        ; obviously suspicious
                        mov eax, TRUE
                        jmp @f
                ; do a check on memory allocation type
                invoke VirtualQuery, lpStartAddress, addr lpMemInfo, sizeof lpMemInfo
                .if !(lpMemInfo.lType & MEM_IMAGE)
                        ; hey, this thread isn't pointing to any loaded image, hmmmm
                        mov eax, TRUE
                        jmp @f
                ; no fish is found here
                xor eax, eax
        Does_Something_Smell_Fishy endp
        Hook_BaseThreadStartThunk proc
                LOCAL lParam
                LOCAL lpStartAddress
                ; EAX = lpStartAddress
                ; EBX = lParam
                ; save the parameters
                mov lpStartAddress, eax
                mov lParam, ebx
                ; does something smell fishy ?
                invoke Does_Something_Smell_Fishy, lpStartAddress
                .if (eax != FALSE)
                        ; yeah, it smells
                        invoke MessageBox, NULL, addr szBusted, NULL, MB_OK
                        ; kill this rogue thread
                        invoke ExitThread, NULL
                        ; jump to kernel32.BaseThreadStart()
                        xor ebp, ebp
                        push lParam
                        push lpStartAddress
                        push NULL
                        jmp Addr_BaseThreadStart
        Hook_BaseThreadStartThunk endp
        ; this wouldn't need any comments, eh?
        invoke GetModuleHandle, addr szkernel32
        mov hModule, eax
        ; scan for kernel32.BaseThreadStartThunk() signature from [base address] to [base address + 20000h] because it is not exported
        ; TODO: retrieve image size from PE, instead of using fixed image size value
        mov ebx, eax
        invoke SigSeek_FindCode, ebx, addr [ebx+20000h], addr Signature, sizeof Signature
        mov Addr_BaseThreadStartThunk, eax
        ; extract the address of kernel32.BaseThreadStart() from jmp instruction
        ; destination = code location + jump offset + 5
        mov ebx, [eax+7]
        add ebx, eax                ; / code location
        add ebx, 6                        ; \
        add ebx, 5
        mov Addr_BaseThreadStart, ebx
        ; hook kernel32.BaseThreadStartThunk() function
        invoke VirtualProtect, Addr_BaseThreadStartThunk, 5, PAGE_EXECUTE_READWRITE, addr lpflOldProtect
        .if (eax != NULL)
                invoke GetCurrentProcess
                invoke FlushInstructionCache, eax, Addr_BaseThreadStartThunk, 5
                mov edi, Addr_BaseThreadStartThunk
                mov eax, offset Hook_BaseThreadStartThunk
                sub eax, edi
                sub eax, 5
                mov  byte ptr [edi+0], 0E9h                ; jmp short
                mov dword ptr [edi+1], eax
                invoke VirtualProtect, Addr_BaseThreadStartThunk, 5, lpflOldProtect, addr lpflOldProtect
        ; get some function address
        invoke GetProcAddress, hModule, addr szLoadLibraryA
        mov Addr_LoadLibraryA, eax
        invoke GetProcAddress, hModule, addr szFreeLibrary
        mov Addr_FreeLibrary, eax
        invoke GetProcAddress, hModule, addr szExitProcess
        mov Addr_ExitProcess, eax
        ; we will see
        invoke Sleep, INFINITE
end start
; ======================================================================= ;


다른 사람들이 많이 읽은 글

'Security > Reversing' 카테고리의 다른 글

GameGuard Nop 처리 부분  (1) 2007.07.09
How to way Bypass CRC Check  (0) 2007.07.09
Shield from DLL Injection  (0) 2007.07.09
점프명령어 쉽게외우기  (0) 2007.03.18
언패커모음사이트  (0) 2007.03.09
Bypass REV 939  (0) 2007.03.08
이 댓글을 비밀 댓글로

티스토리 툴바