본문으로 건너뛰기
5분 AI.
GITHUB TRENDING C++ WEEKLY #9 딥다이브 · 2026-10-23 분석

ImHex 딥다이브
— 바이트에 이름을 붙이면 파일의 설계도가 보인다

데스크탑 분석도구

빠른 판단

무엇
바이트 편집에 패턴 언어·디스어셈블·해시·YARA·시각화를 결합한 C++ 헥스 편집기
이럴 때
실행 파일·게임 저장·미디어 파일의 필드 구조를 해석하고 바이트를 수정하며 분석 플러그인을 확장할 때
입력
바이너리 파일과 구조를 설명하는 패턴·규칙
결과
필드별 해석·시각화·검색 결과와 수정 파일
사진·실행 파일·게임 저장 데이터는 컴퓨터 안에서 모두 바이트의 나열입니다. ImHex는 그 숫자를 살펴보고, 구조를 정의하고, 해석 결과를 화면에 연결하는 C++ 바이너리 분석 도구입니다. 이 글에서는 작은 파일 하나를 출발점으로 데이터 추상화·플러그인·이벤트·비동기 실행을 배웁니다. WerWolv/ImHex · C++ · ⭐55,522 · 포크 2,565 · 2026-10-23 GitHub 기준. 소스 설명은 커밋 34483cb 기준입니다.
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

숫자 배열을 파일 형식의 언어로 읽게 해주는 데스크톱 도구

ImHex는 16진수 편집기와 구조 해석기를 한 화면에 결합한 오픈소스 프로그램입니다. 바이트를 수정하는 기본 기능에 Pattern Language, 디스어셈블러, 해시 계산, 데이터 시각화, YARA 규칙 검색, 플러그인이 붙습니다. 핵심은 파일을 숫자로 보여주는 데서 나아가, 그 숫자가 어떤 필드인지 사람이 설명할 수 있게 만든다는 점입니다.

용어
바이트·16진수·오프셋
바이트는 8비트짜리 데이터 단위입니다. 값은 0~255이며, 16진수로 쓰면 00~FF 두 자리입니다. 오프셋은 파일 시작에서 몇 바이트 떨어졌는지를 나타냅니다. 첫 바이트의 오프셋은 0입니다.

1-1. 같은 바이트도 해석 규칙에 따라 의미가 달라진다

아래는 학습용으로 정의한 18바이트 형식입니다. 앞의 12바이트는 헤더이고, 뒤의 6바이트는 내용입니다. 01 00만 보고서는 이것이 숫자 1인지, 숫자 256인지, 서로 독립적인 두 값인지 알 수 없습니다. 데이터와 해석 규칙을 함께 알아야 의미가 생깁니다.

# 학습용 형식: IMHX 헤더 + 6바이트 내용
오프셋   바이트                                  의미
0x00     49 4D 48 58                             "IMHX"
0x04     01 00                                   버전 1
0x06     03 00                                   항목 수 3
0x08     06 00 00 00                             내용 길이 6
0x0C     41 42 43 44 45 46                       "ABCDEF"

ImHex의 Pattern Editor에 다음과 같은 규칙을 적으면, 각 구간을 필드 이름과 연결할 수 있습니다. u16은 2바이트 부호 없는 정수, u32는 4바이트 부호 없는 정수입니다. 이 예제는 Pattern Language 코드이며 C++ 코드와는 다릅니다.

#pragma endian little

struct DemoHeader {
    char magic[4];
    u16 version;
    u16 count;
    u32 payload_size;
};

DemoHeader header @ 0x00;
한 문장 비유

헥스 화면이 창고의 물건 목록이라면, 패턴은 상자에 붙이는 분류표입니다

49 4D 48 58이라는 물건 네 개에 magic이라는 이름을 붙이고, 다음 두 개에는 version을 붙입니다. 분류표가 있으면 매번 눈으로 숫자를 세지 않아도 됩니다.

하지만 잘못된 분류표를 붙이면 그럴듯한 오답이 나옵니다. 길이·바이트 순서·필드 경계를 검증하는 일이 바이너리 분석의 출발점입니다.

1-2. 이 저장소를 공부하면 연결되는 것들

읽기 목표
처음부터 모든 기능을 이해할 필요는 없습니다

우선 FileProvider::readRaw()에서 바이트가 어디서 오는지 보고, configureRuntime()에서 그 바이트를 해석기에 어떻게 넘기는지 따라가세요. 이 두 지점이 연결되면 나머지 기능의 위치를 찾기 쉬워집니다.

2왜 주목받는가

기능의 연결 방식과 소스 공개가 만드는 학습 가치

2-1. 트렌딩 순위와 상승 원인은 구분해서 읽자

2026-10-23 분석 기준 선정 위치는 GitHub Trending C++ Weekly #9입니다. 스타 55,522개와 포크 2,565개는 누적 관심을 보여주지만, 그 수치만으로 이번 주 유입 원인을 설명할 수는 없습니다. 특정 홍보·영상·신규 릴리스가 순위 상승을 일으켰다는 인과관계는 확인되지 않았습니다.

코드와 기능에서 읽을 수 있는 주목 포인트는 분명합니다. 바이트 편집, 구조 해석, 시각화, 확장 API가 하나의 데이터 인터페이스를 공유하므로 기능 사이를 오가며 분석할 수 있습니다. 여기에 구현 자체가 공개되어 있어 도구의 동작을 소스로 검증할 수 있다는 장점이 있습니다.

2-2. 경쟁 도구와는 무엇을 비교해야 할까

비교의 기준은 “무엇을 주로 읽을 것인가”입니다. 아래는 전체 성능 순위가 아니라 대표적인 작업 흐름의 비교입니다. 같은 기능이 여러 제품에 있어도 설계의 중심은 다를 수 있습니다.

도구분석의 중심ImHex에서 배울 장점
일반 헥스 편집기 바이트 탐색·검색·직접 수정 구조 정의와 시각화까지 연결해 반복적인 수작업을 줄이는 설계
010 Editor 텍스트·헥스 편집과 Binary Templates 기반의 계층적 해석 유사한 구조 해석 문제를 공개된 Pattern Language 연동 코드와 C++ 플러그인 API로 공부할 수 있음
Ghidra 디스어셈블·디컴파일·그래프 등 실행 코드의 역공학 임의 파일 형식의 필드·바이트·통계에 집중하기 좋은 흐름. 디컴파일 기능의 대체재로 단정할 수 없음

010 Editor도 구조 해석을 지원하므로 “ImHex만 파일 구조를 읽는다”는 비교는 부정확합니다. 비교 근거는 010 Editor 공식 소개와 Ghidra 공식 소개입니다. ImHex의 학습상 강점은 그 기능이 연결되는 내부 코드를 끝까지 읽을 수 있다는 것입니다.

