dll injection 조사 3.

자료조사/리버싱, 시스템 2015. 7. 23. 01:19

4. PE 헤더를 조작하는 방식.


프로그램 자체의 헤더를 수정하여 dll을 포함하도록 하는 방법이다.

PE View와 Hex Editor 라는 툴을 사용해서 수정할 수 있다.

프로그램의 빈 공간을 찾거나 만들어서 IDT(Import Directory Table)을 수정하여 새로운 dll을 추가한다.

IDT 구조체는 IID(Image Import Descriptor)의 구조체로 되어있으며 여기에 새로운 구조체를 추가하는 방식이다.

이 방법을 사용하기 위해서는 기본적으로 PE 헤더에 대한 이해가 필요할 듯 하다.

RVA와 offset에 관한 내용이나 BOUND_IMPORT_TABLE과 관련된 문제, IID의 구성 등 여러가지 부분에 추가적인 공부가 필요할 듯 하다.

'자료조사 > 리버싱, 시스템' 카테고리의 다른 글

dll injection 추가  (0) 2015.07.25
dll injection 조사 2  (0) 2015.07.23
dll injection 조사 1  (0) 2015.07.22
Win api를 이용한 gui 개발  (0) 2015.07.16
Tags
Social

dll injection 조사 2

자료조사/리버싱, 시스템 2015. 7. 23. 00:56

2.AppInit_DLLs를 이용한 방법.


윈도우에서 기본으로 제공하는 레지스트리 키 AppInit_DLLs를 사용하는 방법이다.

regedit을 이용하여 AppInit_DLLs의 값에 원하는 dll의 주소를 넣어주고 재부팅하면 윈도우에서 모든 프로세스에 해당 dll을 inject시켜준다.


3. SetWindowsHookEx()를 사용하는 방법.


윈도우에서 제공하는 etWindowsHookEx() 함수는 프로세스간의 메세지를 후킹하는 기능을 한다.

이 함수를 이용해서 dll injection을 할 수 있다.


----------------------------------------------------------------------------

from:http://nocode.tistory.com/5


Microsoft에서는 프로세스간의 주고 받는 메세지를 후킹할 수 있는 함수를 제공한다.
바로 SetWindowsHookEx()함수이다. 이 함수를 통해 DLL을 특정 프로세스나 모든 프로세스에 Injection할 수 있다.그리고 User-mode(ring 3)에서 동작하는 Keylogger들 대부분이 이 함수를 사용하여 구현된다.(SetWindowsHookEx()함수를 통해 후킹(Hooking)을 할 경우 전역 후킹이 간단하므로 많이 사용한다.)

먼저 SetWindowsHookEx()함수의 원형부터 알아보자.
(MSDN에 있는 내용이다.)

HHOOK SetWindowsHookEx(
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);


첫번째 파라메터인 idHook 변수는 후킹 하고자 하는 메세지의 ID라고 할 수 있다. WH_GETMESSAGE, WH_KEYBOARD 등 다양한 메세지가 있다.(MSDN 참조)
idHook 파라메터에 지정된 값의 이벤트(메세지)가 발생할 경우 훅 프로시저(lpfb 파라메터에 설정된)가 동작하게 된다. 훅 프로시저는 Injection할 DLL(앞으로 Injected.dll이라 부르겠다)에 지정되어 있어야한다.

/* Injected.dll */
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 /* 원하는 코드 삽입 */
 return CallNextHookEx(0, nCode, wParam, lParam);
};


마지막에 CallNextHookEx()함수를 호출한 이유는 훅 체인에 있는 다른 훅 프로시저가 해당 메세지를 사용할 수도 있기때문이다. 예를들면 키보드메세지를 후킹하여 Keylogger를 만들었다고 하면 해당 메세지를 후킹 후 로깅을 하고 CallNextHookEx()함수를 통해 처리를 하지 않고 그냥 끝내 버린다면 들통나버릴것이다.

두번째 파라메터는 lpfn이다. 이 파라메터에는 Injected.dll에 지정된  훅 프로시저의 주소값을 지정한다.만약 IdHook에 WH_KEYBOARD를 지정하여 후킹 할경우 해당 훅 프로시저는 KeyboardProc이다. 주소 값을 지정해줘야하는데 하드코딩하여 지정해 줄 수 있지만 LoadLibrary()함수와 GetProcAddress를 이용하여 Injected.dll의 훅 프로시저의 주소를 구할 수 있다.

/* Injector.c */
HMODULE hDll;
unsigned long KeyboardProcAddr;

