zj3t

email: euntaejang@gmail.com

Latest Posts

DLL Injection-실습

By 오후 5:08 ,

리버싱 핵심원리의 실습은 모두 32비트 환경에서 실행되었어서 대부분의 독자들은 실습이 원활하게 되지 않을 것입니다. 저 또한 dll injection 실습을 해보고싶었는데 실습이 되질 않았습니다.

그래서 책에 있는 실습코드를 VS에서 똑같이 코딩한 후 실행했는데도 되지 않아 이유를 찾아봤는데 대부분 VS에서 프로그램을 만든다고 하면 32비트 파일입니다.(기본적으로 설정)
하지만 OS 64bit 이기 때문에 메모장 또한 64bit 프로그램입니다. 따라서 코드는 32비트인데 인젝션할 프로그램은 64bit 이기 때문에 실습이 되지 않았던 것입니다.

그래서 저는
C:\Program Files (x86)\Windows NT\Accessories\wordpad.exe로 실습을 해봤습니다.

notepad로 하고싶은 분들은 32bit 메모장을 구해서 실습할 수 있고 또한 가상머신으로 32bit OS를 적용시켜 실습할 수 있습니다.

///////////////////////////////////////////////////////////////////////////////////////////////////////

//InjectionDll.exe

#include "windows.h"
#include "tchar.h"
 
BOOL InjectDLL(DWORD dwPID, LPCTSTR szDllPath)
{
HANDLE hProcess = NULL, hThread = NULL;
HMODULE hMod = NULL;
LPVOID pRemoteBuf = NULL;
DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1)*sizeof(TCHAR);
LPTHREAD_START_ROUTINE pThreadProc;
 
 
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
{
_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
 
return FALSE;
}
 
pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
 
WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);
 
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");

hThread = CreateRemoteThreadEx(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);
 
CloseHandle(hThread);
CloseHandle(hProcess);
 
return TRUE;
}
 
int _tmain(int argc, TCHAR *argv[])
{
if (argc != 3)
{
_tprintf(L"USAGE: %s pid dll_path\n", argv[0]);
return 1;
}
if(InjectDLL((DWORD)_tstol(argv[1]),argv[2]))
{
_tprintf(L"InjectDll(\"%s\") success!!!\n", argv[2]);
}
else
_tprintf(L"InjectDll(\"%s\") failed!!!\n", argv[2]);
 
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

이 코드는 리버스코어(책의 저작자 블로그)에서 볼 수 있습니다.

이 프로그램이 dll을 프로세스에 인젝션 시킬 수 있도록 해주는 프로그램입니다. 

단계를 보면

1.tmain, 즉 main 함수에서 InjecDLL()함수를 호출합니다. 

2.InjectDLL()을 보면 BOOL InjectDLL(DWORD dwPIDLPCTSTR szDllPath) 라고 정의, 첫번째 매개변수는 PID, 두번   째 매개변수는 인젝션 시킬 dll의 경로

3.hProcess = OpenProcess(PROCESS_ALL_ACCESSFALSEdwPID)), 해당 PID를 가진 프로세스 핸들을 가져옵니다.

4.VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMITPAGE_READWRITE); 해당 핸들의 메모리에 인젝션할 dll의 경로만큼의 크기를 할당합니다.  반환값은 할당한 메모리의 시작주소 입니다.

5.WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL); 로 할당한 메모리에 두번 째 매개변수인 dll의 경로를 써줍니다.

6.
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");

:kernel32.dll의 모듈을 가져와 이를 이용하여 kernel32.dll에 있는 LoadLibraryW의 주소를 알아낸다.

7.hThread = CreateRemoteThreadEx(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL, NULL); 를 이용,
원래 실습코드에서는 CreateRemoteThread를 사용했지만 윈도우 7부터는 Ex를 권장한다고 해서 써봤습니다. Ex가 아니여도 실습은 되었습니다.

8. CloseHandle(hThread);
   CloseHandle(hProcess);

저도 API 프로그래밍을 해본적이 몇번없어서 코드를 이해하는데 많은 시간을 소비했고 이렇게 포스팅을 함으로써 확실히 알아가려고 하는 것입니다. 첨부터 어렵다고 넘기기보단 하나씩 구글검색하면서 찾아보면 이해할 수 있을 것입니다.

팁으로 비쥬얼 스튜디오2015 디버깅을 이용하면 에러찾기가 수월합니다.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//myhack.cpp
 
#include "windows.h"
#include "tchar.h"
 
#pragma comment(lib, "urlmon.lib")
 
#define DEF_URL (L"http://www.naver.com/index.html")
#define DEF_FILE_NAME (L"index.html")
 
HMODULE g_hMod = NULL;
 
DWORD WINAPI ThreadProc(LPVOID lparam)
{
TCHAR szPath[_MAX_PATH] = { 0, };
if (!GetModuleFileName(g_hMod, szPath, MAX_PATH))
return FALSE;
 
TCHAR *p = _tcsrchr(szPath, '\\');
if (!p)
return FALSE;
 
_tcscpy_s(p + 1, _MAX_PATH, DEF_FILE_NAME);
 
URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL);
 
return 0;
}
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
HANDLE hThread = NULL;
g_hMod = (HMODULE)hinstDLL;
 
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
OutputDebugString(L"myhack.dll Injection!!!");
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
CloseHandle(hThread);
break;
}
 
return TRUE;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

이 코드 또한 리버스코에(www.reversecore.com)에서 볼 수 있습니다.

대략 적인 흐름을 보면

1.case DLL_PROCESS_ATTACH:
  OutputDebugString(L"myhack.dll Injection!!!"); 
  hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
  CloseHandle(hThread);

dll일 attach되면 즉 실행하게 되면 실행되는 코드들 입니다.

2. #define DEF_URL (L"http://www.naver.com/index.html")
   #define DEF_FILE_NAME (L"index.html")

3.GetModuleFileName(g_hMod, szPath, MAX_PATH)로 실행되고있는 파일의 경로를 두번째 매개변수에 리턴

4.TCHAR *p = _tcsrchr(szPath, '\\'); : \\다음의 문자열을 가져오고 포인터 p는 그 문자열의 시작주소를 가리킴

5. _tcscpy_s(p + 1, _MAX_PATHDEF_FILE_NAME); : p+1에 index.html  문자열을 copy

6.URLDownloadToFile(NULLDEF_URL, szPath, 0, NULL); : p는 szPath를 가리키므로 파일의 경로에 index.html을 
                                                                           붙혀 URL로 부터 html파일을 다운로드함.



실습:













여기까지 실습이 됬습니다. 계속해도 안되던 실습을 날잡고 해보자 마음먹고 해봤는데 코드의 대략적인 흐름부터해서 알 수있었습니다. 

구글이나 네이버등 사이트를 이용해 API를 검색해서 찾아봐야 이해가 쉬울 것 같습니다.







You Might Also Like

1 개의 댓글

  1. 감사합니다! 몇시간동안 책을 아무리 봐도 해결하지못했는데..

    답글삭제