2-3. 한 기능이 여러 화면에서 재사용된다

plugins/builtin/source/content/views.cpp의 registerViews()는 ViewHexEditor, ViewPatternEditor, ViewPatternData, ViewInformation 등을 같은 등록 API에 넣습니다. 각 화면을 별도 프로그램으로 만들지 않고, 공통 환경 안에 배치하는 방식입니다.

확장도 같은 흐름을 따릅니다. plugins/disassembler/CMakeLists.txt는 Capstone과 별도 libdisassembler를 연결하고, plugins/decompress/CMakeLists.txt는 찾은 압축 라이브러리만 활성화합니다. 큰 제품이 기능별 의존성을 분리하는 사례입니다.

2-4. 최근 커밋을 읽을 때의 관찰 포인트

분석 대상 커밋은 2026-10-08의 34483cb이며, 제목은 Pattern Editor의 데이터 경쟁과 충돌 수정에 관한 것입니다. view_pattern_editor.cpp에는 런타임 잠금, 로그 잠금, 비동기 실행, UI 상태가 함께 나옵니다. 이 복잡함은 “화면이 있는 언어 도구”를 만들 때 동시성이 왜 중요한지 보여줍니다.

비유

편집자는 원고를 바꾸고, 분석가는 같은 원고를 읽고, 인쇄 담당자는 결과를 화면에 내보냅니다. 셋이 동시에 같은 종이를 고치면 충돌합니다. 작업 속도를 높이는 것만큼 누가 언제 어떤 상태를 소유하는지 정하는 일이 중요합니다.

3기술 스택 전체 지도

C++ 네이티브 앱을 중심으로 해석기·GUI·빌드 도구를 나누어 보기

이 프로젝트의 기본 실행 단위는 데스크톱 프로세스입니다. 웹 서비스에서 말하는 백엔드와 프론트엔드를 그대로 대입하기보다, 데이터·분석 계층 / 화면 계층 / 빌드·배포 계층으로 읽으면 명확합니다. 데이터베이스 서버나 Node.js 서버가 핵심 구성 요소인 구조는 아닙니다.

3-1. 백엔드에 해당하는 데이터·분석 계층

기술역할실제 근거·버전
C++23 공통 API, 데이터 접근, 작업 관리, 플러그인 구현 루트 CMakeLists.txt: CMAKE_CXX_STANDARD 23
Pattern Language 파일 구조를 정의하고 바이트를 필드로 해석 lib/external/pattern_language, 서브모듈 커밋 300d738으로 버전 고정
nlohmann/json 설정과 구조화된 메시지 처리 동봉 lib/third_party/nlohmann_json/CMakeLists.txt: 3.11.3
mbedTLS·libmagic 암호 관련 기능·파일 종류 식별 cmake/build_helpers.cmake: 3.4.0 이상, 5.39 이상 요구
Capstone·YARA 기계어 해석·규칙 기반 바이트 검색 plugins/disassembler, plugins/yara_rules. 동봉 버전은 서브모듈 커밋을 참조하며, 시스템 Capstone도 선택 가능
zlib 등 압축 라이브러리 압축 데이터 해제 기능을 선택적으로 제공 plugins/decompress/CMakeLists.txt: ZLIB, BZip2, LibLZMA, ZSTD, LZ4 탐색

3.4.0 이상은 설치된 라이브러리의 확정 버전이 아니라 CMake의 최소 요구값입니다. 시스템 라이브러리를 쓰는 옵션과 동봉 코드를 쓰는 옵션도 다릅니다. 예를 들어 시스템 nlohmann/json은 find_package(nlohmann_json 3.10.2 REQUIRED)를 사용합니다.

3-2. 프론트엔드에 해당하는 화면 계층

기술화면에서 하는 일확인 위치
Dear ImGui 도킹 창, 버튼, 메뉴, 입력과 프레임 구성 lib/third_party/imgui/imgui/include/imgui.h: 1.92.7 WIP
ImPlot·ImPlot3D 2차원·3차원 그래프 각 include/implot.h, include/implot3d.h: 0.17, 0.3 WIP
ImNodes 노드를 선으로 연결하는 데이터 처리 화면의 기반 lib/third_party/imgui/imnodes. 버전 번호는 별도로 확정하지 않음
GLFW·OpenGL 네이티브 창·입력과 GUI 렌더링 루트 기본값 IMHEX_RENDERING_BACKEND="GLFW"; 백엔드 CMake에서 OpenGL 탐색

main/gui/source/window/window.cpp에서 frameBegin()은 ImGui::NewFrame()을 호출하고, frame()은 등록된 뷰를 그리며, frameEnd()는 렌더링을 마무리합니다. HTML DOM을 갱신하는 웹 UI와는 다른 실행 흐름입니다.

3-3. 인프라·빌드·언어 확장

설정의 차이 읽기
README의 지원 안내와 실제 검사 조건이 완전히 같지는 않습니다

README는 MSVC와 AppleClang을 지원하지 않는다고 안내합니다. 그러나 verifyCompiler()는 GCC 12 이상·Clang 17 이상을 검사하고, MSVC 분기는 비어 있습니다. build.yml에도 Windows MSVC 작업이 있습니다. 따라서 “CMake가 MSVC를 무조건 거부한다”고 설명할 수 없습니다.

반대로 이 작업 정의만으로 모든 MSVC 환경에서 빌드가 성공한다고 보장할 수도 없습니다. AppleClang은 허용된 GNU·Clang 식별자에 포함되지 않습니다. 빌드 가능 여부는 컴파일러·표준 라이브러리·의존성을 함께 확인해야 합니다.

버전 숫자를 읽을 때는 앱 버전, 동봉 라이브러리 버전, 최소 요구 버전, 서브모듈 커밋을 구별해야 합니다. 이 구분만 익혀도 낯선 C++ 저장소의 빌드 오류를 훨씬 정확히 해석할 수 있습니다.

4아키텍처 심화 분석

파일을 읽는 계층과 기능을 연결하는 계층을 따로 추적하기

4-1. 전체 흐름: 실행 파일은 환경을 만들고, 플러그인은 기능을 채운다

main/gui/source/main.cpp의 main()은 메인 스레드 ID, 충돌 처리, 네이티브 초기화, 인스턴스 간 메시징을 준비한 뒤 init::runImHex()로 들어갑니다. 데스크톱 구현은 GLFW 초기화, 시작 화면의 초기화 작업, 메인 Window::loop(), 정리 순서로 진행됩니다.

