[2025 하계 모각코] 2회차

안우진·2025년 7월 21일
1

모각코

목록 보기
15/19

dll 을 직접 만들고 사용해보기

1. 만들기

visual studio를 사용했습니다.

New -> Project -> Dynamic-Link Library (DLL) 로 프로젝트를 만든 후 아래와 같이 c파일을 하나 만듭니다.

#include "pch.h"
#include <windows.h>
#include <stdio.h>

__declspec(dllexport) short add(short a, short b) {
    return a + b;
}

__declspec(dllexport) void fuzz_entry(const unsigned char* data, size_t size) {
    if (size < 4) return;

    short a = *(short*)(data);
    short b = *(short*)(data + 2);

    short arr[22222];
	for (int i = 0; i < 22222; i++) {
		arr[i] = i;
	}
    short c = add(a, b);
    arr[c] = 0;
	printf("add(%d, %d) = %d\n", a, b, c);
}

C언어 임을 명시하기 위해 Project -> Property -> C/C++ -> Advanced -> Compile As 의 값을 Compile as C Code (/TC) 로 변경합니다. 이후 Ctrl + Shift + B 로 빌드하면 프로젝트\x64\Debug 에 dll이 빌드됩니다.

눈에 띄는 것은 pch.h, windows.h, dllexport 가 있습니다.

2. 사용하기

이번에는 DDL이 아닌 Console App 으로 로젝트를 만든 후 아래와 같이 c파일을 만듭니다.

#include <windows.h>
#include <stdio.h>

typedef int (*AddFunc)(int, int);

int main() {
    HMODULE hDll = LoadLibraryA("testdll.dll");
    if (!hDll) {
        printf("DLL 로드 실패\n");
        return 1;
    }

    AddFunc add = (AddFunc)GetProcAddress(hDll, "add");
    if (!add) {
        printf("함수 찾기 실패\n");
        return 1;
    }

    int result = (int)add(1, 2);
    printf("1 + 2 = %d\n", result);

    FreeLibrary(hDll);
    return 0;
}

마찬가지로 C로 exe파일로 빌드합니다. dll파일을 exe에 동일한 위치에 두고 exe를 실행하면 정상적으로 1 + 2 = 3 을 출력합니다.

프로그램 실행 중 필요한 시점에서 dll을 로드하고 해제할 수 있습니다.

winafl 시작하기

아래와 같이 winafl을 빌드합니다.

# git clone winafl
# cd winafl
mkdir build32
cd build32
cmake -G"Visual Studio 17 2022" -A Win32 .. -DDynamoRIO_DIR=C:\DynamoRIO\cmake
cmake --build . --config Release
# git clone winafl
# cd winafl
mkdir build64
cd build64
cmake -G"Visual Studio 17 2022" -A x64 .. -DDynamoRIO_DIR=C:\DynamoRIO\cmake
cmake --build . --config Release

위에서 만든 dll을 기반으로 harness 코드를 작성합니다.

#include <windows.h>
#include <stdio.h>

typedef void (*FuzzEntryFunc)(const unsigned char*, size_t);

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Usage: harness.exe <fuzz input file>\n");
        return 1;
    }

    HMODULE hDll = LoadLibraryA("testdll.dll");
    if (!hDll) {
        printf("DLL 로드 실패\n");
        return 1;
    }

    FuzzEntryFunc fuzz_entry = (FuzzEntryFunc)GetProcAddress(hDll, "fuzz_entry");
    if (!fuzz_entry) {
        printf("함수 찾기 실패\n");
        FreeLibrary(hDll);
        return 1;
    }

    FILE* file = nullptr;
    if (fopen_s(&file, argv[1], "rb") != 0) {
        printf("퍼징 데이터 파일 열기 실패\n");
        FreeLibrary(hDll);
        return 1;
    }

    fseek(file, 0, SEEK_END);
    size_t size = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char* data = (unsigned char*)malloc(size);
    fread(data, 1, size, file);
    fclose(file);

    fuzz_entry(data, size);

    free(data);
    FreeLibrary(hDll);
    return 0;
}

C:\\winafl\\input 에 예시 입력(ex. \x01\x02\x03\x04)을 여러 개 넣었습니다.

아래의 명령어로 퍼징을 시작합니다.

# cd winafl
cd build64/bin/Release
afl-fuzz.exe -D C:\DynamoRIO-Windows-11.3.0-1\bin64 ^
  -i "C:\\winafling\\input" -o "C:\\winafling\\output" -t 5000 -- ^
  -coverage_module testdll.dll -target_module testdll.dll -target_method fuzz_entry ^
  -fuzz_iterations 5000 -nargs 1 -- ^
  C:\winafling\testharness.exe @@
  • 중간 결과
                    WinAFL 1.17 based on AFL 2.43b (testharness.exe)
    
    +- process timing -------------------------------------+- overall results ----+
    |        run time : 0 days, 0 hrs, 4 min, 18 sec       |  cycles done : 42    |
    |   last new path : 0 days, 0 hrs, 3 min, 44 sec       |  total paths : 5     |
    | last uniq crash : 0 days, 0 hrs, 4 min, 17 sec       | uniq crashes : 2     |
    |  last uniq hang : none seen yet                      |   uniq hangs : 0     |
    +- cycle progress --------------------+- map coverage -+----------------------+
    |  now processing : 3 (60.00%)        |    map density : 0.07% / 0.08%        |
    | paths timed out : 0 (0.00%)         | count coverage : 1.21 bits/tuple      |
    +- stage progress --------------------+ findings in depth --------------------+
    |  now trying : splice 1              | favored paths : 1 (20.00%)            |
    | stage execs : 95/96 (98.96%)        |  new edges on : 3 (60.00%)            |
    | total execs : 327k                  | total crashes : 453 (2 unique)        |
    |  exec speed : 1406/sec              |  total tmouts : 0 (0 unique)          |
    +- fuzzing strategy yields -----------+---------------+- path geometry -------+
    |   bit flips : 0/96, 0/93, 0/87                      |    levels : 2         |
    |  byte flips : 0/12, 0/9, 0/3                        |   pending : 0         |
    | arithmetics : 0/672, 0/563, 0/0                     |  pend fav : 0         |
    |  known ints : 0/45, 0/285, 0/120                    | own finds : 2         |
    |  dictionary : 0/0, 0/0, 0/0                         |  imported : n/a       |
    |       havoc : 3/121k, 1/204k                        | stability : 94.23%    |
    |        trim : n/a, 0.00%                            +-----------------------+
    +-----------------------------------------------------+   [cpu000001:  13%]
    의도한 uniq crashes; Array Index Out of Bounds Exception, Overflow 2개 모두 발견됐습니다.

0개의 댓글