개발/WIN32-MFC

DLL 시리즈 #6 EXPORT NONAME 방법

-=HaeJuK=- 2024. 9. 12. 15:43
DLL EXPORT 방법 중 NONAME 기술

DLL EXPORT 방법 중 NONAME 기술

1. NONAME 기술이란?

NONAME 기술은 DLL에서 함수나 변수를 이름 대신 번호(ordinal)로 export하는 방식입니다. 이 방법을 사용하면 DLL 크기를 줄이고, 보안을 강화할 수 있지만, 사용성과 유지보수 측면에서 어려움이 있을 수 있습니다.

2. NONAME 기술의 장점

  • DLL 크기 감소: 함수 이름을 저장할 필요가 없기 때문에, DLL 파일의 크기가 조금 줄어듭니다. 대규모 API나 많은 함수가 있는 DLL에서 유리합니다.
  • 보안 강화: 함수 이름이 노출되지 않으므로, 공격자가 함수 이름을 기반으로 공격하는 것을 어렵게 만들 수 있습니다. DLL의 API가 쉽게 후킹되거나 오용되는 것을 방지할 수 있습니다.
  • 간단한 호출: 프로그램은 ordinal 값만 알고 있으면, 해당 함수를 호출할 수 있습니다.

3. NONAME 기술의 단점

  • 가독성 및 유지보수 문제: 함수 이름이 없으면 코드 가독성이 떨어지며, 유지보수나 디버깅이 어려워질 수 있습니다.
  • 호출 오류 가능성: 잘못된 ordinal 값으로 함수를 호출하면, 예상치 못한 함수가 실행될 수 있습니다.
  • 명확한 인터페이스 부족: 함수 이름이 없기 때문에 외부 개발자가 인터페이스를 쉽게 이해하기 어렵습니다.

4. NONAME으로 함수 export 설정

DEF 파일을 사용하여 DLL의 export 함수를 NONAME 방식으로 설정할 수 있습니다.

DEF 파일 작성 예시


LIBRARY MyDLL
EXPORTS
    FunctionA @1 NONAME
    FunctionB @2 NONAME
    FunctionC @3 NONAME

    

이 예시에서 FunctionA, FunctionB, FunctionC는 각각 @1, @2, @3이라는 ordinal 값으로 export됩니다.

5. DLL과 NONAME 호출 예시

DLL 함수 구현 (MyDLL.cpp)


// MyDLL.cpp
#include <windows.h>

extern "C" __declspec(dllexport) void FunctionA() {
    MessageBox(NULL, "Function A Called", "MyDLL", MB_OK);
}

extern "C" __declspec(dllexport) void FunctionB() {
    MessageBox(NULL, "Function B Called", "MyDLL", MB_OK);
}

extern "C" __declspec(dllexport) void FunctionC() {
    MessageBox(NULL, "Function C Called", "MyDLL", MB_OK);
}

    

DEF 파일 설정 (MyDLL.def)


LIBRARY MyDLL
EXPORTS
    FunctionA @1 NONAME
    FunctionB @2 NONAME
    FunctionC @3 NONAME

    

NONAME 방식으로 함수 호출 (main.cpp)


#include <windows.h>
#include <iostream>

typedef void (*FunctionA)();
typedef void (*FunctionB)();
typedef void (*FunctionC)();

int main() {
    HMODULE hModule = LoadLibrary("MyDLL.dll");
    if (!hModule) {
        std::cerr << "DLL 로드 실패" << std::endl;
        return 1;
    }

    // Ordinal 값으로 함수 가져오기
    FunctionA funcA = (FunctionA)GetProcAddress(hModule, MAKEINTRESOURCE(1));  // @1에 해당하는 함수
    FunctionB funcB = (FunctionB)GetProcAddress(hModule, MAKEINTRESOURCE(2));  // @2에 해당하는 함수
    FunctionC funcC = (FunctionC)GetProcAddress(hModule, MAKEINTRESOURCE(3));  // @3에 해당하는 함수

    if (funcA) funcA();
    if (funcB) funcB();
    if (funcC) funcC();

    FreeLibrary(hModule);
    return 0;
}

    

6. 보안 강화 측면

NONAME 방식은 함수 이름을 숨김으로써 보안을 강화할 수 있습니다. 이는 공격자가 DLL 내부의 함수 이름을 쉽게 파악하고 악용하는 것을 방지할 수 있습니다. 그러나, 이 방식만으로는 충분하지 않으며 다른 보안 기법과 함께 사용하는 것이 좋습니다.

7. 결론

NONAME 기술은 DLL의 크기를 줄이고, 보안을 강화하는 데 유리하지만, 사용성과 유지보수 측면에서 어려움이 있습니다. 이 기술을 사용할 때는 장점과 단점을 신중히 고려하여 특정 상황에 맞게 사용하는 것이 좋습니다.

반응형