[main()] | v [init::runImHex() / initializeImHex()] | +--- [PluginManager / Plugin::initializePlugin()] | | | v | [Built-in / other plugins] | | | v | [ContentRegistry: Views / Providers / Functions] | v [Window::loop()] | +--- [ViewHexEditor] -----------+ +--- [ViewInformation] --------+---> [prv::Provider] +--- [ViewPatternEditor] | | | | +--- [FileProvider] v | +--- [MemoryFileProvider] [TaskManager worker] | +--- [GDBProvider / others] | | v | [PatternLanguage runtime] -+ | v [patterns / logs / errors] | +---> [doLater(): EventPatternExecuted] ---> [UI]

그림에서 중요한 연결은 런타임에서 Provider로 향하는 선입니다. 해석기는 파일 핸들을 직접 열지 않아도 됩니다. ImHex가 공급하는 읽기·쓰기 콜백을 통해 현재 데이터에 접근합니다. 전체 연결을 한 번 파악한 뒤 아래 네 가지 설계를 읽으면 세부 코드의 목적이 드러납니다.

4-2. 설계 ① 데이터 접근을 바꾸는 Provider 추상화

lib/libimhex/include/hex/providers/provider.hpp의 prv::Provider는 readRaw(), writeRaw(), getActualSize() 같은 인터페이스를 정의합니다. 화면이 구체적인 파일 구현 대신 이 인터페이스에 의존하므로 다른 데이터 원천을 붙일 수 있습니다. 같은 작업을 다른 구현에 맡기는 전략 교체의 관점으로 읽을 수 있습니다.

// Provider의 실제 선언 중 핵심 부분 발췌
virtual void read(u64 offset, void *buffer,
                  size_t size, bool overlays = true);
virtual void write(u64 offset, const void *buffer, size_t size);
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0;
[[nodiscard]] virtual u64 getActualSize() const = 0;
용어
추상 인터페이스와 다형성
“어디서 읽는지는 달라도, 이 주소에서 이 길이만큼 읽을 수 있다”는 약속을 먼저 정하는 방식입니다. = 0인 함수는 구현을 하위 클래스에 맡깁니다. 호출자는 구체적인 파일·메모리 구현을 몰라도 같은 함수로 작업합니다.

lib/libimhex/source/providers/provider.cpp의 Provider::read()는 기준 주소를 뺀 오프셋으로 readRaw()를 호출하고, 필요하면 오버레이를 적용합니다. 따라서 화면 주소와 파일 오프셋은 항상 같지 않습니다. 기준 주소가 0x1000이면 화면의 0x1004는 파일 오프셋 4에 해당합니다.

plugins/builtin/source/content/providers/file_provider.cpp의 FileProvider::open()은 기본 128_MiB 설정을 기준으로 접근 방식을 나눕니다. 그 이상이면 직접 파일 접근 경로를 선택하고, 처음에는 쓰기를 꺼 둔 뒤 화면에서 허용할 수 있게 합니다. 작은 일반 파일의 메모리 적재 경로와 큰 파일의 직접 접근 경로를 구별해야 합니다.

바이트 수정이 실제 저장소까지 가는 경로

Provider::write()는 곧바로 writeRaw()를 호출하지 않습니다. 먼저 변경 이벤트를 발행합니다. ViewPatches가 이를 받아 이전·이후 바이트를 보관하는 OperationWrite를 만들고, 되돌리기 스택이 작업을 적용합니다.

[Hex editor / pasteBytes()] | v [Provider::write()] | v [EventProviderDataModified::post()] | v [ViewPatches subscriber] | v [undo::Stack::add<OperationWrite>()] | v [OperationWrite::redo() ---> Provider::writeRaw()] | +--- undo() ---> old bytes +--- redo() ---> new bytes

근거는 plugins/builtin/source/content/views/view_patches.cpp, plugins/builtin/include/content/providers/undo_operations/operation_write.hpp, lib/libimhex/source/providers/undo/stack.cpp입니다. Stack::add()는 redo 기록을 비우고 새 작업의 redo()를 실행합니다. 새 편집 뒤에 예전 redo가 사라지는 이유를 코드로 설명할 수 있습니다.

편집 동작
되돌리기 기록과 디스크 저장 시점은 다른 문제입니다

FileProvider::writeRaw()는 메모리 적재 상태에서는 버퍼를 바꾸고, 직접 접근 상태에서는 파일 쓰기 함수를 호출합니다. 따라서 모든 파일이 저장 버튼을 누를 때까지 원본 디스크에 반영되지 않는다고 가정하면 안 됩니다. 실습에는 복사본을 사용하세요.

4-3. 설계 ② 플러그인과 Registry·Factory

lib/libimhex/source/api/plugin_manager.cpp의 Plugin::Plugin(path)는 Windows에서는 LoadLibraryW(), 다른 데스크톱 환경에서는 dlopen()으로 라이브러리를 읽고 initializePlugin 등의 진입점을 찾습니다. Plugin::initializePlugin()은 요청한 호환 버전을 검사한 뒤 초기화 함수를 호출합니다.

기본 기능도 예외가 아닙니다. plugins/builtin/source/plugin_builtin.cpp의 IMHEX_PLUGIN_SETUP_BUILTIN 안에서 registerProviders(), registerViews(), registerPatternLanguageFunctions() 등을 호출합니다. 실행 파일에 기능을 직접 늘어놓기보다 등록 API를 통해 채우는 구조입니다.

// plugins/builtin/source/content/providers.cpp 발췌
ContentRegistry::Provider::add<FileProvider>(true);
ContentRegistry::Provider::add<IntelHexProvider>();
ContentRegistry::Provider::add<MemoryFileProvider>(true);

// plugins/builtin/source/content/views.cpp 발췌
ContentRegistry::Views::add<ViewHexEditor>();
ContentRegistry::Views::add<ViewPatternEditor>();

ContentRegistry::Provider::add<T>()는 타입 이름과 생성 함수를 등록합니다. ContentRegistry::Views::add<T>()는 뷰 객체를 만들어 등록합니다. 둘 다 std::derived_from 제약을 써서 올바른 기반 클래스를 상속한 타입만 받습니다. 등록소는 “무엇이 있는가”를 관리하고, 팩토리는 “어떻게 만들 것인가”를 담당합니다.

비유

Registry는 공구 카탈로그이고 Factory는 주문받은 공구를 만들어 주는 창구입니다. 분석 화면은 공구의 제작법을 몰라도 카탈로그의 공통 규격을 통해 사용할 수 있습니다.

웹 빌드는 같은 플러그인을 모두 동적으로 읽는다고 보면 안 됩니다. dist/web/Dockerfile은 IMHEX_STATIC_LINK_PLUGINS=ON을 지정하고 script_loader;remote를 제외합니다. 플랫폼에 따라 확장 기능의 묶음과 로딩 방식이 달라집니다.

4-4. 설계 ③ 발행·구독으로 화면 사이 연결하기

