티스토리 뷰
728x90
DLL EXPORT의 문제점 (후킹에 대한 위험)
1. 후킹(Hooking)이란?
후킹은 운영 체제나 프로그램의 API 호출 흐름을 가로채는 기술로, 특정 함수 호출이나 메시지 처리를 가로채어 조작하거나 다른 기능을 수행하도록 할 수 있습니다. 후킹은 프로그램의 정상적인 흐름을 변경해 악성 코드를 실행하거나 데이터를 탈취하는 등 여러 가지 보안 위협을 일으킬 수 있습니다.
- API 후킹: 프로그램이 호출하는 API 주소를 변경해 공격자가 원하는 코드가 실행되도록 하는 방법.
- DLL 후킹: DLL의 함수 호출을 가로채는 방식으로, 프로그램이 DLL 내 특정 함수를 호출할 때 이를 가로채 공격자의 코드를 실행하도록 유도.
2. DLL EXPORT와 후킹의 관계
DLL에서 __declspec(dllexport)
로 외부에 노출된 함수는 프로그램이 사용하기 쉽도록 만들어져 있지만, 후킹 공격의 대상이 될 수 있습니다.
특히, Import Address Table (IAT) 후킹과 Inline 후킹이 주요한 공격 방법입니다.
IAT 후킹 예제
아래는 IAT 후킹을 통해 DLL의 원래 함수 대신 공격자가 정의한 악성 함수를 실행하도록 만드는 간단한 예제입니다.
// 원래 DLL 함수 (MyDLL.cpp)
extern "C" __declspec(dllexport) int Add(int a, int b) {
return a + b;
}
// 프로그램에서 사용하는 코드 (main.cpp)
#include <iostream>
#include <windows.h>
typedef int (*AddFunc)(int, int);
int main() {
HMODULE hDll = LoadLibrary("MyDLL.dll");
if (hDll == NULL) {
std::cerr << "DLL 로드 실패" << std::endl;
return 1;
}
AddFunc Add = (AddFunc)GetProcAddress(hDll, "Add");
if (Add == NULL) {
std::cerr << "함수 주소 로드 실패" << std::endl;
FreeLibrary(hDll);
return 1;
}
int result = Add(2, 3); // 정상적인 Add 함수 호출
std::cout << "Add(2, 3) = " << result << std::endl;
FreeLibrary(hDll);
return 0;
}
악성 코드로 IAT 후킹
IAT 후킹은 Import Address Table을 조작하여, 프로그램이 정상적으로 호출하는 DLL 함수를 가로채는 방식입니다.
아래는 Add
함수를 후킹해, 원래 함수 대신 악성 코드를 실행하게 만드는 예시입니다.
// 악성 후킹 함수 (MaliciousHook.cpp)
#include <iostream>
int HookedAdd(int a, int b) {
std::cout << "악성 코드 실행됨!" << std::endl;
return 0; // 실제 덧셈 대신 잘못된 값을 반환
}
// IAT 후킹 (IATHook.cpp)
#include <windows.h>
#include <iostream>
void HookIAT() {
HMODULE hModule = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNTHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDOSHeader + pDOSHeader->e_lfanew);
DWORD_PTR importTableRVA = pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)pDOSHeader + importTableRVA);
while (pImportDescriptor->Name != NULL) {
const char* dllName = (const char*)((DWORD_PTR)pDOSHeader + pImportDescriptor->Name);
if (_stricmp(dllName, "MyDLL.dll") == 0) { // MyDLL을 찾음
PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA)((DWORD_PTR)pDOSHeader + pImportDescriptor->FirstThunk);
while (pThunkData->u1.Function != NULL) {
FARPROC* ppfn = (FARPROC*)&pThunkData->u1.Function;
if ((DWORD_PTR)*ppfn == (DWORD_PTR)GetProcAddress(GetModuleHandle("MyDLL.dll"), "Add")) {
DWORD oldProtect;
VirtualProtect(ppfn, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, &oldProtect);
*ppfn = (FARPROC)HookedAdd; // Add 함수를 HookedAdd로 변경
VirtualProtect(ppfn, sizeof(DWORD_PTR), oldProtect, &oldProtect);
std::cout << "IAT 후킹 성공!" << std::endl;
return;
}
pThunkData++;
}
}
pImportDescriptor++;
}
}
int main() {
HookIAT(); // IAT 후킹 실행
// 이제 프로그램이 Add를 호출하면 HookedAdd가 호출됨
}
후킹 방지 방법
- 디지털 서명: DLL에 디지털 서명을 적용하여, 신뢰할 수 있는 출처에서 배포된 DLL만 로드되도록 해야 합니다.
- ASLR(Address Space Layout Randomization): ASLR을 사용하여 메모리 주소를 무작위화해, 공격자가 DLL 함수 주소를 예측하지 못하게 할 수 있습니다.
- Safe DLL Search Mode: Safe DLL Search Mode를 활성화하여 시스템 디렉터리에서 먼저 DLL을 찾도록 설정하면 악성 DLL 로드를 방지할 수 있습니다.
3. 결론
DLL EXPORT 함수는 프로그램 간의 상호작용을 용이하게 하지만, 후킹과 같은 보안 취약점에 노출될 수 있습니다. 이를 방지하기 위해서는 디지털 서명, ASLR, Safe DLL Search Mode 등 다양한 보안 기법을 적용해야 합니다.
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- CMake
- 네트워크 정보
- C++
- 현포다이브
- 암호화
- C#
- 울릉도
- 블루버블
- 서귀포블루버블
- Effective c++
- 블루버블다이브팀
- 스쿠버다이빙
- C
- 블루버블다이빙팀
- OpenSource
- effective
- 서귀포
- PowerShell
- Build
- C# 고급 기술
- 성산블루버블
- script
- Windows
- 외돌개
- C#.NET
- 패턴
- 제주도
- 스쿠버 다이빙
- DLL
- Linux
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함
250x250