1. SetThreadContext를 이용한 Dll Injection 검사
: SetThreadContext를 이용하여 Dll Injection을 하기 위해서는 Code Injection을 해야 하므로
Code Injection시에는 메모리 속성을 MEM_PRIVATE로 변경하는 것을 이용하여 검출하는 방식.
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(Caller, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if(mbi.Type == MEM_PRIVATE) return false;
2. CreateRemoteThread를 이용한 Dll Injection 검사
: CreateRemoteThread() API함수를 이용한 Dll Inejction을 검출하는 방법은 두가지 이다.
첫째로 , 결국LoadLibraryA() 함수를 호출하는 함수 LdrLoadDll() 함수를 후킹하는 것이다.
왜냐하면 어차피 유저레벨에서 LoadLlibrary함수류가 최종적으로 호출하는 함수가 바로 LdrLoadDll()함수이기 때문에 해당 LdrLoadDll() 함수가 호출되면 쓰레드의 stack base point를 얻어서 쓰레드로 호출되는 코드의 주소를 얻어올 수 있다. (해당 주소는 항상 stack의 가장 위에서 두번째 혹은 세 번째에 존재한다) .
PDWORD psb;
__asm
{
push eax
mov eax, fs:[0x18]
mov eax, [eax+0x4]
mov psb, eax
pop eax
}
이렇게 스택베이스포인터 구하고,
PVOID pvAddr = *(psb-3) ? (PVOID)*(psb-3) : (PVOID)*(psb-2);
if(pvAddr ==LoadLibraryA || pvAddr==LoadLibraryW) return false;
이렇게 해서 LoadLibraryA/W() 의 주소와 비교하여, 맞는지 판단한다.
쓰레드로 호출할 함수는 인자를 하나만 받을 수 있기 때문에 LoadLibraryA() 함수와 LoadLibraryW() 함수 두 함수만 체크하면 된다.
두번째 방법 또한 첫번째 방법과 비슷한 방법인데, CreateRemoteThread()함수를 호출해주는 함수인 BaseThreadStartThunk()의 호출 여부를 확인하는 것이다.
BaseThreadStartThunk()의 ThreadProc호출시에 caller Address의 호출되는 코드 위치가 push eax(0x50)인것을 이용하여 검출하는 방식이다.
LPBYTE pbCaller = (LPBYTE) Caller;
if(*pbCaller == (BYTE)0x50 ) return false;
3. SetWindowsHookEx를 이용한 Dll Injection 검사
: SetWindowsHookEx()는 GUI Thread를 가진 프로세스에 DLL을 삽입하는함수이다.
SetWindowsHookEx()함수를 호출하면 User32.dll 의 ClientLoadLibrary()함수가 호출된다. ClientLoadLibrary()함수는 LoadLibraryExW()함수를 최종적으로 호출하게 된다.
따라서 LoadLibraryExW()함수를 후킹하여 Caller의 주소가 User32.dll의 주소범위 안에 있는지(user32.dll 에서 호출되는 지 )확인하여 다음과 같이 검출하게 된다.
VirtualQuery(Caller, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
LPBYTE pbCaller = (LPBYTE) Caller;
if(((DWORD)pbCaller >= dwUser32Start && (DWORD)pbCaller < dwUser32End) ||
*(pbCaller-7) == (BYTE)0x1C)
{
AntiCodeError += 24;
return false;
}
위에서 사용된 User32.dll 의 주소 범위를 구하는 것은 아래 와 같다.
DWORD dwUser32Start, dwUser32End;
HMODULE hDllUser32;
hDllUser32 = GetModuleHandle( TEXT("user32") );
dwUser32Start = (DWORD)hDllUser32;
PIMAGE_DOS_HEADER idh = (PIMAGE_DOS_HEADER)hDllUser32;
PIMAGE_NT_HEADERS inh = (PIMAGE_NT_HEADERS)(dwUser32Start + idh->e_lfanew);
dwUser32End ^= (dwUser32Start ^ dwUser32End);
dwUser32End += inh->OptionalHeader.SizeOfImage;
'Reversing' 카테고리의 다른 글
PE구조파일 Image Base Address 쉽게 얻자 (0) | 2012.06.11 |
---|---|
ANTI D3D9 hooking (0) | 2012.05.17 |
[ANTI Reversing] BegingDebuged 설명 (0) | 2012.04.24 |
PEB구조체 시작 주소 MS Windows 버전별 (0) | 2012.04.24 |
PEB 구조체 (0) | 2012.04.24 |