참고 강의 - 유튜브 Fin 리버싱 강의
Reloc 섹션 제거
EXE는 원래 재배치가 필요 없었는데 Windows에 ASLR 기능이 도입되면서 주소가 자꾸 바뀌면서 필요해졌음
Hex Editor 사용
- reloc 제거
- 영역 중에서 실제로 동작하는 부분을 지우는 게 1번 나머지를 NULL값으로 채우는 게 2번
- 실질적인 영역은 섹션헤더에서 PointerToRawData부터 끝까지
- 나머지 부분 reloc 섹션헤더 채우기(NULL값/16진수 00으로)
- FILE HEADER 수정
- NumberOfSections 수정 ← 섹션 개수를 나타냄
- reloc을 삭제해서 섹션 개수 하나가 줄었으므로 값을 바꿔줌
- ex) 9 → 8
- NumberOfSections 수정 ← 섹션 개수를 나타냄
- OPTIONAL HEADER 수정
- SizeOfImage ← 메모리에서 로드되는 파일의 크기
- reloc 값을 포함한 파일의 크기라서 reloc 만큼을 빼줘야 함
- SizeOfImage - SizeOfRawData 해서 저장
- 리틀엔디안으로 저장
- reloc 값을 포함한 파일의 크기라서 reloc 만큼을 빼줘야 함
- SizeOfImage ← 메모리에서 로드되는 파일의 크기
ASPack
: 윈도우 실행 파일 크기를 70%까지 줄일 수 있는 파일 패킹 프로그램
OEP(original entry point) 위치 찾기
ret/retn == pop → jump
(jump 하려면 주소여야 함)
ret 전에 push 해놓은 값이 OEP인 걸 알 수 있음
인라인 패치(Inline Patch)
= 인라인 코드 패치(Inline Code Patch)
: 실행 압축이나 암호화된 파일을 패치할 때 사용되는 코드 인젝션
인라인 코드 패치(Inline Code Patch)는 프로그램에서 내가 수정하고 싶은 코드를 수정하기 번거로울 때 코드 케이브(Code Cave)라고 하는 것을 통해 수정함
코드 케이브(Code Cave)는 간단히 스크립트
원래는 디코딩 루프를 통해 jmp OEP를 통해 OEP를 하는데
코드
케이브는 jmp OEP 대신 jmp Code Cave 후 cmp OEP 해주는 것
일반적인 코드 패치와 인라인 패치 차이점
인라인 패치 : 파일 메모리만 가능, 파일에서는 코드케이브를 한 번만 하지만 메모리에서는 실행할 때마다 해야되고 Indirect 에 인라인 패치 가능, 얘는 특정 빈공간을 찾아야 됨
일반적인 코드 패치 : 파일에서만 가능하고 횟수는 1번만 하면 됨. 그리고 원하는 곳에 패치 가능
Window 메세지 후킹
[ Hook ]
hook 는 갈고리, 낚시바늘이라는 뜻으로 원하는 것을 낚아 채고 싶을 때 사용하는 도구
OS - APP - USER 사이의 중간에 오고가는 정보를 낚아챌 수 있다는 것
→ 사용자 몰래 정보를 후킹해서 조작 및 엿볼 수 있음
[ 메세지 훅 ]
- Windows OS는 GUI환경을 제공하고, 이는 Event Driven 방식으로 동작
- 키보드, 마우스를 이용하여 메뉴 선택이나 x 선택 등 위치 이름 등의 정보를 후킹 가능
- → 이런 작업들이 모두 이벤트이기 때문에 이벤트가 발생하면 OS는 미리 정의된 메세지를 해당 응용 프로그램에 띄워줌
- 키보드를 입력할 때도 OS로부터 응용프로그램으로 메세지가 이동함. 이런 메세지를 낚아 채는 행동을 메세지 훅이라고 함
훅 체인 : 같은 키보드 메세지 훅이라도 여러 개 동시 설치 가능. 이러한 훅을 순서대로 호출하는 것
Windows OS에서 기본 기능으로 메세지 훅을 제공함.
→ 대표적인 프로그램으로 MS Visual Studio에서 제공하는 SPY++
[ SetWindowsHookEx() ]
: 후킹하는 걸 도와주는 함수
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // hook procedure가 속해있는 dll 핸들
DWORD dwThreadID // hook을 걸고 싶은 thread의 ID (0은 global hook)
);
- SetWindowsHookEx() API를 이용해 훅을 설치하면 어떤 프로세스에서 메세지가 발생했을 때 OS가 해당 DLL 파일을 해당 프로세스에 강제로 injection하고 hook procedure를 호출함
- 특정 이벤트가 발생하면 호출하도록 지정해놓은 함수인 콜백 함수 중 하나
- dwThreadId에 0값을 주고 호출하면 글로벌 훅이 설치 됨 → 실행되는 모든 파일에 영향을 끼치게 됨
키보드 후킹
https://maple19out.tistory.com/35
/*** HookMain.cpp ***/
#include <stdio.h>
#include <conio.h>
#include <Windows.h>
#define DEF_DLL_NAME "KeyHook.dll"
#define DEF_HOOKSTART "HookStart"
#define DEF_HOOKSTOP "HookStop"
typedef void(*PFN_HOOKSTART)();
typedef void(*PFN_HOOKSTOP)();
void main() {
HMODULE hDll=NULL;
PFN_HOOKSTART HookStart=NULL;
PFN_HOOKSTOP HookStop=NULL;
char ch=0;
//KeyHook.dll 로딩
//핸들에 대한 접근자를 리턴
//핸들은 리소스에 접근할 수 있는 값 정도..?
hDll = LoadLibraryA(DEF_DLL_NAME);
//export 함수 주소 얻기
HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
//후킹 시작
HookStart();
//'q'가 입력으로 들어올 때까지 대기
printf("press 'q' to quit!\n");
while(_getch() != 'q');
//후킹 종료
HookStop();
//KeyHook.dll 언로딩
FreeLibrary(hDll);
}
/*** KeyHook.cpp ***/
#include <stdio.h>
#include <Windows.h>
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hInstance=NULL;
HHOOK g_hHook=NULL;
HWND g_hWnd=NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) {
switch(dwReason) {
case DLL_PROCESS_ATTACH:
g_hInstance=hinstDLL;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
char szPath[MAX_PATH]={0, };
char *p=NULL;
if(nCode>=0) {
//31-th bit=> press, 1st bit=> release
if(!(lParam & 0x80000000)) {
//process의 경로를 알아낸다.
GetModuleFileNameA(NULL, szPath, MAX_PATH);
//경로로부터 프로세스 name 파싱
p = strrchr(szPath, '\\');
//현재 프로세스가 notepad.exe라면,
//응용 프로그램으로 메시지를 전달하지 않는다.
//키보드로 값을 입력 하지 못하도록 하는 거라고 보면 된다
//여기 다양한 응용 가능
if(!_stricmp(p+1, DEF_PROCESS_NAME))
return 1;
}
}
//일반적인 경우에는 CallNextHookEx()를 호출하여
//응용 프로그램으로 메세지를 전달한다.
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void HookStart() {
g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
}
__declspec(dllexport) void HookStop() {
if(g_hHook) {
UnhookWindowsHookEx(g_hHook);
g_hHook=NULL;
}
}
#ifdef __cplusplus
}
#endif
후킹으로 프로그램을 다룰 수 있다 !
PE파일 끝 → UPack → 인라인 패치 → Win32 API → DLL 인젝션
'2. Reversing (리버싱) > 2) 개념 정리' 카테고리의 다른 글
[2025.05.17]리버싱난다_5주차 활동 (2) | 2025.05.22 |
---|---|
[2025.05.10] 리버싱난다_4주차 활동 (0) | 2025.05.14 |
[2025.04.05] 리버싱난다_3주차 활동 (0) | 2025.04.10 |
[2025.03.29] 리버싱난다_2주차 활동 (0) | 2025.04.04 |
[2022.03.19] 어셈블리어, 레지스터 (1) | 2022.03.20 |