참고자료 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ilikebigmac&logNo=221470036755
c++로 만들어진 dll 파일과 exe파일로 dll injection을 하는 방법
처음 DLL injection에 사용되는 프로그램의 소스코드를 보았을 때 이해가지 않는 부분이 많았음.
win32 API함수들이었다는 것을 알게 되고
dll injection을 하기 전에 win32 API 를 우선적으로 공부해야할 것 같다고 판단함.
win32 API란 C언어로 작성되었으며 window환경에서 GUI프로그래밍을 하기위한 코드를 모아둔 거라고 보면 됨.
win32 API에 대해 공부해보자.
참고자료 : http://soen.kr/lecture/win32api/ApiLec.htm
변수 명명법
접두어 | 원래말 | 의미 |
cb | Count of Bytes | 바이트 수 |
dw | double word | 부호없는 long형 정수 |
h | handle | 윈도우, 비트맵, 파일 등의 핸들 |
sz | Null Terminated | NULL 종료 문자열 |
w | Word | 부호없는 정수형 |
i | Integer | 정수형 |
b | Bool | 논리형 |
변수 앞에 붙는 접두어에 대한 정리같다.
예를 들면 cbString은 문자열의 바이트 수를 나타내는 정수형 변수
szMessage는 널 문자열을 가리키는 포인터
데이터형 | 의미 |
BYTE | unsigned char형 / 1BYTE |
WORD | unsigned short형 / 2BYTE |
DWORD | unsigned long형 / 4BYTE |
LONG | long과 동일하다. / 8BYTE? 확실하진 않다. |
LPSTR | char *와 동일하다. |
BOOL | 정수형이며 TRUE, FALSE 중 한 값을 가진다. |
windows.h에 지정되어 있는 타입이다.
win32 API에서는 데이터형으로 이것들을 사용하니 잘 외워두는 게 좋다.
핸들
1. 핸들은 정수값이며 대부분 32비트값이다.
윈도우 운영체제에서 파일에 대한 주소값을 주지 않고 주소에 대한 정수값을 생성하여 그 값을 가지고 사용자가 파일에 접근할 수 있게 해준다. <- 내가 대충 알던 지식
2. 핸들은 운영체제에서 발급해주며 윈도우를 만들거나 파일을 열면 운영체제는 만들어진 윈도우나 열려진 파일에 핸들을 붙여준다. 사용자는 이 핸들을 잘 보관해 두었다가 해당 윈도우나 파일을 다시 참조할 때 핸들을 사용하면 된다.
3. 같은 종류의 핸들끼리는 절대로 중복된 값을 가지지 않는다. 다른 종류의 핸들끼리는 중복된 값을 가질 수도 있다.(이해 안됨.)
4. 윈도우즈에서는 핸들은 예외없이 접두어 H로 시작되며 핸들값을 저장하기 위해 별도의 데이터형까지 정의해 두고 있다.
HWND, HPEN, HBRUSH, HDC 등이 핸들을 담기 위한 데이터형들이며 모두 부호없는 정수형이다.
win32 API만의 특별한 인자 전달법?
보통 함수에서 인자를 전달할 때 printf("%d, %d", num1. num2) 인자 2개를 이런식으로 전달하지만
윈도우 API에서는 비트 OR연산을 통해 하나의 인자에 복수개의 옵션을 묶어 전달하는 방법을 사용한다.
참고자료 : http://soen.kr/lecture/win32api/ApiLec.htm
참고자료를 보는게 복습하는데 좋을 듯 하다.
WIN32 API 예제 프로그래밍 코드의 이해
참고자료 : http://soen.kr/lecture/win32api/ApiLec.htm
windows.h에 모든 API 함수들의 원형과 사용하는 상수들을 죄다 정의하고 있음.
윈도우즈 프로그램의 시작점은 main함수가 아닌 WinMain임.
WinMain함수의 원형은 4개의 인수를 취하는데 다음과 같이 고정되어 있다.
인수 | 의미 |
hInstance | 프로그램의 인스턴스 핸들 |
hPrevInstance | 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들. 없을 경우는 NULL이 되며 WIN32에서는 항상 NULL이다. 호환성을 위해서만 존재하는 인수이므로 신경쓰지 않아도 된다. |
lpCmdLine | 명령행으로 입력된 프로그램 인수이다. 도스의 argv인수에 해당한다. |
nCmdShow | 프로그램이 실행될 형태이며 최소화, 보통모양 등이 전달된다. |
hInstance에서 Instance라는 말은 클래스가 메모리에 실제로 구현된 실체를 의미한다. 쉽게 이해하자면
메모장이 2번 실행되어 있다고 가정했을 때 이 두 개의 메모장은 서로 다른 메모리를 사용하는 다른 프로그램이므로 인스턴스 핸들의 값은 서로 다르다!
위의 코드를 보면 HINSTACNE g_hInst; 로 프로그램의 인스턴트 핸들을 전역변수로 설정하고 있다. <- 나중에 사용한다고 함.
WinMain 함수는 윈도우를 만들고 화면에 출력하기만 할 뿐 대부분의 일은 WndProc에서 이루어진다.
그래서 WinMain함수보다 WndProc함수를 더 유의깊게 봐야한다!
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); <- WInProc의 함수 원형
윈도우 클래스!
윈도우를 만드려면 윈도우 클래스를 먼저 등록한 후 CreateWindow함수를 호출해야 한다.
윈도우 클래스는 windows.h에 정의되어 있는 구조체이다.
윈도우 클래스 구조체는 다음과 같다.
typedef struct tagWNDCLASS
{
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCSTR lpszMenuName;
LPCSTR lpszClassName;
} WNDCLASS;
윈도우 클래스에 지정된 속성들의 내용은 아래를 참고하자...
참고자료:http://soen.kr/lecture/win32api/ApiLec.htm
정리하기에 양이 너무 방대하다.
다음은 윈도우 클래스에 설정된 속성들의 값을 사용하여 윈도우를 생성하는 CreateWindow함수 원형을 보자
HWND CreateWindow(lpszClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, hwndParent, hmenu, hinst, lpvParam)
ㅈ같이 API 함수들은 인자가 존나 많다.
이 내용도 위의 참고자료를 활용하자.
BOOL ShowWindow(hWnd,nCmdShow)
CreateWindow함수로부터 생성된 hWnd 인수를 받아 ShowWindow함수로 프로그램을 생성한다.
nCmdShow는 윈도우를 화면에 출력하는 방법을 지정하며 아래와 같은 매크로 상수들이 정의되어 있다.
매크로 상수 | 의미 |
SW_HIDE | 윈도우를 숨긴다. |
SW_MINIMIZE | 윈도우를 최소화시키고 활성화시키지 않는다. |
SW_RESTORE | 윈도우를 활성화시킨다. |
SW_SHOW | 윈도우를 활성화시켜 보여준다. |
SW_SHOWNORMAL | 윈도우를 활성화시켜 보여준다. |
메세지 루프
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
프로그램에서 메세지를 처리하는 부분을 메세지 루프라고 하며 보통 WinMain 함수의 끝에 존재한다.
메세지란 키보드를 누르거나 마우스로 클릭하는 등 변화에 대한 정보들의 메시지를 말한다.
메세지 루프는 위의 3개의 함수 호출로 이루어져 있음.
BOOL GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
이 함수는 시스템이 유지하는 메시지 큐에서 메시지를 읽어들인다.
첫번째 인자는 메세지가 WM_QUIT일 경우 False를 리턴, 그 외의 메세지이면 True를 리턴한다.
WM_QUIT메시지가 읽혀지면 프로그램이 종료된다.
나머지 3개의 인자는 잘 사용되지 않는다.
BOOL TranslateMessage( CONST MSG *lpMsg);
키보드 입력 메세지를 가공하여 프로그램에서 쉽게 쓸 수 있도록 해준다.
윈도우즈는 키보드의 어떤 키가 눌러졌다거나 떨어졌을 때 키보드 메시지를 발생시키는데 이 함수는 키보드의 눌림(WM_KEYDOWN)과 떨어짐(WM_KEYUP)이 연속적으로 발생할 때 문자가 입력되었다는 메시지(WM_CHAR)를 만드는 역할을 한다. 예를 들어 A키를 누른 후 다시 A키를 떼면 A문자가 입력되었다는 메시지를 만들어 낸다.
LONG DispatchMessage( CONST MSG *lpmsg);
시스템 메시지 큐에서 꺼낸 메시지를 프로그램의 메시지 처리함수(WndProc)로 전달한다.
이 함수를 통해 메시지가 프로그램으로 전달되며 프로그램에서는 전달된 메시지를 점검하여 다음 동작을 결정하게 된다.
메시지 루프에서 하는 일은 메시지를 꺼내고, 필요한 경우 약간 형태를 바꾼 후 응용 프로그램으로 전달하는 것 뿐이다. 이 과정은 WM_QUIT 메시지가 전달될 때까지, 즉 프로그램이 종료될때까지 반복된다. 결국 메시지 루프가 하는 일이란 메시지 큐에서 메시지를 꺼내 메시지 처리 함수로 보내주는 것 뿐이다.
실제 메시지 처리는 별도의 메시지 처리 함수(WndProc)에서 수행한다. 메시지는 시스템의 변화에 대한 정보이며 MSG라는 구조체에 보관된다. MSG 구조체는 다음과 같이 정의되어 있다.
typedef struct tagMSG
{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
여기까지 정리하면서 느낀거지만 그냥 soen.kr에 들어가서 직접 읽어보면서 공부하는게 더 좋을 듯 하다.
'알쓸신잡' 카테고리의 다른 글
윈도우 사용자(디렉토리명) 이름 변경 방법 (2) | 2025.01.02 |
---|---|
[VMware] windows -> windows 복사 붙혀넣기 방법 (2) | 2024.11.16 |
chatGPT (0) | 2023.02.28 |
프로그램 툴 정리 (0) | 2021.10.11 |