lib/libimhex/include/hex/api/event_manager.hpp에는 subscribe(), unsubscribe(), post()가 있습니다. 한 기능이 이벤트를 보내면 구독한 기능들이 반응합니다. 예를 들어 편집 계층은 변경 이벤트를 보내고, 패치 화면은 그것을 받아 편집 이력을 관리합니다.

// 학습용 의사 코드: 이벤트의 흐름만 요약
EventProviderDataModified::subscribe(owner, onBytesChanged);
EventProviderDataModified::post(provider, offset, size, bytes);
EventProviderDataModified::unsubscribe(owner);

여기서 post()라는 이름에 주의하세요. 구현은 해당 이벤트의 구독 목록을 순회하며 현재 호출 스레드에서 콜백을 직접 실행합니다. 메시지를 큐에 넣고 나중에 처리하는 비동기 버스가 아닙니다. std::recursive_mutex를 사용한다는 사실도 모든 구독자 상태의 안전을 자동으로 보장하지는 않습니다.

배울 점은 “발행자는 구독자를 몰라도 된다”는 결합도 완화와 그 대가입니다. 호출 관계가 파일 사이로 흩어지므로, 이벤트 이름을 검색해 구독자까지 함께 읽어야 실제 실행 경로가 보입니다. 객체가 사라질 때 구독 해제도 살펴봐야 합니다.

4-5. 설계 ④ 작업 큐와 UI 반영 경계

lib/libimhex/source/api/task_manager.cpp의 TaskManager::init()은 hardware_concurrency() 값에 따라 std::jthread 작업자를 만들고, 조건 변수와 작업 큐를 사용합니다. 긴 해석 작업을 화면 루프와 분리하는 기반입니다.

ViewPatternEditor::evaluatePattern()의 중요한 단계는 다음과 같습니다. 근거 파일은 plugins/builtin/source/content/views/view_pattern_editor.cpp입니다.

  1. getRuntimeLock()을 잡고 런타임과 화면의 이전 실행 상태를 정리합니다.
  2. TaskManager::createTask()에 평가 작업을 넘깁니다.
  3. 작업 안에서 configureRuntime(runtime, provider)로 데이터 원천을 연결합니다.
  4. 중단 콜백·로그 콜백·위험 함수 호출 처리기를 설정하고 runtime.executeString()을 호출합니다.
  5. 완료 뒤 TaskManager::doLater()를 통해 EventPatternExecuted 발행을 예약합니다.
// configureRuntime()의 데이터 연결 부분 발췌
runtime.setDataSource(
    provider->getBaseAddress(), provider->getActualSize(),
    [provider](u64 offset, u8 *buffer, size_t size) {
        provider->read(offset, buffer, size);
    },
    [provider](u64 offset, const u8 *buffer, size_t size) {
        if (provider->isWritable())
            provider->write(offset, buffer, size);
    }
);

TaskManager::doLater()는 콜백을 별도 목록에 저장하고, 화면의 Window::frameBegin()에서 runDeferredCalls()가 이를 실행합니다. 작업을 큐에 넣는 API와 이벤트를 즉시 발행하는 API를 구분해야 UI 스레드를 잘못 건드리지 않습니다.

용어
탭별 상태와 스레드 안전성
getRuntime()은 PerProvider<pl::PatternLanguage>를 사용합니다. 여러 파일의 상태를 나누는 장치입니다. 반면 잠금은 동시에 같은 상태를 만지지 못하게 하는 장치입니다. 데이터를 나누는 것과 접근 순서를 정하는 것은 별개의 설계입니다.

새 기능을 읽을 때는 데이터가 어디서 오고, 누가 상태를 소유하며, 어느 스레드에서 결과가 반영되는지를 함께 추적하세요. 이 세 질문으로 GUI·플러그인·언어 런타임의 연결을 설명할 수 있습니다.

5디렉토리 구조 해부

화면 이름보다 책임의 경계를 기준으로 읽기
ImHex/ +-- CMakeLists.txt 빌드 옵션과 최상위 타깃 +-- VERSION 1.39.0.WIP +-- main/ | +-- gui/source/ | | +-- main.cpp 프로그램 진입점 | | +-- init/ 초기화·실행·정리 | | +-- window/ 프레임 루프와 OS별 처리 | +-- forwarder/ 실행 인자 전달용 프로그램 | +-- updater/ 업데이트 보조 프로그램 +-- lib/ | +-- libimhex/ | | +-- include/hex/api/ 공개 API·등록소·이벤트 | | +-- include/hex/providers/ 데이터 접근·상태·편집 이력 | | +-- source/ 위 API의 구현 | +-- external/ 별도 프로젝트 서브모듈 | | +-- pattern_language/ 구조 해석 언어 본체 | | +-- libwolv/ 공통 유틸리티 | | +-- libromfs/ 내장 리소스 처리 | | +-- disassembler/ 디스어셈블 기반 | +-- third_party/ GUI·JSON 등 외부 라이브러리 | +-- trace/ 예외·스택 추적 기반 +-- plugins/ | +-- builtin/ | | +-- source/content/ 뷰·Provider·패턴·기능 등록 | | +-- include/content/ 기본 기능의 선언·도우미 | | +-- romfs/ 언어·테마·MCP 스키마 등 | +-- ui/ 공통 위젯·텍스트 편집기 | +-- fonts/ 글꼴·아이콘 지원 | +-- hashes/ 해시 계산 화면과 알고리즘 등록 | +-- disassembler/ 기계어 해석 화면 | +-- yara_rules/ YARA 검색 | +-- diffing/ 데이터 비교 | +-- decompress/ 압축 해제 확장 | +-- remote/ 원격 데이터 접근 | +-- script_loader/ C·.NET 스크립트 연결 +-- tests/ 공통·도우미·알고리즘·플러그인 테스트 +-- cmake/ 빌드 도우미·모듈·SDK 템플릿 +-- dist/ 배포별 의존성·패키징·웹 빌드 +-- resources/ OS별 배포 리소스 +-- .github/workflows/ CI·릴리스 자동화

5-1. 이름이 비슷한 세 계층을 구별하자

예를 들어 버튼을 눌렀을 때 동작을 찾고 싶다면 main.cpp부터 전부 읽기보다 plugins/builtin/source/content/views/에서 화면을 찾으세요. 그 화면이 호출하는 hex/api와 Provider를 거슬러 올라가면 범위를 좁힐 수 있습니다.

5-2. 코드 규모: 외부 코드와 앱 코드를 나누어 보기

아래는 커밋 34483cb의 파일을 확장자별로 센 물리 줄 수입니다. 줄바꿈 문자 LF를 세므로 마지막에 줄바꿈이 없는 줄은 제외합니다. 빈 줄·주석을 포함하며, lib/third_party/와 lib/external/은 제외했습니다. 글꼴·아이콘 헤더 등 선언이 많은 파일은 포함되므로 순수 기능 구현량과 같지는 않습니다.

