Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
pe-signgen — Winbindex를 사용하여 모든 Windows 빌드의 모든 시스템 함수에 대한 범용 서명 생성 | Kitploit
도구/GitHubGitHub/forentfraps/pe-signgen
Static AnalysisVulnerability AnalysisReverse EngineeringForensicsMalware AnalysisBinary Analysis
GitHubforentfraps/pe-signgen

pe-signgen

Winbindex를 사용하여 모든 Windows 빌드의 모든 시스템 함수에 대한 범용 서명 생성

저장소 보기
2039개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
웹사이트
공유

pe-signgen

Windows PE 함수용 크로스 버전 바이너리 시그니처 및 RVA 오프셋


개요

pe-signgen는 리버스 엔지니어와 보안 연구자를 위한 도구로, 다음 항목을 자동으로 생성합니다:

  • 비내보내기 및 내보내기 함수에 대한 바이너리 시그니처 (와일드카드가 포함된 바이트 패턴)
  • 바이너리에서 함수를 직접 찾기 위한 RVA 및 파일 오프셋
  • 여러 Windows 버전에서 작동하는 크로스 빌드 시그니처
  • 다양한 사용 사례에 최적화된 여러 출력 형식
  • x64, ARM64 및 WoW64 아키텍처 지원

핵심 아이디어는 Windows 10/11 빌드 전반에 걸쳐 체계적이고 견고한 방식으로 내보내지지 않은 함수에 접근하는 것입니다. 이를 위해 다음을 활용합니다:

  • Windows 빌드 메타데이터용 Winbindex
  • PDB를 위한 Microsoft 공개 기호 서버
  • 재현 가능하고 오프라인 친화적인 워크플로를 위한 로컬 캐싱

⚠️ Windows 버전 지원 pe-signgen은 Windows 10 및 Windows 11만 지원합니다. 이는 의도적인 설계 선택입니다: Winbindex는 이전 버전에 대한 완전한 데이터를 제공하지 않습니다.