hDll = LoadLibrary("injected.dll");
KeyboardProcAddr = GetProcAddress(hDll, "KeyboardProc"); 


다음으로 세번째 파라메터인 hMod를 보자. hMod는 DLL의 핸들(Handle)을 지정해야한다.여기에선 Injected.dll의 핸들을 지정해주면 된다.
이미 Injector.c에서 LoadLibrary("Injected.dll"); 통해 핸들을 얻었으므로 hDll변수를 사용하면 된다.

네번째 파라메터 dwThreadId는 후킹할 프로세스 즉 Injected.dll을 삽입할 스레드(Thread)의 ID이다. PID라고 하며 해당 파라메터에 0을 지정하면 모든 스레드에 훅(Hook)을 한다는 의미로 전역 훅을 할 수 있다. 특정 스레드에 Injection을 하려고 한다면 "작업관리자"를 통해 PID를 얻어 하드코딩하거나 아래와 같은 방법으로 PID를 얻어 사용할 수 있다.

/* 전역 훅 */
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, 0)

/* 지역 훅*/
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, GetCurrentThreadID());


'자료조사 > 리버싱, 시스템' 카테고리의 다른 글

dll injection 추가  (0) 2015.07.25
dll injection 조사 3.  (0) 2015.07.23
dll injection 조사 1  (0) 2015.07.22
Win api를 이용한 gui 개발  (0) 2015.07.16
Tags
Social

dll injection 조사 1

자료조사/리버싱, 시스템 2015. 7. 22. 23:16

1.CreateRemoteThread를 이용한 방법.


dll을 로드시키기 위해 LoadLibrary를 사용할 수 없어서 CreateRemoteThread를 이용하는 방법이다.

windows에서는 API를 호출하도록 하는 API 제공하지 않는다고 한다.

그래서 새로운 스레드를 생성하면서 스레드 함수 주소로 LoadLibrary함수의 주소를 전달하고 그 파라미터 값으로 injection 하려는 dll파일의 경로를 전달하는 방식이다.


전체적인 진행은 대략 이러하다.


1. dwPID를 이용하여 대상 프로세스의 핸들을 구한다.

2. 대상 프로세스의 메모리에 dll의 경로를 넣기 위한 공간을 할당한다.

3. 할당받은 공간에 dll의 경로를 입력시킨다.

4. LoadLibraryA함수의 주소를 구한다.

5. CreateRemoteThread 함수를 사용하여 LoadLibraryA함수를 실행시킨다.


특이점: 

- 다른 프로세스의 메모리 공간에 접근하기 위해서는 Debug API에서 제공하는 함수들을 사용하면 된다.

  VirtualAllocEx(), VirtualFreeEx(), WriteProcessMemory(), ReadProcessMemory 등이 있다.

- 내가 이해한게 맞다면 LoadLibraryA()함수는 kernel32.dll에 들어있는 듯 하다. 그리고 이 dll은 모든 프로세스  에서 같은 주소에 위치하기 때문에 이를 이용해서 LoadLibraryA()함수의 주소를 구할 수 있다.

- 구한 API의 주소를 가지고 직접 호출시키는 API를 윈도우에서 제공하지 않으므로 새로운 스레드를 생성하면  서 스레드 함수 시작주소로 LoadLibraryA()함수의 주소를 전달하고 파라미터 주소로 inject하려는 dll의 주소를   전달한다.


--------------------------------예제-----------------------------------

from:revercore.com


#include "stdio.h"

#include "windows.h"

#include "tlhelp32.h"


#define DEF_PROC_NAME ("notepad.exe")

#define DEF_DLL_PATH ("c:\\work\\myhack.dll")


DWORD FindProcessID(LPCTSTR szProcessName);

BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName);


int main(int argc, char* argv[])

{

DWORD dwPID = 0xFFFFFFFF;

// find process

dwPID = FindProcessID(DEF_PROC_NAME);

if( dwPID == 0xFFFFFFFF )

{

printf("There is no <%s> process!\n", DEF_PROC_NAME);

return 1;

}


// inject dll

InjectDll(dwPID, DEF_DLL_PATH);


return 0;

}


DWORD FindProcessID(LPCTSTR szProcessName)

{

DWORD dwPID = 0xFFFFFFFF;

HANDLE hSnapShot = INVALID_HANDLE_VALUE;

PROCESSENTRY32 pe;


// Get the snapshot of the system

pe.dwSize = sizeof( PROCESSENTRY32 ); // 296d (128h)

hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL ); // ProcessID = 0


// find process

Process32First(hSnapShot, &pe);

do

