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. :)
; ======================================================================= ;
.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib
.data
; 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
.data?
; address
Addr_LoadLibraryA DWORD ?
Addr_FreeLibrary DWORD ?
Addr_ExitProcess DWORD ?
Addr_BaseThreadStart DWORD ?
Addr_BaseThreadStartThunk DWORD ?
; you know
hModule DWORD ?
lpflOldProtect DWORD ?
.code
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
.repeat
; 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
.endif
; 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
@@:
ret
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
.endif
; 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
.endif
; no fish is found here
xor eax, eax
@@:
ret
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
.else
; jump to kernel32.BaseThreadStart()
xor ebp, ebp
push lParam
push lpStartAddress
push NULL
jmp Addr_BaseThreadStart
.endif
Hook_BaseThreadStartThunk endp
start:
; 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
.endif
; 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
ret
end start
; ======================================================================= ;
'Security' 카테고리의 다른 글
GameGuard Nop 처리 부분 (1) | 2007.07.09 |
---|---|
How to way Bypass CRC Check (0) | 2007.07.09 |
XSS (0) | 2007.06.14 |
KISA 2007 보고서 (0) | 2007.06.14 |
Anti Game Hacking 의 원리, 그리고 Codes (0) | 2007.04.01 |