본문으로 바로가기

[D+13] DLL Injection (2)

category 해킹&보안/리버싱 2017. 4. 20. 21:15
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

6. DLL Injection


2) DLL (Dynamic Linked Library)


▣ LoadLibrary & FreeLibrary

- 두 함수 모두 Kernel32.DLL 안에 들어있음.

- HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);

☞ 해당 dll 파일을 메모리 상으로 로드.

☞ HINSTANCE : 로딩한 DLL의 핸들값.

☞ LPCTSTR lpLibFileName : DLL 경로(상대, 절대 경로 모두 가능)

- BOOL FreeLibrary(HMODULE hLibModule);

☞ 해당 dll 파일을 메모리 상에서 해제.

☞ HMODULE hLibModule : 핸들 값

- Load된 수 만큼 메모리 상에서 개수만 중첩되기 때문에 Free또한 load한 만큼 해야함.


▣ DLL 파일 로드하는 함수 만들기

#include <windows.h>

int main(int argc, char *argv[])
{
	HMODULE hModule;
	
	hModule = LoadLibrary("C:\\Documents and Settings\\student\\바탕 화면\\LoadMain\\DLL\\Debug\\DLL.dll");
	
	if(hModule)
		OutputDebugString("로드성공");
	else
		OutputDebugString("로드실패");

	if(hModule)
		FreeLibrary(hModule);
	
	return 0;
}

- 8줄 LoadLibrary : 로딩한 dll의 핸들값 리턴. (로딩실패시 NULL 리턴)

- 16줄 FreeLibrary : 메모리상에서 제거 전 dll의 main함수가 한번 더 돌면서 메시지박스가 한번 더 뜬다.

▣ 메모리 분석하기

- 앞서 만든 DLL 파일을 PEview로 열어보면 IMAGE BASE가 10000000임.

- 해당 DLL을 불러오는 프로그램을 디버깅모드로 실행하여 DLL 파일의 IMAGE BASE인 10000000번지를 보면 LoadLibrary 전에는 아무 값이 없음.

- LoadLibrary함수를 실행하게 되면 dll 파일이 해당 메모리의 주소에 올라옴을 확인할 수 있음.

- hModule 변수에는 1000000이 들어감.



3) DLL (Dynamic Linked Library) -- 함수 불러오기


--> DLL 의 가장 큰 사용 목적은 해당 DLL 파일안의 함수를 쓰기위한 것이다.


▣ DLL 파일 속 함수 참조 원리

- DLL 파일 속 함수를 쓰려면 해당 함수의 주소가 필요함.

- 프로그램은 DLL 파일의 EAT를 참조하여 IAT를 완성하고 IAT를 참조하여 주소를 가지고 해당 함수를 사용.

- 직접 IAT와 비슷하게 만들기 위해 DLL 파일 속 함수의 주소를 담을 함수 포인터 변수를 사용할 것임.


▣ DLL 파일 만들기

#include <windows.h>

extern "C"
void _declspec(dllexport) Test()
{
	MessageBox(NULL, "export 함수 호출 테스트", "", MB_OK);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
					  DWORD  ul_reason_for_call, 
					  LPVOID lpReserved
					  )
{
	switch(ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		OutputDebugString("ATTACH");
		break;
		
	case DLL_PROCESS_DETACH:
		OutputDebugString("DETACH");
		break;
	}
    return TRUE;
}

- 3줄 extern "C" : 다음 함수를 C컴파일러로 컴파일한다는 뜻.

☞ dll파일은 cpp로 작성되는데 cpp 컴파일러의 경우 함수 이름 앞뒤에 랜덤 문자열을 붙임.

☞ extern "C"를 사용하지 않았을 때 ( == C++컴파일러 사용 시)

☞ extern "C"를 사용했을 때 ( == C컴파일러 사용 시)

- 4줄 _declspec(dllexport) : export함수로 사용한다고 명시적으로 표시를 해주어야 EAT에 반영됨.


▣ DLL 속 Test 함수를 불러올 프로그램 만들기


[함수 포인터]

- 기본형태 : return_type (*function_name)(arg1, arg2 ....);

- 함수 이름 앞에 포인터 * 붙이고 ( )로 감싸주기.

☞ ( ) 로 감싸주지 않으면 리턴형이 return_type* 로 컴파일러가 착각함.

- function_name = 함수이름;

☞ 함수이름의 함수 주소가 function_name 변수에 들어감.

#include <windows.h>

typedef void (*PFNFUNC)();

PFNFUNC fnTest;

