출처 :
http://yuik.tistory.com/83
예전에 복사해 놓은 것인데..
출처가 어디인지 정확히 기억이 안난다;;
dll Injection은?
이미 실행되어 있는 프로세스로 DLL 을 삽입하는 기법
-특정 함수를 실행 하기 전에 프로세스를 실행 하는 지점에서 제어권을 가로 챈 뒤, 자신의 코드를 주입, 실행 하고 제어권을 다시 돌려주는 방법
dll Injection에 필요한 함수와 코드의 흐름
OpenProcess
- 프로세스를 열어 핸들을 구한다
LoadLibrary
- .dll을 로드한다.
GetProcAddres
- 특정함수의 메모리 주소를 얻어온다.
VirtualAllocEx
- 타 프로세스의 새로운 힙영역을 확보한다.
WriteProcessMemory
- 타 프로세스의 공간에 데이터를 쓴다.
CreateRemoteThread
-타 프로세스에 스레드를 생성 시킨다.
간단한 dll injection 샘플
계산기 프로그램의 주소공간에 DLL을 인젝션하여 숫자 입력시 1씩을 더하도록 하는 인젝션 예..
#include <iostream.h>
#include <windows.h>
// DLL Inject : 다른 프로세스의 주소 공간에 특정 DLL을 넣는다.
void DllInject(DWORD pid, char* path)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
// 내 프로세스에 있는 KERNEL32.DLL의 주소와 LoadLibrary의 주소를 구한다.
HMODULE hDll = GetModuleHandle("kernel32.dll"); // kernel32.dll 모듈의 핸들값을 GetModuleHandle로 구한다.
PTHREAD_START_ROUTINE f = (PTHREAD_START_ROUTINE)GetProcAddress(hDll, "LoadLibraryA");
// PTHREAD_START_ROUTINE은 미리 정의되어 있는 스레드 함수 모양의 함수 포인터 type
// 계산기의 주소공간에 메모리를 할당하고, DLL의 경로를 복사해준다.
// VirtualAlloc은 가상 메모리를 할당하는 API이지만, Ex가 붙으면 다른 프로세스의 주소공간을 할당할 수 있다.
void* p = VirtualAllocEx(hProcess, 0, // 원하는 주소(0은 알아서 해달라)
strlen(path)+1, // 크기
MEM_RESERVE | MEM_COMMIT, // 예약과 동시 확정
PAGE_READWRITE);
// 이제 DLL의 경로를 담을 문자열 복사
// WriteProcessMemory()는 다른 프로세스 주소 공간에 무언가를 쓸 수 있다.
DWORD len;
WriteProcessMemory(hProcess, p, path, strlen(path)+1, &len);
// 계산기에 새로운 스레드를 만든다.
// CreateRemoteThread는 다른 프로세스에 스레드를 생성시킨다.
HANDLE hThread = CreateRemoteThread(hProcess, // 계산기 핸들
0, 0,
f, p, // 함수, 파리미터
0, 0);
CloseHandle(hThread);
CloseHandle(hProcess);
}
void main()
{
HWND hwnd = FindWindow(0, "계산기");
if(hwnd == 0)
{
cout << "계산기를 먼저 실행하시오" << endl;
return;
}
DWORD pid;
DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
DllInject(pid, "C:\\spy1.dll");
}
이제부터, DLL 로 작성한다.
#include <windows.h>
WNDPROC old; // 원래 계산기의 메세지 함수의 주소를 담을 변수
// 계산기의 메세지를 처리할 새로운 함수
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg)
{
case WM_COMMAND: // 버튼 또는 메뉴를 선택할 경우
{
UINT id = LOWORD(wp);
if(id >= 0x7c && id <= 0x85)
return CallWindowProc(old, hwnd, msg, wp+1, lp+1);
break;
}
}
// 나머지 모든 메세지는 원래의 함수로 보내준다.
return CallWindowProc(old, hwnd, msg, wp, lp);
}
// 모든 DLL은 Process에 Mapping 되거나 해제될 때 DllMain이 호출됨.
BOOL WINAPI DllMain(HANDLE h, DWORD r, LPVOID p)
{
if(r == DLL_PROCESS_ATTACH)
{
HWND hwnd = FindWindow(0, "계산기");
old = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc);
}
return TRUE;
}