언어·파일 종류파일 수물리 줄 수
C++·공통 헤더512117,457
Objective-C2909
C#7545
Python6745
JavaScript2296
GLSL8209
CMake524,338

C++·공통 헤더의 집계 대상은 .cpp·.hpp·.h·.cppm입니다.

C++·헤더의 주요 위치파일 수물리 줄 수
plugins/builtin19646,412
lib/libimhex17430,491
plugins/ui3215,416
main265,414
tests132,274

외부 디렉터리까지 포함해 존재하는 C++·헤더 파일을 세면 738개, 473,305줄입니다. 이 차이는 동봉 GUI·JSON 등 외부 코드의 비중을 보여줍니다. 미전개 서브모듈 본체는 어느 수치에도 포함되지 않으므로 전체 의존성까지 합친 완전한 제품 코드량이라고 부를 수 없습니다.

디렉터리별 줄 수를 먼저 나누면, 수십만 줄의 저장소도 지금 읽을 책임 범위로 좁힐 수 있습니다. 처음에는 main 전체보다 Provider → FileProvider → configureRuntime의 짧은 경로부터 읽는 편이 좋습니다.

6학습 포인트 (기술별)

문법을 외우는 대신 코드가 해결하는 문제를 하나씩 선택하기

6-1. C++ 타입·소유권: 누구의 객체인가

ContentRegistry::Views::add()는 std::make_unique<T>()로 뷰를 만들고 등록소에 넘깁니다. Provider 생성 API에는 std::shared_ptr도 등장합니다. 같은 스마트 포인터라도 소유자가 하나인가, 여러 곳이 함께 수명을 유지해야 하는가라는 질문은 다릅니다.

실습 아이디어: lib/libimhex/include/hex/api/content_registry/views.hpp와 lib/libimhex/include/hex/api/content_registry/provider.hpp를 나란히 읽고, 생성 함수의 반환 타입과 보관 타입을 표로 정리하세요. 이어서 런타임 콜백의 [provider] 캡처가 데이터 자체의 복사인지 포인터 값의 복사인지 설명해 보세요. 포인터를 캡처한다고 대상의 수명이 자동 연장되는 것은 아닙니다.

6-2. 바이너리 해석: 엔디언과 길이 필드

앞의 예제에서 01 00은 little endian u16으로 1입니다. 순서를 반대로 해석하면 256이 됩니다. C++ 구조체의 sizeof는 패딩 때문에 파일 형식의 길이와 다를 수 있으므로, 파일의 레이아웃과 메모리 레이아웃을 혼동하지 마세요.

실습 아이디어: tests/algorithms/source/endian.cpp의 changeEndianness<u32>() 검사와 tests/helpers/source/encoding.cpp의 UTF-16 LE·BE 사례를 읽으세요. 같은 바이트가 정수·문자·문자열 중 무엇으로 해석되는지 별도로 적어 보면 바이트 순서와 문자 인코딩의 차이가 보입니다.

6-3. GUI: 화면 상태는 어디에 남는가

ImGui의 즉시 모드에서는 매 프레임 UI를 기술합니다. 그렇다고 사용자 상태가 사라지는 것은 아닙니다. 파일별 콘솔·편집기 상태는 PerProvider<T> 같은 저장 공간에 남습니다. lib/libimhex/include/hex/providers/provider_data.hpp에서 Provider 열기 이벤트와 상태 생성의 연결을 볼 수 있습니다.

실습 아이디어: 두 파일을 연 상황을 종이에 그려 보세요. 탭 A의 오류 메시지가 탭 B에 보이지 않으려면 어떤 상태가 전역이고 어떤 상태가 Provider별이어야 할지 분류합니다. 그 뒤 view_pattern_editor.cpp의 .get(provider) 호출을 찾아 예상과 비교하세요.

6-4. 동시성: 취소와 완료도 설계의 일부다

Task::update()는 진행률을 갱신하면서 중단 요청을 확인하고, 요청이 있으면 TaskInterruptor를 던집니다. 취소 버튼을 만드는 일은 버튼만 그리는 일이 아닙니다. 반복 작업이 적절한 간격으로 취소 상태를 확인해야 합니다.

실습 아이디어: Task::interrupt(), Task::update(), 작업자의 예외 처리 분기를 이어 읽으세요. “중단 요청 → 작업의 확인 → 정리 → 완료 상태 반영”을 네 칸 도식으로 정리합니다. 잠금을 오래 잡을 때 어떤 화면 동작이 기다릴지도 예상해 보세요.

6-5. 통계: 엔트로피는 판정이 아니라 관찰값이다

InformationByteAnalysis::process()는 선택한 영역을 한 번 순회하면서 바이트 분포·종류 분포·구간 엔트로피를 함께 갱신합니다. 파일은 plugins/builtin/source/content/data_information_sections.cpp입니다. 엔트로피 구간 크기 설정이 0이면 256바이트를 사용합니다.

# diagrams.hpp의 calculateEntropy()를 수식으로 풀면
p[b] = 바이트 b의 등장 횟수 / 구간의 바이트 수
H = -sum(p[b] * log2(p[b]))
화면에 쓰는 정규화 값 = min(1, H / 8)

# 같은 바이트만 반복: 0에 가까움
# 256종류가 고르게 등장: 1에 가까움

수식 구현은 plugins/builtin/include/content/helpers/diagrams.hpp의 DiagramChunkBasedEntropyAnalysis::calculateEntropy()에 있습니다. 화면의 힌트는 평균값이 0.83보다 크고 최고 구간값이 0.9보다 클 때 나타납니다. 압축 데이터와 암호화 데이터는 모두 높은 값을 보일 수 있으므로 그 숫자만으로 암호화 여부를 확정할 수 없습니다.

실습 아이디어: 0만 반복하는 파일과 0~255가 반복하는 파일을 같은 길이로 준비한다고 가정하고 분포를 먼저 예상하세요. 구간 길이를 줄였을 때 값이 어떻게 달라질지도 설명해 보면 통계의 표본 크기를 배울 수 있습니다.

6-6. MCP·JSON-RPC: 화면 기능을 외부 도구로 노출하기

이 커밋에는 MCP 연동도 있습니다. plugins/builtin/source/content/mcp_tools.cpp는 파일 열기·열린 데이터 목록·데이터 선택·읽기 도구를 등록합니다. ViewPatternEditor::registerHandlers()에는 패턴 실행·콘솔 조회·결과 조회 도구 등록도 있습니다.

