본문 바로가기
Study/리버싱

PE Structure (3) DLL

by 꼬부기가우는소리 2016. 6. 29.
728x90


참고 도서 : [리버싱 핵심원리 : 악성 코드 분석가의 리버싱 이야기]

저자 : 이승원

출판사 : 인사이트


참고 사이트 :

- [위키백과] 동적 링크 라이브러리

- [WIKIPEDIA] Dynamic-link library

- [Microsoft] DLL은 무엇입니까?

- [텀즈] DLL (dynamic link library)

- [sck.pe.kr] DLL이란 무엇인가?



DLL

DLL (Dynamic Linked Library)은 우리말로 '동적 연결 라이브러리'라고 하며 마이크로소프트 윈도우에서 구현된 동적 라이브러리이다. 코드와 데이터를 지니고 있으며 동시에 하나 이상의 프로그램에서 사용할 수 있다. 내부에는 다른 프로그램이 불러서 쓸 수 있는 다양한 함수들을 가지고 있다.


사용 방법

(1) 묵시적 링킹 (Implicit Linking)

프로그램 시작할 때 같이 로딩되어 프로그램 종료할 때 메모리에서 해제된다.


(2) 명시적 링킹 (Explicit Linking)

프로그램에서 사용되는 순간에 로딩하고 사용이 끝나면 메모리에서 해제된다.


장점

- 프로그램에 라이브러리를 포함시키지 않고 별도의 파일(DLL)로 구성하여 필요할 때마다 불러쓸 수 있다.

- 일단 한 번 로딩된 DLL의 코드, 리소스는 Memory Mapping 기술로 여러 Process에서 공유해서 쓸 수 있다.

- 라이브러리가 업데이트 되었을 때 해당 DLL 파일만 교체하면 되어 쉽고 편하다.



DLL과 실행 파일

일반적으로 라이브러리는 C/C++ program에서 컴파일한 뒤 링크할 때 이 라이브러리에서 서브루틴들을 가져다가 실행파일을 만든다.


(1) Compile 단계

C/C++ program의 소스 코드를 기계어 코드로 (어셈블리어 코드) 번역하는 것을 말한다. C/C++에는 미리 만들어 놓은 공용 함수인 수많은 표준함수들이 있다. 표준 라이브러리 파일 안에 어셈블리 코드의 형태로 담겨 있다. 후에 링크할 때 표준 라이브러리에서 가져다 연결할 것이다.


(2) Link 단계

프로그램의 구조가 복잡해질 수록 소스파일의 수도 여러개로 나뉘게 된다. 링크 단계에서는 이 여러개의 소스 파일들을 번역된 어셈블리 파일들과 함께 묶에 실행 파일을 생성한다. 이 때 각각의 소스파일에서 호출한 표준함수들을 표준 라이브러리에서 빼내어 만들어진 실행 파일에 붙여준다.


일반적인 컴파일의 경우 static library라고 한다. 과정은 아래와 같다.





(3) 실행 단계

실행할 때는 실행 파일을 메모리로 읽어들여 OS에서 실행하게 된다.


만약 이 때 실행파일 속에 프로세스끼리 서로 겹쳐진 영역이 존재한다면, 공용 코드를 하나의 DLL 파일 속에 어셈블리의 형태로 넣고 실행파일의 용량을 줄일 수 있다. DLL 속에는 각각의 함수들의 시작 지점을 가리키고 있는 엔트리 포인트가 있기 때문에 가능하다. 엔트리 포인트를 얻어낼 수 있다면 일종의 메모리 쉐어 (Memory Share)와 같은 효과를 낼 수 있다.


static library가 아닌 dynamic linked library (DLL)의 경우는 아래와 같다.





유닉스에서는 SO 또는 DSO (Dynamic Shared Object, 동적 공유 객체)가 존재한다.



DLL 사용 과정

링크 시 DLL에 들어갈 어셈블리 함수들은 그 함수 이름과 엔트리 포인트를 DLL 앞부분에 저장해 놓는다. 그리고 메인 실행파일 (DLL 호출)에는 DLL에 있는 함수의 몸체를 빈 부분으로 남겨두고 DLL의 함수를 호출할 엔트리 포인트 (참조 포인트)를 확보해 둔다.


실행파일을 생성 후, 메인 실행파일을 실행하면 메모리에 적재될 때 DLL 파일을 메모리에서 탐색하여 이미 메모리에 존재 시 이미 적재된 DLL의 엔트리 포인트와 자기 함수 내부의 DLL Reference point를 서로 연결한다.


일한 DLL을 가지고 잇는 실행파일이 메모리에 적재되면 이미 DLL이 메모리에 적재되어 있기 때문에 굳이 새로 적재하지 않는다. 이와 같은 방식으로 여러개의 메인 실행 파일이 올라오더라도 동일한 DLL 파일이 하나만 적재되어 있으면 동작이 가능하다. 메모리 사용의 효율성이 늘어나게 된다.


시작 포인트 주소에 DLL의 메모리 적재 시작 번지를 더한 값이 Main 실행파일의 공용 함수 (DLL 속 함수) 호출 주소가 된다.



C Programming 예시

(1) Creating DLL exports


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <windows.h>
 
// DLL entry function (called on load, unload, ...)
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    return TRUE;
}
 
// Exported function - adds two numbers
extern "C" __declspec(dllexportdouble AddNumbers(double a, double b)
{
    return a + b;
}
cs



(2) Using DLL imports


1
2
3
4
5
6
7
8
9
10
11
12
#include <windows.h>
#include <stdio.h>
 
// Import function that adds two numbers
extern "C" __declspec(dllimportdouble AddNumbers(double a, double b);
 
int main(int argc, char *argv[])
{
    double result = AddNumbers(12);
    printf("The result was: %f\n", result);
    return 0;
}
cs



(3) Using explict run-time linking

Warning : The following code is vulnerable, it doesn't conform to Microsoft's guidance for safe library loading!


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
31
32
33
34
35
36
37
38
#include <windows.h>
#include <stdio.h>
 
// DLL function signature
typedef double (*importFunction)(doubledouble);
 
int main(int argc, char **argv)
{
    importFunction addNumbers;
    double result;
        HINSTANCE hinstLib;
 
    // Load DLL file
    hinstLib = LoadLibrary(TEXT("Example.dll"));
    if (hinstLib == NULL) {
        printf("ERROR: unable to load DLL\n");
        return 1;
    }
 
    // Get function pointer
    addNumbers = (importFunction) GetProcAddress(hinstLib, "AddNumbers");
    if (addNumbers == NULL) {
        printf("ERROR: unable to find DLL function\n");
        FreeLibrary(hinstLib);
        return 1;
    }
 
    // Call function.
    result = addNumbers(12);
 
    // Unload DLL file
    FreeLibrary(hinstLib);
 
    // Display result
    printf("The result was: %f\n", result);
 
    return 0;
}
cs




728x90

'Study > 리버싱' 카테고리의 다른 글

RegFsNotify (1) 파일 시스템 변화 알림  (0) 2016.07.07
Registry  (0) 2016.07.06
PE Structure (2) PE 헤더  (1) 2016.06.29
PE Structure (1) PE 포맷  (0) 2016.06.19
Stack  (0) 2016.06.12

댓글