이전에 만들었던 DLL을 실제로 사용하는 방법에 대해서 포스팅한다 ..
두 가지 방법이 있다 ..
먼저 .LIB파일을 사용하는 암시적인 방법과 .. 명시적인 방법이 있다.
암시적인 방법은 .LIB파일을 링크옵션에 추가시켜주어서 링크하는 것인데 이 방법을 사용하기
위해서는 당연히 .LIB파일이 필수적으로 존재해야 한다.
위 스크린샷 처럼 dll.LIB를 추가시켜주고 실제 dll에 구현되어 있는 함수를 가져다가 쓰면 된다.
무척이나 간단한 방법이다 ..
명시적인 방법에 대해서 알아보자.
명시적인 방법은 .LIB가 없는 경우에 사용되면 좋다.
하지만 그러기 위해서는 먼저 dll에 구현되어 있는 정확한 함수의 이름 ..
그리고 함수의 리턴 타입.. 아규먼트 형식과 갯수등을 매우 정확하게 알고 있어야 한다.
명시적인 방법에서 사용되는 주요 함수가 LoadLibrary와 GetProcAddress이다..
첫 번째 함수는 dll을 로드해서 인스턴스를 반환하고 GetProcAddress 는 LoadLibrary를 통해서
받은 dll 인스턴스를 통해서 인자로 넘겨주는 심볼의 함수 주소를 가져온다.
즉 실제 구현된 함수의 포인터를 가져오는 것이다.
간단한 예제를 통해 알아보자.
위 코드는 함수 포인터를 선언하는 내용이다.
위에서 잠깐 말했듯이 명시적인 DLL사용방법을 쓰기 위해서는 DLL 에 구현되어 있는 함수의
리턴 타입과 아규먼트 타입을 잘 알아야 한다고 하였다 ..
위에서 처럼 함수 포인터를 선언할 때 꼭 DLL에서 구현된 함수와 같은 타입으로 해주어야
실제 사용할 때 에러가 없다.
위 코드에서는 LoadLibrary를 사용하고 있다. 인자로 로드할 dll의 파일명을 넘겨준다.
그런데 반환되는 타입을 보니 HMODULE이다. 위에서는 인스턴스라고 했는데?
HMODULE과 HINSTANCE는 각각 16비트 시절에 코드역역과 데이터영역을 나누는데에서 의미가
있었지만 32비트로 넘어오면서 이 두개의 차이가 없어졌다.
아무튼 .. 반환된 값은 hDll로 넘겨지게 되고 if 문을 사용해서 로드가 되었는지 안되었는지 먼저
확인을 한다 ..
이제 GetProcAddress를 사용해서 포인터를 구해오고 그 포인터를 해당 함수형으로 타입캐스팅을
한 다음 실제 사용할 함수 포인터에 넣어준다.
이때 GetProcAddress의 두 번째 인자는 실제 DLL의 Export 정보에 등록된 이름이어야 한다.
만약 조금이라도 틀리면 포인터를 얻어올 수 없다,
이렇게 얻어온 함수 포인터는 if문으로 평가되어서 로드가 되었는지 안되었는지 확인한다.
두 가지 방법을 알아보았는데 두 가지 모두 장단점이 있는것 같다..
먼저 .LIB를 사용하는 암시적인 방법은 실제 프로그램을 개발하는 입장에서는 사용하기 편리하다.
그러나 만약 DLL이 없거나 DLL 안에 구현된 함수를 얻어오지 못하는 등의 예외상황에서
유연한 대처가 힘들다 ..
그러나 명시적인 사용방법에서는 그러한 예외상황에 대해서 유연하게 대처가 가능하다
위에서 본 코드들 처럼 if 문을 사용해서 예외처리가 가능하기 때문이다 ..
그리고 해커적인 입장에서는 명시적인 사용방법에 대해서 잘 인지하고 있다면 리버싱등을 할때
좋은 힌트가 될 수 있을것 같다.
[출처] [PE구조] DLL 사용하기 ~!!|작성자 비누방울