plugins/builtin/romfs/mcp/tools/read_data.json은 입력 스키마를 정의하며, 구현은 한 번의 읽기를 16_MiB로 제한하고 결과 바이트를 Base64로 돌려줍니다. 여기서 Base64는 암호화가 아니라 JSON 문자열로 옮기기 위한 인코딩입니다.

실습 아이디어: 읽기 도구의 스키마와 콜백을 비교해 보세요. “문법상 숫자”라는 조건과 “현재 파일 범위에 들어가는 유효한 주소”라는 조건을 구분해 입력 검증 표를 만듭니다. 서버 구현의 JSON-RPC 오류 처리만으로 모든 도구 인자가 검증된다고 가정하지 않는 것이 핵심입니다.

이 저장소의 학습 가치는 개별 라이브러리를 쓰는 법보다, 타입·상태·작업·입력 검증을 서로 연결하는 방법에 있습니다.

6-7. 테스트·CI: 정상값보다 경계를 먼저 읽자

tests/helpers/source/common.cpp의 TestProvider_read는 8바이트 데이터에서 오프셋 7부터 2바이트를 읽는 경계 초과 요청을 검사합니다. 대상 버퍼가 바뀌지 않는지도 확인합니다. 성공한 값만 비교하는 테스트보다 API의 실패 계약을 더 잘 드러냅니다.

.github/workflows/tests.yml은 AddressSanitizer·LeakSanitizer·UndefinedBehaviorSanitizer를 켜고 ctest --output-on-failure를 실행하도록 정의합니다. IMHEX_OFFLINE_BUILD=ON일 때 일부 네트워크 테스트는 tests/helpers/CMakeLists.txt에서 제외됩니다. 테스트 구성의 존재와 실제 통과 여부는 별개의 정보입니다.

7하드웨어 / 시스템 요구사항

앱을 사용하는 조건과 소스를 빌드하는 조건은 다르다

7-1. 사용 환경: README의 최소 안내

항목README 기준 안내읽을 때 주의할 점
WindowsWindows 7 이상, 10/11 권장 배포 파일별 의존성과 지원 범위를 별도로 확인해야 함
macOS배포 바이너리 기준 macOS 15 이상 이전 버전은 직접 빌드 가능성을 안내하지만 호환성 보장은 아님
Linux·FreeBSD현대적인 Linux 배포판, FreeBSD 14.3 테스트 안내 배포판별 패키지·AppImage·Flatpak·Snap 및 직접 빌드 경로가 다름
CPUx86·AMD64·ARM64 공식 지원 안내 다른 little endian CPU의 가능성은 README 설명이며 별도 검증이 필요
GPU일반 빌드에서 OpenGL 3.0 이상 일부 Windows Intel HD 드라이버의 그래픽 문제를 README가 안내
메모리·저장 공간약 50MiB·약 100MiB 앱의 기본 사용 안내값. 큰 파일 분석·패턴 결과·편집 이력의 상한이 아님

-NoGPU 릴리스는 README 기준 소프트웨어 렌더링 대안입니다. GPU 가속보다 느릴 수 있습니다. 머신러닝 모델을 돌리는 도구가 아니므로 CUDA GPU나 대용량 VRAM을 기본 조건으로 삼을 이유는 없습니다.

7-2. 파일 크기만으로 메모리 사용량을 계산하면 안 된다

FileProvider::open()의 128_MiB는 메모리 적재 여부를 가르는 기본 설정값입니다. 전체 앱의 메모리 한도나 최대 파일 크기가 아닙니다. 패턴이 생성하는 객체 수, 문자열·배열 크기, 통계 버퍼, 이전·이후 바이트를 보관하는 편집 이력이 추가 비용을 만듭니다.

비유

책 한 권의 무게만 보고 공부방 전체의 무게를 알 수는 없습니다. 원본 파일은 책이고, 해석한 필드·그래프·되돌리기 기록은 노트와 복사본입니다. 분석 방식에 따라 부가 자료가 더 커질 수 있습니다.

7-3. 개발 환경: 최소 검사값과 실제 CI 조합

루트 기준 CMake는 3.25 이상이며 C++23을 요구합니다. verifyCompiler()의 하한은 GCC 12·Clang 17이지만, Linux 테스트 CI와 Linux 빌드 안내는 GCC 16을 사용합니다. 최소 버전 검사를 통과하는 것과 모든 최신 코드가 성공적으로 컴파일되는 것은 같은 약속이 아닙니다.

서브모듈과 시스템 의존성도 필요합니다. detectBadClone()는 외부 의존성 디렉터리가 비어 있으면 오류를 냅니다. 빌드 학습에서는 먼저 .gitmodules, dist/compiling/, CI 설정을 읽고 툴체인 조합을 정리하는 것이 좋습니다. 구체적인 빌드 시간·필요 RAM·동시 작업 수는 CPU와 환경에 따라 달라 고정 수치로 보장할 수 없습니다.

7-4. 웹 버전의 범위

dist/web/Dockerfile은 의존성에도 -pthread를 붙이며 wasm32-emscripten을 사용합니다. 웹에서는 registerProviders()의 OS_WEB 조건 때문에 데스크톱과 같은 Provider가 모두 등록되지 않습니다. 브라우저 권한과 샌드박스가 있으므로 디스크·프로세스 메모리·원격 기능을 그대로 기대하면 안 됩니다.

8직접 해볼 수 있는 실습 과제

작은 입력·예상 결과·확인 기준을 함께 정하기

아래 다섯 과제는 읽기에서 시작해 작은 구현으로 확장합니다. 1~3번은 배포 앱과 별도 학습 파일을 사용할 수 있고, 4~5번은 소스를 수정할 수 있는 별도 실습 환경을 전제로 합니다. 과제의 완료 기준을 코드 작성량이 아니라, 입력을 바꿨을 때 결과가 왜 달라지는지 설명할 수 있는가로 잡으세요.

과제 1 · 입문

18바이트 파일을 손으로 해석하기 30~45분

목표: 오프셋·정수 크기·little endian을 연결합니다.

할 일: 아래 명령은 새 학습 파일을 만드는 예입니다. 파일을 ImHex로 열고, 0x04에서 2바이트를 선택해 버전 값을 확인합니다. 복사본의 01 00을 02 00으로 바꿔 보세요.

python3 - <<'PY'
from pathlib import Path
raw = bytes.fromhex(
    "49 4D 48 58 01 00 03 00 06 00 00 00 41 42 43 44 45 46"
)
Path("demo.bin").write_bytes(raw)
PY

완료 기준: 총 길이 18바이트, 헤더 길이 12바이트, 내용 시작 0x0C를 설명합니다. 0x04의 두 바이트를 big endian으로 해석했을 때 256이 되는 이유도 적습니다.

소스 연결: tests/algorithms/source/endian.cpp에서 순서 변환의 기대값을 읽습니다.

