[- Disclaimer -]
아래 내용은 정보보안 공부 목적으로 작성된 것이나, 이를 토대로 허가되지 않은 대상에 실습을 진행할 경우 해킹 시도로 간주하여 법적 처벌을 받을 수 있음을 알려 드립니다.
WinMain()
✦ Windows GUI 프로그램 시작점
✧ Window 창 생성 과정 처리
→ WndClass부터 ShowWindow()까지
✦ APIENTRY 지시자
✧ __stdcall로 정의되어 있음
✦ Parameter1에 전달되는 Argument1
✧ hInstance
→ 현재 Instance Handle
→ 직접 hInstance를 사용하는 경우는 드물지만 아래의 경우에 사용될 경우 Windows Message 처리 및 Resource 관리에 핵심적 역할 수행
ㄴㄴ RegisterClassEx() 내 WNDCLASSEX 구조체의 hInstance Parameter
ㄴㄴ CreateWindowEx()의 Argument11
ㄴㄴ CreateWindowEx()의 Argument12와 Argument13의 Callback 함수의 NULL이 전달되는 Parameter에도 hInstance가 전달될 수 있으며 이때 OS에서 제공하는 것이 아닌 자체 제작 Resource 사용 // 자체 제작 Resource는 PE 내 Resource Section에 저장 됨
✦ Parameter2에 전달되는 Argument2
✧ hPrevInstance
→ 이전 Instance Handle
→ 없을 경우 NULL 포인터
ㄴㄴ Win32에서는 Default=NULL
ㄴㄴ 16 bit 호환성 때문에 존재 // 과거 16 bit 프로그램에서 동일 프로그램 실행 시 메모리 절약 목적의 Instance 공유를 위해 사용되었으나 현재는 의미 없음
✦ Parameter3에 전달되는 Argument3
✧ lpszCmdLine
→ 프로그래명 포함 명령행 Parameter
→ 통상 실행 직후의 경로 전달
✦ Parameter4에 전달되는 Argument4
✧ nCmdShow
→ Windows Application 팝업 방식이며 프로그램 실행 시 최소화, 모양 등의 형태 전달
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow);
Plain Text
복사
WinMain()의 hInstance Argument <-> _IMAGE_NT_HEADERS 구조체의 ImageBase 간 동일 - Ex)
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, PTSTR pszCmdLine, int nCmdShow) {
g_hInstance = hInstance;
(...)
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
static TCHAR s_szMsg[64];
switch(uMsg) {
case WM_CREATE:
wsprintf(s_szMsg, C_YHD_MSG, g_hInstance);
return TRUE;
case WM_PAINT: {
(...)
DrawText(hDC, s_szMsg, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS);
EndPaint(hWnd, &ps);
}
return 0;
(...)
Plain Text
복사
WinMain() Caller
✦ RtlUserThreadStart() → BaseThreadInitThunk() → wWinMainCRTStartup() → _tmainCRTStartup() → wWinMain()
✦ RtlUserThreadStart()
✧ ntdll.dll
✦ BaseThreadInitThunk()
✧ Kernel32.dll
__tmainCRTStartup()
✦ C/C++ Runtime 초기화, WinMain() 호출, Process 종료 처리
__tmainCRTStartup()에서 WinMain() 호출 - Ex)
✦ 전처리기 조건을 GUI와 Unicode로 한정했을 경우에 한 함
(...)
// WinMain()의 마지막 Parameter인 nCmdShow 값 획득
__declspec(noinline) int __tmainCRTStartup(void) {
_TUCHAR *lpszCommandLine = NULL;
WORD showWindowMode = 0;
showWindowMode = __crtGetShowWindowMode(); // GetStartupInfo() 호출 후 Return 값 저장 (showWindowMode에 STARTUPINFO.wShowWindow 값 설정)
// 초기화 작업을 위한 동기화 처리
__try {
void *lock_free = 0;
void *fiberid=((PNT_TIB)NtCurrentTeb())->StackBase;
int nested=FALSE;
while((lock_free = _InterlockedCompareExchangePointer((volatile PVOID *)&__native_startup_lock, fiberid, 0)) != 0) {
(...)
// c/c++ 관련 초기화 처리
if(__native_startup_state == __initializing)
_amsg_exit(_RT_CRT_INIT_CONFLICT);
else if(__native_startup_state == __uninitialized) {
__native_startup_state == __initializing;
if(_initterm_e(__xi_a, __xi_z) != 0)
return 255;
}
if(__native_startup_state == __initializing) {
_initterm(__xc_a, __xc_z);
__native_startup_state = __initialized;
}
// WinMain()의 pszCmdLine Parameter에 전달될 명령어 Parsing
(...)
lpszCommandLine = (wchar_t *)_wcmdln;
(...)
// WinMain() 호출
mainret = wWinMain((HINSTANCE)&__ImageBase, NULL, lpszCommandLine, showWindowMode);
// Process 종료
exit(mainret);
}
__except(_XcpFilter(GetExceptionCode(), GetExceptionInformation())) {
mainret = GetExceptionCode();
_exit(mainret);
}
return 0;
}
// 리코엔 두꺼운거 1권_파일 구조 편 192p 이어서
Plain Text
복사