사용 사례

  • 내보내지지 않은 Windows 내부 함수 LdrpInitializeTls, RtlpInsertInvertedFunctionTableEntry 등과 같은 함수에 대한 시그니처를 생성합니다.

  • 게임 해킹 / 안티치트 연구 게임 업데이트에도 유지되는 안정적인 시그니처 생성

  • 보안 연구 Windows 빌드 전반에서 보안에 중요한 루틴 찾기

  • 자동화 내부 API 전체 집합에 대한 스크립트 가능한 시그니처 및 오프셋 생성


  • 출력 형식

    pe-signgen은 다양한 사용 사례를 위해 세 가지의 서로 다른 출력 형식을 제공합니다:

    1. JSON 형식

    자동화, 스크립팅 및 다른 도구와의 통합을 위한 구조화된 데이터입니다.```bash pe-signgen --signature ntdll!NtCreateFile -o ntcreatefile.json --output-format json

    root@kitploit:~
    **출력 구조:**```json
    {
      "dll_name": "ntdll",
      "function_name": "NtCreateFile",
      "architecture": "x64",
      "generated": "2024-12-11T15:30:00.123456",
      "total_builds": 1247,
      "unique_signatures": 3,
      "signature_groups": [
        {
          "matched_symbol": "NtCreateFile",
          "signature": "4C 8B DC 49 89 5B 08 49 89 6B 10 49 89 73 18 ...",
          "length": 48,
          "build_count": 845,
          "versions": [
            { "major": 10240, "minor": 16384, "build": "10240.16384" },
            { "major": 10586, "minor": 0, "build": "10586.0" }
          ]
        }
      ]
    }
    

    Notes:

    • major 및 minor는 빌드 문자열을 첫 번째 .에서 분할하여 파생됩니다. 예: "10240.16384" → major = 10240, minor = 16384.
    • build는 내부적으로 사용되는 원래 빌드 문자열 키입니다.

    2. 바이너리 형식 (WSIG/WOFF)

    임베디드 시스템과 낮은 오버헤드 스캐닝에 최적화된 컴팩트하고 런타임 준비가 된 바이너리 형식입니다.

    이 형식들은 write_wsig() 및 write_woff()에 구현된 디스크 레이아웃과 일치합니다.


    WSIG 형식 (Windows 서명)

    매직: WSO\0 (0x57 0x53 0x4F 0x00) 현재 버전: 1 목적: 와일드카드 마스크 및 관련 Windows 빌드 버전과 함께 바이너리 서명을 저장합니다.

    파일 구조 (개념적)```

    ┌─────────────────────────────────────┐ │ Header (36 bytes) │ ├─────────────────────────────────────┤ │ DLL Name (variable) │ ├─────────────────────────────────────┤ │ Function Name (variable) │ ├─────────────────────────────────────┤ │ Signature / Mask / Build blobs │ ← Arbitrary order, see notes ├─────────────────────────────────────┤ ← Aligned to 4 bytes │ Groups Table (24 × N bytes) │ └─────────────────────────────────────┘

    root@kitploit:~
    **중요한 레이아웃 참고 사항(`write_wsig`와 일치)**
    
    * 헤더 다음에는 DLL 및 함수 이름이 UTF‑8 바이트로 기록됩니다.
    * 각 서명 그룹에 대해 패턴 바이트와 마스크 바이트가 기록된 다음 해당 그룹의 빌드 배열이 이어집니다.
    * 이러한 그룹별 영역은 유형별로 전역적으로 그룹화되지 **않습니다**: 패턴, 마스크 및 빌드 배열이 서로 인터리브될 수 있습니다.
    * 빌더는 각 빌드 배열 앞과 그룹 테이블 앞에서 **4바이트**로 정렬합니다. 이로 인해 패딩이 발생할 수 있습니다.
    * 소비자는 헤더 및 그룹 항목의 오프셋을 **항상** 따라야 하며, 물리적 연속성에 대해 개념 다이어그램에 의존하지 **마십시오**.
    
    ##### 헤더 레이아웃(36바이트)```c
    // Packed as: "<4sIIIIIIII" (little-endian)
    
    typedef struct {
        char     magic[4];   // "WSO\0" (WSIG_MAGIC)
        uint32_t version;    // FORMAT_VERSION (currently 1)
        uint32_t arch;       // Architecture code (1=x64, 2=ARM64, 3=WoW64)
        uint32_t dll_off;    // Offset to DLL name string
        uint32_t dll_len;    // Length of DLL name in bytes
        uint32_t func_off;   // Offset to function name string
        uint32_t func_len;   // Length of function name in bytes
        uint32_t group_count;// Number of signature groups
        uint32_t groups_off; // Offset to groups table
    } wsig_header_t; // 36 bytes
    
    그룹 항목 (24 bytes)

    각 시그니처 그룹은 하나 이상의 Windows 빌드에 적용되는 고유한 패턴을 나타냅니다.```c // Packed as: "<IIIIII" (little-endian)

    typedef struct { uint32_t sig_off; // Offset to signature pattern bytes uint32_t sig_len; // Length of signature pattern (in bytes) uint32_t mask_off; // Offset to wildcard mask bytes uint32_t mask_len; // Length of wildcard mask (≈ ceil(sig_len/8)) uint32_t builds_off; // Offset to build version array uint32_t build_cnt; // Number of builds using this signature } wsig_group_t; // 24 bytes

    root@kitploit:~
    ##### 빌드 버전 항목 (8바이트)
    
    각 빌드 항목은 이 서명을 사용하는 특정 Windows 버전을 식별합니다.```c
    typedef struct {
        uint32_t major; // e.g. 19041
        uint32_t minor; // e.g. 1234
    } wsig_build_t; // 8 bytes
    

    major와 minor는 빌드 문자열("A.B" → A, B)을 분할하여 얻습니다. 원본 빌드 문자열은 바이너리 형식에 저장되지 않습니다. 필요하다면 외부에 보관하십시오 (JSON 출력에 있습니다).

    와일드카드 마스크 형식

    마스크는 비트마스크로, 각 비트는 시그니처 패턴의 한 바이트에 대응합니다:

    • Bit = 1: 바이트가 정확히 일치해야 합니다 (고정 바이트)
    • Bit = 0: 바이트는 와일드카드입니다 (매칭 중 이 바이트를 무시합니다)

    예시:``` Signature: 4C 8B DC 49 89 ?? 08 49 Mask bits: 1 1 1 1 1 0 1 1 (MSB first within each byte) Mask byte: 0xBF (binary: 10111111)

    root@kitploit:~
    마스크 바이트는 각 바이트 내에서 **리틀 엔디안 비트 순서**로 저장되고 해석됩니다 (C 헬퍼 및 `parse_signature`에서 사용되는 것과 정확히 동일함):```c
    uint8_t bit = (mask_bytes[byte_index >> 3] >> (byte_index & 7)) & 1u;
    
    문자열 저장
    • DLL 및 함수 이름은 UTF‑8로, null 종결자 없이 저장됩니다.
    • 길이를 확인하려면 *_len을 사용하고, 그 이상 읽지 마십시오.
    • 문자열 자체에는 정렬 요구 사항이 없습니다.
    • 추가 데이터 영역(빌드 배열 및 그룹 테이블)은 4바이트 경계에 정렬됩니다. 패딩은 불투명한 것으로 취급하십시오.

    WOFF 형식 (Windows 오프셋)

    매직: WOF\0 (0x57 0x4F 0x46 0x00) 현재 버전: 1 목적: Windows 빌드 전반에 걸쳐 함수에 대한 직접 RVA 및 파일 오프셋 저장

    파일 구조```

    ┌─────────────────────────────────────┐ │ Header (36 bytes) │ ├─────────────────────────────────────┤ │ DLL Name (variable) │ ├─────────────────────────────────────┤ │ Function Name (variable) │ ├─────────────────────────────────────┤ │ Matched Symbol Names (variable) │ ← One UTF‑8 string per entry ├─────────────────────────────────────┤ ← Aligned to 4 bytes │ Entries Table (32 × N bytes) │ └─────────────────────────────────────┘

    root@kitploit:~
    레이아웃 세부 정보(`write_woff` 일치):
    
    * 헤더 자리 표시자 뒤에 DLL 및 함수 이름이 UTF‑8 바이트로 작성됩니다.
    * 각 빌드에 대해 일치하는 심볼 이름이 UTF‑8 문자열(종결자 없음)로 작성됩니다. 이들은 단순 문자열 풀을 형성합니다.
    * 그런 다음 작성자가 4바이트로 정렬하고 고정 크기 항목 테이블을 작성합니다.
    * 각 항목에는 이 문자열 풀을 가리키는 오프셋(`matched_off`, `matched_len`)이 포함됩니다.
    
    ##### 헤더 레이아웃(36바이트)```c
    // Packed as: "<4sIIIIIIII" (little-endian)
    
    typedef struct {
        char     magic[4];   // "WOF\0" (WOFF_MAGIC)
        uint32_t version;    // FORMAT_VERSION (currently 1)
        uint32_t arch;       // Architecture code (1=x64, 2=ARM64, 3=WoW64)
        uint32_t dll_off;    // Offset to DLL name string
        uint32_t dll_len;    // Length of DLL name in bytes
        uint32_t func_off;   // Offset to function name string
        uint32_t func_len;   // Length of function name in bytes
        uint32_t entry_cnt;  // Number of offset entries
        uint32_t entries_off;// Offset to entries table
    } woff_header_t; // 36 bytes
    
    Offset Entry (32바이트)

    각 항목은 Windows 빌드를 해당 빌드에서의 함수 위치에 매핑합니다.```c // Packed as: "<IIQQII" (little-endian)

    typedef struct { uint32_t major; // Windows major version (e.g., 19041) uint32_t minor; // Windows minor version (e.g., 1234) uint64_t rva; // Relative Virtual Address in the DLL uint64_t file_offset; // Raw file offset in the DLL on disk uint32_t matched_off; // Offset to matched symbol name string uint32_t matched_len; // Length of matched symbol name } woff_entry_t; // 32 bytes

    root@kitploit:~
    ##### 사용 참고 사항
    
    * **RVA**는 DLL이 선호 기본 주소에 로드될 때의 메모리 오프셋입니다.
    * **File offset**은 디스크의 PE 파일에서 원시(raw) 위치입니다.
    * **Matched symbol**은 요청된 함수와 다를 수 있습니다(예: 전달된 내보내기(forwarded exports)).
      문자열은 문자열 풀에 한 번 저장되며, `matched_off`/`matched_len`이 이를 참조합니다.
    * 항목은 빠른 조회를 위해 **빌드 버전**(`major`, 그다음 `minor`) 기준으로 정렬됩니다.
    
    ---
    
    #### 아키텍처 코드
    
    두 바이너리 형식 모두 동일한 아키텍처 인코딩(`ARCH_CODE_MAP` 사용)을 사용합니다:
    
    | Code | Architecture | Description                  |
    | ---- | ------------ | ---------------------------- |
    | 1    | x64          | 64비트 AMD64/Intel64         |
    | 2    | ARM64        | 64비트 ARM(AArch64)          |
    | 3    | WoW64        | 64비트 Windows의 32비트 x86  |
    
    알 수 없는 아키텍처 문자열은 내부적으로 기본값 `1`(x64)로 설정되며, CLI는 지원되는 집합으로 값을 제한합니다.
    
    ---
    
    ### 3. **C 헤더 형식**
    
    컴파일 준비가 된 C 헤더로, 타입 안전 구조체와 데이터 배열을 포함합니다.
    
    `pe-signgen`은 두 가지 *종류*의 C 헤더를 생성할 수 있습니다:
    
    * **WSIG 헤더** – 서명(signature) 및 마스크 데이터용 (`write_wsig_header`에서 생성).
    * **WOFF 헤더** – 직접 RVA/파일 오프셋 테이블용 (`write_woff_header`에서 생성).
    
    `--output-format cheader` 옵션은 C 헤더를 선택하며, 이를 `--offsets`와 결합하면 WSIG와 WOFF 변형 간에 전환됩니다.
    
    #### WSIG C 헤더```bash
    pe-signgen --signature ntdll!RtlpInitializeThreadActivationContextStack \
      -o rtlp_init_actx.h --output-format cheader
    

    생성된 헤더 구조(간소화, write_wsig_header와 일치):```c /* Auto-generated WSIG header for ntdll ! RtlpInitializeThreadActivationContextStack ! x64. */ #ifndef WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H #define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H

    #include <stdint.h> #include <stddef.h>

    #define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_DLL_NAME "ntdll" #define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_FUNCTION_NAME "RtlpInitializeThreadActivationContextStack" #define WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ARCH "x64"

    /* Per-version build identifier. */ typedef struct { uint32_t major; uint32_t minor; } WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t;

    /* Signature group entry. */ typedef struct { const uint8_t *pattern; const uint8_t *mask; uint32_t length; uint32_t build_count; const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t *versions; } WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t;

    /* One pattern/mask/versions triple per group. / static const uint8_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern[] = { / ... / }; static const uint8_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_mask[] = { / ... / }; static const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_version_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions[] = { { 10240u, 16384u }, / 10240.16384 / / ... */ };

    static const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS[] = { { WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern, WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_mask, (uint32_t)(sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern) / sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_pattern[0])), (uint32_t)(sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions) / sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions[0])), WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group0_versions }, /* group 0 (RtlpInitializeThreadActivationContextStack) / / ... */ };

    static const size_t WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUP_COUNT = sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS) / sizeof(WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_GROUPS[0]);

    #endif /* WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H */

    root@kitploit:~
    **통합 예시(생성된 타입과 일치하도록 수정됨):**```c
    #include "rtlp_init_actx.h"
    
    static inline int match_byte(uint8_t want, uint8_t got,
                                 const uint8_t *mbits, uint32_t i) {
        uint8_t bit = (mbits[i >> 3] >> (i & 7)) & 1u;
        return bit ? (want == got) : 1;
    }
    
    static const uint8_t *
    find_signature(const uint8_t *base, size_t size,
                   const uint8_t *pattern,
                   const uint8_t *mbits,
                   uint32_t sig_len) {
        if (!base || !pattern || !mbits || sig_len == 0)
            return NULL;
        if (size < sig_len)
            return NULL;
    
        // Find first non-wildcard byte as anchor
        uint32_t anchor = sig_len;
        for (uint32_t i = 0; i < sig_len; ++i) {
            if ((mbits[i >> 3] >> (i & 7)) & 1u) {
                anchor = i;
                break;
            }
        }
        if (anchor == sig_len)
            return base; // all wildcards
    
        const uint8_t anchor_val = pattern[anchor];
        const size_t last_pos = size - (size_t)sig_len;
    
        for (size_t pos = 0; pos <= last_pos; ++pos) {
            if (base[pos + anchor] != anchor_val)
                continue;
    
            uint32_t i = 0;
            for (; i < sig_len; ++i) {
                if (!match_byte(pattern[i], base[pos + i], mbits, i))
                    break;
            }
            if (i == sig_len)
                return base + pos;
        }
        return NULL;
    }
    
    static void
    fetch_signature(uint32_t major, uint32_t minor,
                    const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *groups,
                    size_t group_len,
                    const uint8_t **signature_dest,
                    const uint8_t **mask_dest,
                    uint32_t *signature_len_dest) {
        *signature_dest = NULL;
        *mask_dest = NULL;
        *signature_len_dest = 0;
    
        const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *closest = NULL;
        uint32_t best_distance = 0xFFFFFFFFu;
    
        for (size_t gi = 0; gi < group_len; ++gi) {
            const WSIG_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_group_t *g = &groups[gi];
            for (uint32_t vi = 0; vi < g->build_count; ++vi) {
                uint32_t m = g->versions[vi].major;
                uint32_t n = g->versions[vi].minor;
    
                uint32_t distance = (m > major ? m - major : major - m) * 10000u +
                                    (n > minor ? n - minor : minor - n);
    
                if (distance < best_distance) {
                    best_distance = distance;
                    closest = g;
                }
    
                if (m == major && n == minor) {
                    *signature_dest = g->pattern;
                    *mask_dest = g->mask;
                    *signature_len_dest = g->length;
                    return;
                }
            }
        }
    
        if (closest) {
            *signature_dest = closest->pattern;
            *mask_dest = closest->mask;
            *signature_len_dest = closest->length;
        }
    }
    

    그런 다음 이를 자신만의 로더별 코드에 연결할 수 있습니다(예: GetModuleHandleA 사용, PE 섹션 탐색 등). 이 헤더는 의도적으로 데이터만 제공하며, 헬퍼 함수는 사용자가 직접 구현해야 합니다.

    WOFF C 헤더

    오프셋 전용 사용 사례의 경우, write_woff_header는 (major, minor, rva, file_offset) 항목들의 정렬된 테이블을 설명하는 작은 헤더를 생성합니다.

    레이아웃(write_woff_header와 일치):```c /* Auto-generated WOFF header for ntdll ! RtlpInitializeThreadActivationContextStack ! x64. */ #ifndef WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H #define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H

    #include <stdint.h> #include <stddef.h>

    #define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_DLL_NAME "ntdll" #define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_FUNCTION_NAME "RtlpInitializeThreadActivationContextStack" #define WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ARCH "x64"

    /* Per-build offset entry. */ typedef struct { uint32_t major; uint32_t minor; uint64_t rva; uint64_t file_offset; } WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_entry_t;

    static const WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_entry_t WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES[] = { { 10240u, 16384u, 0x5B195ULL, 0x5A595ULL }, /* 10240.16384 (RtlpInitializeThreadActivationContextStack) / / ... (sorted by major, then minor) ... */ };

    static const size_t WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRY_COUNT = sizeof(WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES) / sizeof(WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_ENTRIES[0]);

    #endif /* WOFF_NTDLL_RTLPINITIALIZETHREADACTIVATIONCONTEXTSTACK_X64_H */

    root@kitploit:~
    이는 오프셋 자체를 신뢰하고 패턴 매칭이 필요하지 않을 때 유용합니다.
    
    ---
    
    ## 설치
    
    ### 사전 요구 사항
    
    * Python 3.8+
    * Git
    * 인터넷 연결 (최초 실행 시)
    * 전체 캐시를 위한 ~10GB 디스크 공간
    
    ### Pip으로 설치```bash
    pip install pe-signgen
    

    소스에서 설치```bash

    git clone https://github.com/forentfraps/pe-signgen.git cd pe-signgen pip install -r requirements.txt pip install -e .

    root@kitploit:~
    ---
    
    ## 빠른 시작
    
    ### 서명 생성```bash
    pe-signgen --signature ntdll!LdrLoadDll
    

    오프셋 생성```bash

    pe-signgen --signature kernel32!CreateFileW --offsets

    root@kitploit:~
    ### JSON으로 저장```bash
    pe-signgen --signature ntdll!NtCreateFile -o out.json --output-format json
    

    명령줄 옵션

    기본 구문```bash

    pe-signgen --signature DLL!FUNCTION [OPTIONS]

    root@kitploit:~
    ### 아키텍처```bash
    --arch x64   # default
    --arch arm64
    --arch wow64
    

    버전 필터링```bash

    --os-version win10 # Only Windows 10 --os-version win11 # Only Windows 11 --min-version 10.0 # Minimum version --max-version 11.0 # Maximum version

    root@kitploit:~
    ### 서명 길이 제어```bash
    --min-length 32          # Minimum signature length
    --max-length 64          # Maximum signature length
    

    출력 옵션```bash

    -o, --output PATH # Output file path --output-format FORMAT # json | binary | cheader --offsets # Generate offsets instead of signatures

    root@kitploit:~
    ### 성능```bash
    --workers 16             # Parallel workers (default: CPU count)
    --no-cache               # Disable caching
    --no-git-update          # Skip Winbindex updates
    

    상세 수준```bash

    --verbose # Detailed output --quiet # Minimal output --no-progress # Disable progress bars

    root@kitploit:~
    ---
    
    ## 캐싱
    
    ### 캐시 레이아웃```text
    ~/.cache/pe-signgen/
    │
    ├── dlls/           # Downloaded DLLs
    ├── pdbs/           # Downloaded PDBs
    ├── signatures/     # Generated signatures
    └── winbindex_data/ # Winbindex metadata
    

    캐시 제어```bash

    Disable cache for fresh generation

    pe-signgen --signature ntdll!NtCreateFile --no-cache

    Clear cache

    rm -rf ~/.cache/pe-signgen

    Custom cache location

    export PE_SIGNGEN_CACHE=/custom/path pe-signgen --signature ntdll!NtCreateFile

    root@kitploit:~
    ---
    
    ## 성능
    
    **예시 성능 (12코어 CPU, 100 Mbps):**
    
    | 작업                         | 시간        |
    | --------------------------------- | ----------- |
    | 첫 실행 (캐시 없음)              | 5–10분    |
    | 캐시된 실행                        | < 1초     |
    | 빌드당 분석                | 0.1–0.5초 |
    | 전체 실행 (빌드 1000개, 워커 8개) | 2–4분     |
    
    **리소스 요구 사항:**
    
    * **디스크:** 전체 DLL/PDB 캐시에 약 10GB
    * **메모리:** 최대 약 500MB 사용
    * **네트워크:** 첫 실행 시 수 GB
    
    ---
    
    ## 알려진 제한 사항
    
    * **Windows 버전 범위:** Windows **10 및 11**만 지원 (Winbindex 제한)
    * **빌드 가용성:** 모든 Win10/11 빌드가 Winbindex에 존재하는 것은 아님
    
    ---
    
    ## 개발```bash
    git clone https://github.com/forentfraps/pe-signgen.git
    cd pe-signgen
    pip install -e ".[dev]"
    
    # Code formatting
    black pe_signgen/
    
    # Type checking
    mypy pe_signgen/
    

    라이선스

    MIT 라이선스 – LICENSE를 참조하세요.


    크레딧

    • Winbindex – @m417z의 Windows 빌드 메타데이터
    • pefile – PE 파싱 라이브러리
    • winpdb-rs – PDB 파싱 Python 바인딩

    내부 Windows API를 위한 강력하고 자동화된 시그니처 생성의 필요성에서 영감을 받았습니다.


    기여

    기여를 환영합니다! 다음을 따라주세요:

    1. 저장소를 포크하세요
    2. 기능 브랜치를 만드세요
    3. 새 기능에 대한 테스트를 추가하세요
    4. 풀 리퀘스트를 제출하세요

    지원

    • 이슈: GitHub Issues
    • 토론: GitHub Discussions
    도구 다운로드