과제 2 · 입문

패턴으로 필드에 이름 붙이기 45~60분

목표: 숫자 배열과 구조 정의를 연결합니다.

할 일: 1절의 DemoHeader를 Pattern Editor에 입력하고 실행합니다. 결과에서 version과 payload_size의 위치를 확인한 뒤, 다음 선언을 덧붙여 내용 영역도 표시합니다.

char payload[header.payload_size] @ 0x0C;

완료 기준: version=1, count=3, payload_size=6과 내용 6바이트의 범위가 일치합니다. 버전 바이트를 바꾸고 재평가했을 때 결과가 달라지는 이유를 설명합니다.

추가 질문: 내용 길이만 20으로 바꾸면 실제 남은 6바이트와 모순됩니다. 오류 표시와 원본 바이트를 비교하고, 유효한 파일이 되려면 어떤 검사가 필요한지 적습니다.

소스 연결: configureRuntime()의 setDataSource() 콜백에서 읽기 요청의 경계를 찾습니다.

과제 3 · 중급

한 바이트 수정의 호출 경로 그리기 60~90분

목표: 이벤트와 되돌리기 기록을 연결합니다.

할 일: Provider::write() → EventProviderDataModified → ViewPatches → Stack::add() → OperationWrite::redo()를 읽고, 함수마다 입력·상태 변경·다음 호출을 한 줄씩 적습니다.

확인 방법: 학습 파일의 버전 바이트를 수정하고 Undo·Redo를 사용합니다. 메모리 버퍼 변경과 디스크 저장은 별도 항목으로 기록하세요.

완료 기준: “새 수정 뒤에 예전 redo를 왜 지우는가”와 “왜 writeRaw가 아니라 write를 호출하는가”를 소스 경로와 함께 설명합니다.

과제 4 · 중급

고정 바이트를 돌려주는 Provider 설계하기 반나절

목표: 데이터 원천과 화면을 분리하는 계약을 익힙니다.

할 일: 먼저 lib/libimhex/include/hex/test/test_provider.hpp와 tests/helpers/source/common.cpp를 읽습니다. 별도 실습 코드에서 8바이트 배열을 읽기 전용 데이터 원천으로 제공하는 클래스를 설계하세요. 실제 플러그인 연결은 SDK 환경을 갖춘 다음 단계입니다.

필수 사례: 시작에서 읽기, 끝에 정확히 닿는 읽기, 범위를 넘는 읽기, 빈 읽기, 기준 주소가 0이 아닌 경우를 표로 만듭니다.

완료 기준: 데이터 크기를 넘는 요청이 버퍼를 어떻게 처리해야 하는지 정의하고 테스트합니다. read()의 주소와 readRaw()의 오프셋을 구별해 설명합니다.

과제 5 · 고급

취소 가능한 바이트 빈도 분석 작업 만들기 1~2일

목표: 작업 실행·취소·UI 반영을 분리합니다.

할 일: 플러그인 SDK 실습 환경에서 작은 파일의 바이트 빈도 256칸을 계산하는 기능을 설계합니다. 계산은 TaskManager 작업으로 보내고 반복 중 중단 요청을 확인합니다. 완료 결과는 소유권을 정한 뒤 UI에 반영합니다.

확인 방법: InformationByteAnalysis::process(), Task::update(), TaskManager::doLater()를 참고합니다. 계산 중 탭 전환·파일 닫기·취소를 했을 때 작업이 참조하는 데이터의 수명을 먼저 정하세요.

완료 기준: 0만 있는 입력에서는 빈도 0번 칸만 증가하고, 취소 뒤 불완전한 결과가 정상 완료처럼 표시되지 않습니다. 닫힌 Provider를 뒤늦게 접근하지 않도록 수명 전략도 문서화합니다.

권장 제출물
입력 파일 + 기대값 표 + 호출 경로 한 장

화면 캡처만 남기기보다 바이트·필드·함수의 대응을 기록하세요. 이 세 가지가 있으면 결과가 틀렸을 때 파일 형식 해석, 주소 계산, UI 표시 중 어디부터 확인할지 정할 수 있습니다.

9관련 기술 심화 학습 로드맵

6주 동안 하나의 실행 경로를 점차 넓히기

주당 3~5시간 정도를 가정한 학습 제안입니다. C++가 처음이라면 1~2주차를 반복해도 좋습니다. 매주 새로운 기능을 늘리기보다, 같은 작은 바이너리를 더 깊은 계층에서 설명하는 방식으로 공부하세요.

주차배울 개념·읽을 코드남길 결과물
1주차 16진수, 정수 크기, 엔디언, 인코딩. tests/algorithms/source/endian.cpp 18바이트 파일을 오프셋·길이·값으로 나눈 표
2주차 상속, 가상 함수, 스마트 포인터. provider.hpp와 FileProvider::readRaw() Provider 공통 계약과 파일별 구현을 나눈 그림
3주차 Registry, Factory, 플러그인 진입점. registerViews(), Plugin::initializePlugin() 새 뷰가 생성되어 화면 루프에 도달하는 호출 경로
4주차 Pattern Language, 콜백, 오류 결과. configureRuntime(), evaluatePattern() 정상·길이 오류·엔디언 오류를 비교한 패턴 실습 기록
5주차 뮤텍스, 작업 큐, 중단 요청, UI 스레드. task_manager.cpp, doLater() 상태별 소유 스레드 표와 취소 시나리오
6주차 CMake 타깃, 의존성, CTest, sanitizer. 루트 빌드 설정과 tests.yml 플러그인 또는 테스트 하나의 설계·검증 보고서

9-1. 기반 지식이 부족할 때 돌아갈 지점

9-2. 그다음에 확장할 세 방향

언어 도구에 관심이 있다면 별도 PatternLanguage 저장소의 렉서·파서·평가기와 오류 위치 전달을 공부합니다. ImHex의 연결 코드와 언어 본체를 구분해 읽는 것이 출발점입니다.

시스템 도구에 관심이 있다면 Provider의 주소 변환·파일 접근·권한·원격 데이터 경계를 공부합니다. 같은 읽기 인터페이스라도 지연 시간과 실패 방식은 달라집니다.

데스크톱 제품에 관심이 있다면 ImGui 프레임, 탭별 상태, 단축키, 로컬라이제이션, 패키징을 따라갑니다. 기능 구현 이후 사용자에게 전달하기까지 필요한 층을 배울 수 있습니다.

10핵심 키워드 사전

