DLL 인젝션 간단한 예제
DLL Injection에 대한 튜토리얼을 진행해 봤으니, 예제를 함 해보아야 겠다는 생각이 들어서 예제를 시작한다.
MinGW에서 모든 것을 진행 했으므로 에셈블리 부분은 따로 생각을 해보아야 할 문제 일듯... 이건 단지 나의 생각이긴 한데, GCC가 만들어내는 것과 MS 컴파일러가 이해하는 어셈블리는 약간 다르다는 판단이 섰고, 예제를 만들면서 컴파일을 해 본 결과 컴파일 만드로 해결되지 않았음..능력에 문제인가 한다....아...
시나리오
시나리오는 간단하게 다음과 같이 된다.
노드패드를 실행하고 나서, 해당 실행파일을 실행하면 안녕이라는 메시지가 뜬다.
작성형태
우선 injector 실행파이을 만들고, 이 실행 파일은 dll을 로딩하는 역할 을 하는 것으로 한다.
그리고 test.dll 파일을 하나 만들어서 notepad.exe가 실행이 되면 인사말을 찍는 정도록 마쳐야 겠다.
결과물
결과는 시나리오에서 처럼 다음과 같은 순으로 진행한다.
1. 노트패드를 실행한다.
사진 설명을 입력하세요.
2. 실행파일을 실행한다.
이때 안녕이라는 메시지가 나오도록...
정말 이게 다 인가??
여하튼 문제점은 계속 업데이트 되어야 할 것인데 몇가지를 집어 본다.
1. 기본적으로 위의 시나리오 대로만 해야한다는 것
- 노트패드를 띄우는 동시에 이놈은 이 이벤트를 감지하고 인사 메시지를 뿌려야 하는 것이 아닌가?
2. 노트패트는 한번 뿐..
소스 코드상에서도 그렇게 되어 있긴 하지만, "notepad.exe"를 찾아서 실행하도록 되어 있다.
코드를 보면
DWORD pID = GetTargetThreadIDFromProcName("notepad.exe");
그리고 위에서 받은 pID를 사용해서 인젝션한다.
if(!Inject(pID, buf))
근데, 문제는 한번 notepad.exe를 실행하고 나면 다시 모든 노트패드(몇개가 되었든..) 다 죽이고 나서 다시 하나 띄워야만 된다는 것이다.
결론...
곰곰히 생각 해 보니 뭐가 잘못되었는 지는 잘 모르겠다.. 애덜 장난같기도 하고...
아직까지는 잘 모르는 걸로...
부록 1. injector.c
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * DLL_NAME);
DWORD GetTargetThreadIDFromProcName(const char * ProcName);
int main(int argc, char * argv[])
{
// Retrieve process ID
DWORD pID = GetTargetThreadIDFromProcName("notepad.exe");
// Get the dll's full path name
char buf[MAX_PATH] = {0};
GetFullPathName("test.dll", MAX_PATH, buf, NULL);
printf(buf);
printf("\n");
// Inject our main dll
if(!Inject(pID, buf))
{
printf("DLL Not Loaded!");
}else{
printf("DLL Loaded!");
}
_getch();
return FALSE;
}
BOOL Inject(DWORD pID, const char * DLL_NAME)
{
HANDLE Proc;
HMODULE hLib;
char buf[50] = {0};
LPVOID RemoteString, LoadLibAddy;
if(!pID)
{
sprintf(buf, "Invalid process id: %d\r\n", GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
printf(buf);
return FALSE;
}
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if(!Proc)
{
sprintf(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
printf(buf);
return FALSE;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(NULL != LoadLibAddy)
{
// Allocate space in the process for our DLL
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Write the string name of our DLL in the memory allocated
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
// Load our DLL
CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, RemoteString, 0, NULL);
}
else
{
sprintf(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", MB_OK);
printf(buf);
return FALSE;
}
CloseHandle(Proc);
return TRUE;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = FALSE;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(thSnapShot == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK);
printf("Error: Unable to create toolhelp snapshot!");
return FALSE;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while(retval)
{
if(StrStrI(pe.szExeFile, ProcName))
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return FALSE;
}
부록 2. testdll.c
#include "main.h"
DWORD DLL_EXPORT WINAPI ShowMessageBox(LPVOID lpParam)
{
INITCOMMONCONTROLSEX iccex = {
sizeof(INITCOMMONCONTROLSEX), ICC_STANDARD_CLASSES
};
InitCommonControlsEx(&iccex);
IsGUIThread(TRUE);
OutputDebugString(TEXT("test.dll: Displaying MessageBox"));
if(MessageBox(HWND_DESKTOP, TEXT("안녕"), TEXT("안녕 이게 다야"), MB_OK | MB_ICONINFORMATION) == 0){
TCHAR szBuffer[64];
wsprintf(szBuffer, TEXT("MessageBox Error: %u"), GetLastError());
OutputDebugString(szBuffer);
}
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
{
DWORD dwThreadId;
DisableThreadLibraryCalls(hInst);
OutputDebugString(TEXT("test.dll: DLL_PROCESS_ATTACH"));
CreateThread(NULL, 0, ShowMessageBox, NULL, 0, &dwThreadId);
}
break;
case DLL_PROCESS_DETACH:
OutputDebugString(TEXT("test.dll: DLL_PROCESS_DETACH"));
break;
}
return TRUE;
}
부록 3. main.h
#ifndef __MAIN_H__
#define __MAIN_H__
//
// compiled with:
// cl test.c /link /dll /out:test.dll user32.lib kernel32.lib comctl32.lib
//
#ifndef _WIN32_IE
/* define _WIN32_IE if you really want it */
#if 1
#define _WIN32_IE 0x0400 //for INITCOMMONCONTROLSEX
#endif
#endif
#ifndef _WIN32_WINNT
/* define _WIN32_WINNT if you really want it */
#if 1
#define _WIN32_WINNT 0x501 //for ICC_STANDARD_CLASSES
#endif
#endif
#include <windows.h>
#include <commctrl.h>
/* To use this exported function of dll, include this header
* in your project.
*/
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
/* Not needed for now
#ifdef __cplusplus
extern "C"
{
#endif
void DLL_EXPORT SomeFunction(const LPCSTR sometext);
#ifdef __cplusplus
}
#endif
*/
#endif // __MAIN_H__
부록 4. 컴파일
gcc -c -I/hack/incl -DBUILD_DLL testdll.c -o testdll.o testdll.c
gcc -Wl,--kill-at -shared -o /hack/dll/test.dll testdll.o -lcomctl32
gcc -c -I/hack/incl injector2.c -o injector2.o
gcc -Wl,--kill-at -o /hack/exec/injector.exe injector2.o
이상.
'프로그래밍' 카테고리의 다른 글
C# - Thread (0) | 2023.02.24 |
---|---|
Mosquitto와 Paho 클라이언트라이브러리를 사용 (0) | 2023.02.22 |
열거 유형 - 정량적 연구 (0) | 2023.02.20 |
SQL 문장 들여쓰기 (0) | 2023.02.17 |
[JavaScript] console.log() 함수에 여러변수를 한줄로 ? (0) | 2023.02.15 |