{

if(!_stricmp(szProcessName, pe.szExeFile))

{

dwPID = pe.th32ProcessID;

break;

}

}

while(Process32Next(hSnapShot, &pe));


CloseHandle(hSnapShot);


return dwPID;

}


BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)

{

HANDLE hProcess, hThread;

LPVOID pRemoteBuf;

DWORD dwBufSize = lstrlen(szDllName) + 1;

LPTHREAD_START_ROUTINE pThreadProc;


if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )

return FALSE;


pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);


WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);


pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");

hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);

WaitForSingleObject(hThread, INFINITE);


CloseHandle(hThread);

CloseHandle(hProcess);


return TRUE;

'자료조사 > 리버싱, 시스템' 카테고리의 다른 글

dll injection 추가  (0) 2015.07.25
dll injection 조사 3.  (0) 2015.07.23
dll injection 조사 2  (0) 2015.07.23
Win api를 이용한 gui 개발  (0) 2015.07.16
Tags
Social

Win api를 이용한 gui 개발

자료조사/리버싱, 시스템 2015. 7. 16. 17:24

윈도우 창을 하나 띄우고 두개의 버튼에 하나는 메세지박스, 하나는 계산기를 띄우는 과제


api를 공부하면서 어려웠던 점은 api만이 가지는 독특한 자료형들이 많다는 점과 그 자료형들 사이에 호환이 잘 안된다는 점이었다.

그부분에 관한 내용을 정리하자면.


1.과거 win32 api에서 쓰던 LPCSTR과 LPCWSTR이 호환이 되지 않는 경우, char 또는 const char와 wchar_t가 호환이 되지 않는 문제가 있었다.


프로젝트 우클릭 , 속성에서 멀티바이트 문자열 사용으로 대부분 해결할 수 있는 것 같다.

하지만 어째서인지 내 개발환경에서는 실패..


과거의 책이나 블로그에 있는 내용들은 CreateWindow 등 함수에서 LPCSTR자료형을 상정하고 쓰여져 있는 듯 하다. 때문에 실제 LPCWSTR을 사용하는 개발환경에서 호환이 되지 않는 경우가 많았다.


변수를 선언할 때 LPCWSTR로 바꿔주고 ""안에 들어있는 const char 앞에 L 매크로를 붙여 쉽게 LPCWSTR로 변환할 수 있었다.


//LPCWSTR과 wchar_t는 비슷한 개념인 것 같다.



두번째로 발생한 문제는 계산식들과 정답 역시 double, int, char등 여러가지 형태로 나누어져 있는데 TextOut함수를 이용하여 출력하기 위해서는 이들을 모두 LPCWSTR형태로 바꾸어줘야 하는 문제였다.


itoa, strcat을 이용하여 계산식을 문자열 형태로 묶는것은 간단하게 해결이 되었으나 여기서부터가 더 끔찍했다.


mbstowcs함수는 const char* -> LPCWSTR형태밖에 지원하지 않는다. 사실 char* 형태를 넣어도 에러가 나지는 않는다. 그래서 그냥 사용하려고 했는데... TextOut을 이용해 출력한 녀석을 지우기 위해 새로운 char*을 이용하자 문제가 일어났다. 스텍이 오염되었다는 것이다. 한번은 되고 왜 두번은 안되는가... 아무튼 char*형 변수에 들어가 있는 문자열을 LPCWSTR로 바꾸는 방법을 몰라 한참을 막혀있었다.


결론부터 얘기하자면 저 문제에 대한 해결방법은 찾지 못했다. 대신 두번째 사용할 char*형태의 녀석이 clear라는 스페이스만 백개가 들어가는 녀석이라 눈물을 머금고 memset을 이용한 초기화를 포기하고 L"  ..."의 방식으로 const char* clear를 선언하여 해결했다.


왜 mbstowcs에 char*형태를 쓰면 스텍이 망가지는지, 왜 하필 두번 쓰면 그때부터 망가지는지 그부분은 결국 알아내지 못했다...


2.핸들 DC에 관한 부분을 거의 이해하지 못했다.


사람들이 써놓은 코드를 가져다 쓰다보니 구조적인 부분에 있어서 많이 미숙한 것 같다.


결론은 api 코딩에 관해서도 많은 공부가 필요한듯.

'자료조사 > 리버싱, 시스템' 카테고리의 다른 글

dll injection 추가  (0) 2015.07.25
dll injection 조사 3.  (0) 2015.07.23
dll injection 조사 2  (0) 2015.07.23
dll injection 조사 1  (0) 2015.07.22
Tags
Social