소스에서 만나는 말을 일상적인 설명과 연결하기
용어쉬운 설명
바이너리바이트로 저장된 데이터. 실행 파일뿐 아니라 이미지·압축 파일·저장 데이터도 포함합니다.
헥스 편집기바이트를 16진수로 보고 바꾸는 편집기입니다.
오프셋시작점에서 떨어진 거리입니다. 파일의 첫 바이트는 오프셋 0입니다.
기준 주소데이터를 화면의 어느 주소부터 배치할지 정하는 값입니다. 파일 오프셋과 구별합니다.
엔디언여러 바이트짜리 숫자를 어떤 바이트 순서로 저장하고 읽을지 정한 규칙입니다.
매직 바이트파일 종류를 알아보는 단서가 되는 특정 바이트 배열입니다. 이름만으로 파일의 무결성을 보장하지는 않습니다.
Pattern Language파일의 필드·배열·구조를 정의해 바이트를 해석하는 ImHex의 별도 언어입니다.
Provider파일·메모리 등 데이터 원천을 공통 읽기·쓰기 계약으로 감싸는 객체입니다.
콜백어떤 시점에 호출하도록 다른 코드에 건네는 함수입니다.
Registry사용 가능한 화면·타입·함수·설정 등을 모아 두는 등록소입니다.
Factory구체적인 객체 생성 절차를 호출자 대신 맡는 코드입니다.
플러그인공통 API와 진입점을 통해 프로그램에 기능을 보태는 모듈입니다.
ABI컴파일된 코드끼리 함수·객체를 주고받는 이진 수준의 약속입니다. C++ 플러그인 호환성과 관련됩니다.
발행·구독이벤트를 보내는 쪽과 반응하는 쪽을 등록 관계로 연결하는 방식입니다.
되돌리기 스택편집의 이전·이후 상태나 작업을 저장해 Undo·Redo를 가능하게 하는 구조입니다.
오버레이원본 위에 별도의 바이트 내용을 겹쳐 읽을 수 있게 하는 층입니다.
뮤텍스동시에 접근하면 안 되는 공유 상태 앞에서 순서를 정해 주는 잠금입니다.
데이터 경쟁여러 스레드가 동기화 없이 같은 메모리에 접근하며 적어도 하나가 쓰기인 상황입니다. C++에서는 정의되지 않은 동작을 일으킬 수 있습니다.
작업 큐할 일을 줄에 넣고 작업자 스레드가 가져가 실행하도록 만든 구조입니다.
즉시 모드 GUI매 프레임 코드를 통해 화면 구성을 기술하는 방식입니다. 앱의 상태 저장 자체가 없어지는 것은 아닙니다.
엔트로피바이트 분포가 얼마나 다양하고 고른지 나타내는 통계량입니다. 이 코드에서는 8로 나눠 정규화합니다.
디스어셈블기계어 바이트를 어셈블리 명령으로 해석하는 작업입니다.
YARA문자열·바이트 패턴과 조건을 규칙으로 적어 데이터를 찾는 도구입니다.
MCP·JSON-RPCMCP는 AI 도구 연결에 쓰이는 프로토콜이며, JSON-RPC는 메서드·인자·결과를 JSON 메시지로 주고받는 규약입니다.
WebAssemblyC++ 등의 코드를 브라우저 같은 실행 환경에서 구동할 수 있게 하는 바이너리 명령 형식입니다.
서브모듈다른 Git 저장소를 특정 커밋으로 참조하는 방식입니다. 상위 저장소만 받으면 본체가 비어 있을 수 있습니다.
sanitizer실행 중 메모리 오류·누수·정의되지 않은 동작 등을 찾도록 계측하는 도구입니다. 모든 오류를 보장해 검출하지는 않습니다.

11참고 링크

공식 자료와 커밋에 고정된 소스를 함께 읽기

11-1. 공식 저장소·문서

11-2. 핵심 소스 다시 찾아가기

아래 링크의 파일 경로는 저장소 루트 기준이며, 모두 분석 커밋에 고정되어 있습니다. 함수 이름으로 검색하면 본문에서 설명한 연결을 확인할 수 있습니다.

11-3. 관련 기술의 공식 자료

현재 상태 (2026-10-23 GitHub 기준)

항목상태·해석
저장소WerWolv/ImHex · 주 언어 C++
선정 위치GitHub Trending C++ Weekly #9 · 2026-10-23 분석 기준
스타 / 포크55,522 / 2,565 · 2026-10-23 GitHub 기준
생성일2020-11-10
최신 릴리스v1.38.1 · 2025-12-21
최근 push2026-10-09 · GitHub 저장소 메타데이터 기준
분석한 최근 커밋34483cb · 2026-10-08 · Pattern Editor의 데이터 경쟁·충돌 수정 (#2930)
소스 버전VERSION은 1.39.0.WIP · 릴리스와 다른 개발 상태
코드 규모외부 디렉터리 제외 C++·헤더 512개, 117,457줄. Objective-C 909줄, C# 545줄, Python 745줄 등
라이선스GitHub 표기 GPL-2.0. README는 대부분 GPLv2-only, lib/libimhex와 plugins/ui는 LGPLv2.1 예외로 설명하며 각 LICENSE 파일도 분리

최근 push 날짜는 저장소의 갱신 시각이고 커밋 날짜는 해당 커밋에 기록된 시각이므로 서로 다를 수 있습니다. 코드 규모는 빈 줄·주석을 포함한 물리 줄 수이며, 날짜·스타·포크와 달리 위에서 정의한 소스 범위의 집계입니다.

사용 전에 알아둘 한계
해석 결과·지원 안내·라이선스의 적용 범위를 확인하세요

버전: 이 문서의 함수와 설정은 개발 커밋 기준입니다. v1.38.1 배포 파일에 MCP 도구나 같은 UI·기본값이 모두 있다고 가정하면 안 됩니다. 별도 PatternLanguage 서브모듈 본체의 내부 알고리즘과 성능은 이 설명의 범위 밖입니다.

정확도와 성능: 패턴은 작성한 구조 가정에 따라 해석합니다. 엔트로피 힌트는 암호화 판정의 증거가 아니며, README의 약 50MiB 메모리 안내는 복잡한 분석 작업의 보장치가 아닙니다. 하드웨어 표와 CI 정의는 실제 환경별 실행·호환성 측정을 대체하지 않습니다.

데이터와 연결: 직접 파일 접근 경로에서는 수정이 원본에 반영될 수 있습니다. 복사본으로 연습하세요. 로컬 분석이 가능해도 모든 기능이 무조건 오프라인이라는 뜻은 아닙니다. Store·업데이트·원격 기능과 함께 PRIVACY.md의 선택적 통계·동의 기반 충돌 로그 안내를 확인하세요.

라이선스: 루트 GPL과 일부 LGPL 예외, 외부 라이브러리의 조건이 나뉩니다. 재사용할 때는 루트 LICENSE, libimhex LICENSE, UI LICENSE와 해당 의존성의 원문을 함께 읽어야 합니다.