int main(int argc, char *argv[])
{
	HMODULE hModule;
	hModule = LoadLibrary("C:\\Documents and Settings\\student\\바탕 화면\\LoadMain\\DLL\\Debug\\DLL.dll");
	
	if(hModule)
	{
		// PFNFUNC로 자료형을 설정하지 않았다면
		// fnTest = (void(*)())GetProcAddress(hModule, "Test");
		fnTest = (PFNFUNC)GetProcAddress(hModule, "Test");
		if(fnTest) fnTest();

		// 함수호출 다른방법
		// 1.
		// ((PFNFUNC)GetProcAddress(hModule, "Test"))();

		// 2.
		// GetProcAddress(hModule, "Test");
		// _asm call eax
	}
	
	if(hModule) FreeLibrary(hModule);
	return 0;
}

- 3줄 typedef : 함수 포인터 자료형을 설정해줌. (캐스팅할거라서 사용)

- 5줄 PFNFUNC fnTest : 함수 포인터 변수 선언.

- 16줄 GetProcAddress : 핸들의 모듈값으로 해당 dll의 EAT를 찾아가서 2번째 인자와 일치하는 이름의 함수 주소를 가져옴.



4) DLL Injector 만들기


CreateRemoteThread

- 타 프로세스에서 다른 프로세스에 스레드 생성후 어떤 행동을 어떤 인자를 가지고 할지도 결정 가능.

- 대상 프로세스에 스레드 생성 --> LoadLibrary 함수 호출 가능.

- CreateRemoteThread(대상 프로세스의 핸들값, 인자(주소), 함수주소);

☞ 대상 프로세스 핸들값 : OpenProcess 함수로 구함.

☞ 인자(주소) : 대상 메모리에 인자가 존재해야함. WriteProcessMemory 함수 사용.

☞ 함수 주소 : GetProcAddress(모듈핸들, 함수이름) 사용

→ 모듈핸들은 GetModuleHandle(모듈이름) 로 구함.

→ 하지만 함수 주소는 현재 프로세스의 메모리 안에서 구하니까 현재 프로세스 메모리 속 해당 모듈의 함수주소를 찾아옴.

   진짜 구해야하는 함수주소는 dll을 주입할 프로세스의 메모리에서 찾아와야함.

   그래서 가정을 함. 현재 프로세스와 주입당할 프로세스의 메모리가 같은 위치에 해당 모듈이 있을거라고..


▣ OpenProcess

- 주입할 대상 프로세스에 대한 핸들 얻음.

OpenProcess(pid);

☞ pid를 구하기 위해서 툴을 이용하여 알아내거나 함수로 구하거나.


▣ WriteProcessMemory

- 대상 프로세스 내에 내가 원하는 위치에 원하는 값 기록.

- 할당된 메모리에 DLL 경로를 기록.

WriteProcessMemory(대상프로세스 핸들값, 위치, 쓸 내용, 쓸 크기);

☞ 위치 : VirtualAllocEx 함수로 구함.

☞ 쓸 내용, 쓸 크기 : dll 경로.


▣ VirtualAllocEx

- 대상 프로세스 내에서 DLL 경로를 넣기 위한 메모리를 할당.

- 새로운 공간 생성 (원하는 위치에 원하는 크기로 공간확보)

VirtualAllocEx(프로세스 핸들값, 위치, 크기)

☞ 0 (NULL 값) 넣으면 알아서 비어있는 공간을 자동으로 할당해줌.


[Thread Injection]

- DLL Injection : LoadLibrary함수로 실행 (이미 해당 메모리에 존재하는 함수 실행)

- Code Injection : 본인이 직접 짠 코드 실행.



★☆ String 주소랑 함수 주소를 어떻게 독립된 다른 메모리로 보낼까? ★☆

- 레지스터를 쓴다!

- 그래서 가장 먼저 EBX와 EAX를 사용하여 자신의 메모리 스택으로 온전히 불러와서 씀. 

- 나중에 해당 스택에 접근하여 PUSH와 CALL을 통해 함수를 실행함.






i2sec 대구지점 23기 수료생.

'해킹&보안 > 리버싱' 카테고리의 다른 글

[D+14] 악성코드 분석  (0) 2017.04.21
[D+12] DLL Injection (1)  (0) 2017.04.18
[D+11] 안티 디버깅  (0) 2017.04.17
[D+10] 패킹&언패킹 (2)  (0) 2017.04.12
[D+9] 패킹&언패킹 (1)  (0) 2017.04.11