프로세스 메모리에서 암호화 알고리즘의 고유 상수를 탐지하고, 실제 사용 여부를 Hardware Watchpoint로 검증하는 보안 분석 도구입니다.
- 🎯 동적 추적 (기본): Hardware watchpoint로 암호화 상수의 실제 사용 검증
- 프로세스 메모리 스캔:
/proc/<pid>/maps를 분석하여 메모리 영역 탐색 - 암호화 상수 탐지: AES, ChaCha20, SHA-256, P-256 등의 고유 상수 패턴 매칭
- ptrace 기반 실행: 빠르게 종료되는 프로그램도 탐지 가능
- False Positive 제거: 링크만 되고 사용하지 않는 라이브러리 제외
- 역공학 지원: 접근한 명령어 주소(RIP) 제공
- 엔디안 변종 지원: Little/Big endian 자동 감지
- NDJSON 출력: 구조화된 JSON 라인 형식으로 결과 출력
- 성능 최적화: Boyer-Moore-Horspool 알고리즘으로 빠른 패턴 검색
| 알고리즘 | 시그니처 | 크기 | 설명 |
|---|---|---|---|
| AES | S-box 테이블 | 256B | SubBytes 변환 테이블 |
| AES | Rcon | 10-40B | 라운드 상수 |
| ChaCha20 | "expand 32-byte k" | 16B | 매직 상수 |
| SHA-256 | K[64] | 256B | 라운드 상수 테이블 |
| SHA-256 | H[8] | 32B | 초기 해시 값 |
| P-256 | Prime, Gx, Gy, B | 32B | NIST 타원곡선 파라미터 |
- CMake 3.10+
- C++17 지원 컴파일러 (GCC 7+, Clang 5+)
- Linux (WSL 포함)
# Release 빌드
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
# 실행 파일: build/crypto_const_scannerrm -rf build
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)Hardware watchpoint를 사용하여 암호화 상수가 실제로 사용되는지 검증
# 기본 사용 (1초 추적)
./build/crypto_const_scanner ./my_crypto_program
# 인자가 있는 프로그램
./build/crypto_const_scanner ./my_program arg1 arg2
# 추적 시간 조정 (복잡한 프로그램용)
./build/crypto_const_scanner --trace-time 5000 ./my_program
# 출력 예시:
# === Crypto Constant Dynamic Tracer ===
# Hardware watchpoint-based verification of actual crypto constant usage.
# Max constants: 4 (hardware limit)
# Trace duration: 1000ms
#
# === Trace Results ===
# aes_sbox @ 0x5e57169e2020 ✓ USED (3 access(es)) from RIP=0x5e57169e1243
# sha256_k @ 0x5e57169e3100 ✗ NOT ACCESSED during trace
#
# === Summary ===
# Verified: 1/2 constants actually used특징:
- ✓ 실제 사용 여부 검증 (메모리 접근 감지)
- ✓ False positive 제거 (링크만 되고 미사용인 라이브러리 제외)
- ✓ 접근한 명령어 주소(RIP) 제공 → 역공학 지원
- ✓ 사용된 상수만 자동 로그 저장 (미사용 상수는 제외)
- ⚠ Hardware watchpoint 제한: 최대 4개 상수 동시 모니터링
- ⚠ 우선순위: AES S-box > ChaCha20 > SHA-256 K > AES Rcon > ...
로그 저장:
# 기본 logs 디렉토리에 검증된 상수 저장
./build/crypto_const_scanner ./program
# 커스텀 로그 디렉토리
./build/crypto_const_scanner --log-dir ./my_logs ./program
# 로그 저장 비활성화
./build/crypto_const_scanner --no-log ./program- 파일명:
<log-dir>/<process_name>_<YYYYMMDD_HHMMSS_mmm>.ndjson - 예:
logs/test_crypto2_20251101_044447_063.ndjson - 밀리초 포함으로 빠르게 연속 실행 시에도 파일명 중복 방지
- 실제 사용된 상수만 저장 (False positive 없음)
./test.sh이 스크립트는:
tests/CustomImpl/폴더의 모든 암호화 구현 코드를 빌드- 각 테스트 프로그램을 동적 추적으로 실행 (500ms trace)
- 실제로 사용된 상수만
logs/에 저장 - 검증된 알고리즘 통계 출력
실행 예시:
➜ crypto_const_scanner git:(master) ✗ ./build/crypto_const_scanner ./build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch
=== Crypto Constant Dynamic Tracer ===
Hardware watchpoint-based verification of actual crypto constant usage.
Max constants: 4 (hardware limit)
Trace duration: 1000ms
Started process: ./build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch (PID: 30245)
Process paused for scanning (PID: 30245)
=== Crypto Constant Tracer ===
Target PID: 30245
Found 12 memory regions
Filtered to 12 crypto-relevant regions
Scanning region: 5acf43ce0000-5acf43ce2000 (8 KB) /mnt/d/git/crypto_const_scanner/build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch
Scanning region: 5acf43ce2000-5acf43ce5000 (12 KB) /mnt/d/git/crypto_const_scanner/build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch
Scanning region: 5acf43ce5000-5acf43ce7000 (8 KB) /mnt/d/git/crypto_const_scanner/build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch
Scanning region: 5acf43ce7000-5acf43ce9000 (8 KB) /mnt/d/git/crypto_const_scanner/build/tests/symmetric/custom_impl_symmetric_aes256_ecb_from_scratch
Scanning region: 7cb52406b000-7cb52406d000 (8 KB)
Scanning region: 7cb52406d000-7cb52406e000 (4 KB) /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Scanning region: 7cb52406e000-7cb524099000 (172 KB) /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Scanning region: 7cb524099000-7cb5240a3000 (40 KB) /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Scanning region: 7cb5240a3000-7cb5240a7000 (16 KB) /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Scanning region: 7ffdb3bae000-7ffdb3bd0000 (136 KB) [stack]
Scanning region: 7ffdb3bd8000-7ffdb3bdc000 (16 KB) [vvar]
Failed to read memory from region
Scanning region: 7ffdb3bdc000-7ffdb3bde000 (8 KB) [vdso]
Scan complete. Found 2 crypto constant signatures
Found 2 crypto constant(s)
Watching 2 constant(s) (hardware limit: 4)
Watchpoint 0 set at 0x5acf43ce5020
[0] Watching aes_sbox at 0x5acf43ce5020
Watchpoint 1 set at 0x5acf43ce5220
[1] Watching aes_rcon_words at 0x5acf43ce5220
Tracing execution...
✓ HIT: aes_rcon_words at 0x5acf43ce5220 accessed by RIP=0x5acf43ce2fd2
✓ HIT: aes_rcon_words at 0x5acf43ce5220 accessed by RIP=0x5acf43ce2fd2
✓ HIT: aes_sbox at 0x5acf43ce5020 accessed by RIP=0x5acf43ce252c
✓ HIT: aes_sbox at 0x5acf43ce5020 accessed by RIP=0x5acf43ce25e3
✓ HIT: aes_sbox at 0x5acf43ce5020 accessed by RIP=0x5acf43ce25e3
✓ HIT: aes_sbox at 0x5acf43ce5020 accessed by RIP=0x5acf43ce25e3
✓ HIT: aes_sbox at 0x5acf43ce5020 accessed by RIP=0x5acf43ce25e3
Plaintext : 6bc1bee22e409f96e93d7e117393172a
Ciphertext: f3eed1bdb5d2a03c064b5a7e3db181f8
Recovered : 6bc1bee22e409f96e93d7e117393172a
Process exited with code 0
Failed to write DR0: No such process
Failed to read DR7: No such process
Failed to write DR7: No such process
Failed to write DR1: No such process
Failed to read DR7: No such process
Failed to write DR7: No such process
=== Trace Results ===
aes_sbox @ 0x5acf43ce5020 ✓ USED (5 access(es)) from RIP=0x5acf43ce25e3
aes_rcon_words @ 0x5acf43ce5220 ✓ USED (2 access(es)) from RIP=0x5acf43ce2fd2
=== Summary ===
Verified: 2/2 constants actually used
✓ Verified constants saved to: logs/custom_impl_symmetric_aes256_ecb_from_scratch_20251101_050355_013.ndjson
참고:
- RSA, LCG, DH 프로토콜 테스트는 AES/SHA-256/ChaCha20 상수가 없어 정상적으로 탐지되지 않습니다
- 프로세스 이름이 15자로 잘려도 밀리초 타임스탬프로 로그 파일 구분 가능
# 1. 테스트 프로그램 빌드
g++ -o /tmp/aes_test tests/CustomImpl/symmetric/aes256_loop.cpp -O0 -g -std=c++17
# 2. 스캔 실행
./build/crypto_const_scanner /tmp/aes_test
# 3. 로그 확인 (가장 최근 파일)
ls -t logs/custom_impl_*.ndjson | head -1 | xargs cat | jq .cd tests
make # 모든 테스트 빌드 (build/tests/에 저장)
make clean # 빌드 결과물 삭제
make list # 빌드할 파일 목록 보기실제 사용 확인된 상수만 저장:
{
"ts": 1761939887.061,
"source": "constscan",
"pid": 0,
"map_path": "/tmp/test_crypto2",
"start": "0x566a3b64c020",
"end": "0x566a3b64c120",
"hit_type": "aes_sbox",
"offset": 0,
"address": "0x566a3b64c020",
"confidence": 1.00,
"detail": "verified used (accessed 1 time(s) from RIP=0x566a3b64b243",
"permissions": "traced"
}ts: 타임스탬프 (Unix time, 밀리초 정밀도)source: 데이터 출처 (항상 "constscan")pid: 대상 프로세스 ID (추적 완료 후 0)map_path: 실행한 프로그램 경로start/end: 메모리 영역 범위hit_type: 탐지된 상수 타입 (aes_sbox,aes_rcon,chacha20_const,sha256_k,sha256_h,p256_prime등)offset: 영역 내 오프셋address: 절대 메모리 주소confidence: 신뢰도 (항상 1.0, 사용 확인됨)detail: 중요! 접근 횟수와 RIP (명령어 주소) 포함 - 역공학에 활용permissions: 항상"traced"(동적 추적 완료)
crypto_const_scanner/
├── .gitignore # Git 무시 파일
├── CMakeLists.txt # CMake 빌드 설정
├── README.md # 사용 가이드 (본 문서)
├── test.sh # 통합 테스트 스크립트
├── src/ # 소스 코드
│ ├── main.cpp # CLI 엔트리포인트
│ ├── scan_process.{h,cpp} # 프로세스 메모리 스캔
│ ├── matchers.{h,cpp} # 패턴 매칭 알고리즘
│ ├── runner.{h,cpp} # ptrace 기반 실행
│ ├── watchpoint.{h,cpp} # Hardware watchpoint 관리
│ ├── trace_runner.{h,cpp} # 동적 추적 엔진
│ ├── watchpoint.{h,cpp} # Hardware watchpoint 관리
│ ├── trace_runner.{h,cpp} # 동적 추적 엔진
│ ├── reporters/
│ │ └── ndjson.{h,cpp} # NDJSON 리포터
│ └── signatures/ # 암호화 상수 정의
│ ├── aes_sbox.h
│ ├── aes_rcon.h
│ ├── chacha_const.h
│ ├── sha256_k.h
│ └── curve_p256.h
├── tests/ # 테스트 코드
│ ├── Makefile # 테스트 빌드 설정
│ └── CustomImpl/ # 자체 구현 암호화 코드
│ ├── symmetric/ # AES, ChaCha20 등
│ ├── HashKdf/ # PBKDF2, SHA-256 등
│ ├── PublicKey/ # RSA 등
│ ├── signature/ # RSA 서명 등
│ ├── protocol/ # DH 핸드셰이크 등
│ └── entropy/ # LCG 등
├── build/ # 빌드 디렉토리 (git ignored)
│ ├── crypto_const_scanner # 메인 실행 파일
│ └── tests/ # 테스트 빌드 결과물
└── logs/ # 스캔 로그 (git ignored)
이 도구는 4단계 프로세스로 암호화 상수의 실제 사용을 검증합니다:
fork()+ptrace(PTRACE_TRACEME)+execvp()로 대상 프로그램 실행- 10번의 syscall 실행을 대기하여 초기화 완료 확인
/proc/<pid>/maps파싱하여 메모리 영역 획득process_vm_readv()로 프로세스 메모리 읽기- Boyer-Moore-Horspool 알고리즘으로 암호화 상수 패턴 매칭
- 발견된 상수들의 메모리 주소 수집
Note: 정적 스캔은 watchpoint를 설정하기 위한 내부 준비 단계입니다. 단순히 메모리에 존재하는지만 확인하며, 실제 사용 여부는 다음 단계에서 검증합니다.
- 발견된 상수 중 우선순위 상위 4개 선택 (x86-64 하드웨어 제한)
- 우선순위: AES S-box (10) > ChaCha20 (9) > SHA-256 K (8) > AES Rcon (7) > ...
- x86-64 debug register (DR0-DR3)에 상수 메모리 주소 설정
- DR7 (제어 레지스터)에서 Read/Write 감지 활성화
ptrace(PTRACE_CONT)로 프로그램 계속 실행- 상수 메모리 접근 시 SIGTRAP 신호 발생 (하드웨어 자동 감지)
- DR6 (상태 레지스터)를 읽어 어떤 watchpoint가 hit되었는지 확인
- RIP (명령어 포인터) 기록 → 어느 코드에서 접근했는지 추적
- 설정된 시간 동안 모니터링 (기본 1초)
- ✓ USED: 실제 접근 확인 (접근 횟수, RIP 포함) → 로그에 저장
- ✗ NOT ACCESSED: 메모리에는 존재하나 미사용 → 로그에 저장 안 함
핵심 특징:
- 디버거처럼 데이터 주소에 breakpoint를 거는 방식
- 메모리 존재 ≠ 실제 사용을 명확히 구분
- False positive 최소화 (실제 접근한 것만 로그)
난독화되거나 분석이 어려운 바이너리에서 암호화 사용 여부 확인
메모리 덤프 분석 시 암호화 키나 알고리즘 추적
디버거나 후킹 도구와 함께 사용하여 암호화 함수 위치 특정
시스템에서 실행 중인 프로세스의 암호화 라이브러리 사용 현황 파악
기본적으로 암호화 관련 영역만 스캔:
libcrypto,libssl,libsodium,mbedtls,boringssl등- 실행 가능 영역 (
r-xp) - 읽기 전용 데이터 (
r--p)
- 기본 최대 크기: 100MB
--max-size옵션으로 조정 가능- 초과 시 자동으로 스킵
- Boyer-Moore-Horspool: O(n/m) 평균 시간복잡도
- 대부분의 경우 선형 시간보다 빠름
프로그램을 실행하고 메모리를 읽기 위해 root 권한 필요:
sudo ./build/crypto_const_scanner ./programsudo setcap cap_sys_ptrace+ep ./build/crypto_const_scanner
./build/crypto_const_scanner ./program- Linux 전용:
/proc파일시스템과 ptrace 의존 - 읽기 전용: 메모리 수정 불가 (분석만 가능)
- 시그니처 기반: 알려진 상수만 탐지 (새로운 암호화 알고리즘은 탐지 불가)
- Hardware 제한: 최대 4개 상수만 동시 모니터링 (x86-64 debug register 제한)
- 코드 경로 의존: 추적 시간 내에 실행되지 않은 코드는 탐지 불가
- False Positive: 거의 없음 (실제 접근 확인된 상수만 로그 저장)
src/signatures/디렉토리에 새 헤더 파일 생성src/matchers.cpp의scan_for_crypto_constants()함수에 탐지 로직 추가- 테스트 후 빌드
예시:
// src/signatures/md5.h
constexpr uint32_t MD5_INIT[4] = {
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
};# .gitignore가 다음을 자동으로 제외:
# - build/ (빌드 결과물)
# - logs/ (스캔 로그)
# - *.o, *.a (중간 파일)# 실행 권한 부여
chmod +x build/crypto_const_scanner test.sh이 도구는 ptrace를 사용하여 빠르게 종료되는 프로그램도 자동으로 캡처합니다:
sudo ./build/crypto_const_scanner ./your_program- Root 권한으로 실행 필요:
sudo - ptrace 권한 확인:
cat /proc/sys/kernel/yama/ptrace_scope- 값이 1 이상이면 권한 제한됨
- 임시 해제:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope