17 Jun
2015
Posted in: 코드
By    2 Comments

[플밍노트] GetProcAddress를 편리하게 사용하는 방법


[플밍노트] GetProcAddress를 편리하게 사용하는 방법
by 신영진(YoungJin Shin), codewiz at gmail.com, @codemaru, http://www.jiniya.net

윈도우의 경우 9x와 NT 계열의 함수 세트가 틀린 경우가 있다. 9x에만 존재하는 함수가 있는가 하면, NT에만 존재하는 함수도 있다. 이러한 경우 한 프로그램이 두가지 환경에서 모두 동작해야 하는 경우에 주로 LoadLibrary를 사용해서 해당 함수들을 동적으로 불서서 사용한다. 물론 그 외에도 동적으로 불러쓰는 경우는 매우 많다.

이렇게 LoadLibrary를 통해서 함수를 불러 쓸 때 가장 불편한 점은 함수 포인터를 반환받는 과정이다. 함수 하나하나 마다 모두 GetProcAddress로 함수 포인터를 받아야 하기 때문이다. 이러한 과정을 좀 더 간소화 시킬 수 없을까? 여기에 대한 답이 www.codeproject.com에 나와있다. 바로 가변 인자를 사용한 방법이다. 아래 함수는 실제 원문에 있던 함수를 약간 수정한 버전이다. 출구를 하나로 통일하고, 함수 로드에 실패한 경우에는 항상 DLL을 언로드 하도록 변경했다. 실제 원문은 http://www.codeproject.com/dll/dllease.asp 에서 확인할 수 있다.

GetProcAddresses

소스 코드 다운로드

BOOL GetProcAddresses( HINSTANCE *hLibrary, LPCSTR lpszLibrary, INT nCount, ... )
{
    BOOL bRet = TRUE;
    va_list va;
    va_start( va, nCount );
    
    if ( ( *hLibrary = LoadLibrary( lpszLibrary ) ) 
        != NULL )
    {
        FARPROC * lpfProcFunction = NULL;
        LPSTR lpszFuncName = NULL;
        INT nIdxCount = 0;
        while ( nIdxCount < nCount )
        {
            lpfProcFunction = va_arg( va, FARPROC* );
            lpszFuncName = va_arg( va, LPSTR );
            if ( ( *lpfProcFunction = 
                GetProcAddress( *hLibrary, 
                lpszFuncName ) ) == NULL )
            {
                lpfProcFunction = NULL;
                bRet = FALSE;
                break;
            }
            nIdxCount++;
        }
    }
    else
    {
        bRet = FALSE;
    }
    va_end( va );
    
    if(bRet == FALSE && *hLibrary != NULL)
        FreeLibrary(*hLibrary);
    
    return bRet;
}

사용하는 방법은 무척이나 간단하다. 첫번째 인자로 리턴받을 DLL인스턴스 핸들을, 두번째 인자로 DLL 파일명을, 세번째 인자로 로드할 함수 갯수를, 그 다음부터는 함수 포인터의 포인터와, 함수명을 교대로 적어주면 된다. 말로하니 매우 복잡한데, 실제 사용예를 보면 금방 알 수 있다. 아래는 kernel32.dll에서 CreateFileW와 CloseHandle 함수를 로드하는 방법을 보여준다.

HINSTANCE hinst;
GetProcAddresses(&hinst, "kernel32.dll", 2, 
                 &fnCreateFileW, "CreateFileW", 
                 &fnCloseHandle, "CloseHandle");


  • 트랙백 주소: http://www.jiniya.net/wp/archives/11204/trackback

관련 글

  • l lawliet

    xez인가 xkaga인가 안에 모듈 이름이랑 proc name을 둘다 받는 함수가 있길래 초보적인 설계다 싶었는데, 가변적인 인자를 쓰고 있진 않더군요. 결과적으로 실사용은 불편하면서도 비효율적이기만 하다고 할 수 있겠습니다.
    va_xxx 류 함수들은 아시다시피 여러의미에서 취약하고 elegant하지 않으니, variadic template을 사용해보시는게 어떨까 조언 드립니다.

  • YoungJin Shin

    안녕하세요. 댓글 감사합니다. 혹시 게임 보안 쪽에 관심 있으시면 제 메일로 연락 한 번 부탁 드립니다.