
정적 디오브퍼스케이션 도구 키트로, 컴파일된 V8 JavaScript 바이트코드를 대상으로 하며 JSCeal 페이로드에 중점을 둡니다. 패턴 기반 필터, 제어 흐름 평탄화 해제, 문자열 재구성, 그리고 분석을 위한 선택적 LLM 지원 함수 이름 변경 기능을 제공합니다.
이 도구는 javascript-obfuscator로 보호된 컴파일된 V8 JavaScript 바이트코드를 정적으로 디오브퍼스케이션하는 데 전념합니다.
원본 JavaScript 소스가 아닌 View8이 생성한 의사 코드에서 작동합니다. 이 프로젝트는 JSCeal 페이로드에서 개발 및 테스트되었습니다.
필터는 패턴 기반이며 주로 연구 도구 키트 및 참조 구현으로 사용됩니다. 이 도구는 범용 JavaScript 디오브퍼스케이터가 아니며, 원본 소스 코드를 재구성하지 않으며, 실행 가능한 JavaScript를 생성하지 않습니다. 출력은 정적 검사, 검색, 비교 및 함수 트리 내보내기를 위한 View8 의사 코드로 유지됩니다.
📖 위키 읽기
pickle을 사용합니다. 악의적이거나 신뢰할 수 없는 .pkl 파일을 로드하면 코드가 실행될 수 있습니다. View8로 로컬에서 직접 생성한 직렬화 파일만 로드하세요.requirements.txt의 Python 종속성;brotli 명령줄 유틸리티;격리된 Python 환경을 생성하세요:
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
deobf_ai.py의 OpenAI 백엔드는 추가로 OpenAI Python 패키지가 필요합니다:
python3 -m pip install openai
Anthropic 백엔드는 requests를 통해 HTTP API를 사용합니다. Ollama 백엔드는 연결 가능한 Ollama 서버를 기대합니다.
원본 JSCeal app.jsc 페이로드는 Brotli 압축되어 있습니다. Linux에서는 brotli 유틸리티로 압축을 해제할 수 있습니다:
brotli -d app.jsc -o app.decompressed.jsc
scripts/ 아래의 배치 워크플로우는 scripts/unpack_all.sh로 이 단계를 수행합니다.
Windows에서 또는 brotli 명령줄 유틸리티를 사용할 수 없을 때는 포함된 Node.js 헬퍼를 폴백으로 사용할 수 있습니다. 입력만 압축 해제하고 실행하지 않습니다:
node Utils/decompress-jsc.js app.jsc
다음을 작성합니다:
app.jsc.decompressed.jsc
V8 코드 캐시는 버전별로 다릅니다. 페이로드와 동일한 V8 버전으로 빌드된 디스어셈블러를 사용하세요.
개발 중 사용된 JSCeal 샘플은 V8 10.2.154.26을 기반으로 했습니다. 관련 없는 V8 빌드의 기본 디스어셈블러는 올바르게 작동하지 않습니다.
소스 트리에는 디스어셈블러 소스와 필요한 V8 패치가 아래에 포함되어 있습니다:
Utils/disasm/v8dasm.cpp
Utils/disasm/patches/
사전 빌드된 Linux 바이너리는 프로젝트 릴리스와 함께 배포되며, 소스 트리에는 재빌드에 필요한 소스와 패치가 포함되어 있습니다. 자세한 설명은 프로젝트 위키에서 확인할 수 있습니다. 일치하는 v8dasm을 얻거나 빌드한 후 다음을 실행하세요:
/path/to/v8dasm app.decompressed.jsc > app.jsc.disasm.txt
디스어셈블된 파일을 view8.py에 공급하고 추가 처리를 위한 직렬화 출력과 사람이 읽을 수 있는 의사 코드를 모두 생성하세요:
mkdir -p decompiled
python3 View8/view8.py \
--input_format disassembled \
--inp app.jsc.disasm.txt \
--normalize \
--out decompiled/app.dec.txt \
--export_format decompiled serialized
다음을 생성합니다:
decompiled/app.dec.txt
decompiled/app.dec.pkl
--normalize 옵션은 반복된 디스어셈블리 및 디컴파일 실행에서 생성된 함수 식별자를 재현 가능하게 만듭니다.
개별 난독화 레이어에 대한 별도의 필터가 있습니다. deobf_all.py로 직렬화된 View8 출력에 함께 적용할 수 있습니다:
mkdir -p deobfuscated
python3 deobf_all.py \
--inp decompiled/app.dec.pkl \
--out deobfuscated/app.deobf.txt \
--export_format decompiled serialized
기본 문자열 필터는 분석된 대부분의 JSCeal 페이로드에서 사용되는 변형 2입니다. 더 간단한 문자열 체계를 명시적으로 선택하려면 다음을 추가하세요:
--str_deobf 1
일반적인 출력은 다음과 같습니다:
deobfuscated/app.deobf.txt
deobfuscated/app.deobf.pkl
deobfuscated/app.deobf.txt.strings.txt
decompiled/app.dec.resolved_funcs.csv
해석된 함수 CSV는 샘플별 캐시입니다. 없으면 문자열 패스가 필요한 디코더 구성을 복구하고 CSV를 작성한 다음 같은 실행에서 문자열 디오브퍼스케이션을 계속합니다. 이후 실행은 캐시를 재사용하며 일반적으로 더 빠릅니다.
해석된 함수 CSV를 다른 디컴파일된 페이로드와 함께 재사용하지 마세요.
모든 구조적 디오브퍼스케이션 필터가 적용된 후 deobf_ai.py는 함수 동작을 설명하는 이름을 제안할 수 있습니다. Anthropic, OpenAI 및 Ollama 백엔드를 지원합니다.
실행이 재현 가능하도록 모델을 명시적으로 전달하세요.
export ANTHROPIC_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend anthropic \
--model '<model-id>' \
--export_format decompiled serialized
export OPENAI_API_KEY='...'
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend openai \
--model '<model-id>' \
--export_format decompiled serialized
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--llm_backend ollama \
--model '<local-model>' \
--ollama_url http://localhost:11434 \
--export_format decompiled serialized
기본 모드에서 이름 변경기는 진입 함수에서 시작하는 직접 호출 트리를 구축하고 호출을 통해 도달한 함수만 이름을 변경합니다. 콜백 및 할당된 핸들러를 포함한 모든 보이는 함수 참조를 포함하려면 --greedy를 추가하세요.
생성된 2열 CSV는 캐시 역할을 하며 중단된 실행을 계속할 수 있게 합니다. --csv로 기존 캐시를 명시적으로 선택하세요:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--csv deobfuscated/app.deobf.renamed_funcs.greedy.example-model.csv \
--llm_backend anthropic \
--model '<model-id>' \
--greedy \
--export_format decompiled serialized
일반 모드에서 CSV는 잠재적으로 부분적인 캐시로 처리됩니다. 캐시된 이름이 먼저 적용되고, 캐시로 이미 덮인 함수는 선택된 호출 또는 참조 트리에서 제거되며, LLM은 해결되지 않은 함수에 대해서만 호출됩니다. CSV가 해당 트리를 완전히 덮으면 API 키나 LLM 연결이 필요하지 않습니다. 트리의 일부만 덮으면 선택된 백엔드가 초기화되고 새로 생성된 매핑이 동일한 CSV에 추가됩니다.
CSV가 생성될 때 사용된 것과 동일한 트리 모드를 사용하세요. --greedy 실행에서 생성된 CSV는 직접 호출 하위 집합만 재사용하는 것이 아니라 해당 실행을 계속하는 것이 목표라면 일반적으로 다시 --greedy가 필요합니다.
CSV에 검토, 편집, 가져오기 또는 리베이스된 매핑을 포함하여 적용하려는 레이블이 이미 포함된 경우 --apply-csv-only를 사용하세요:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--out deobfuscated/app.renamed.txt \
--csv renamed_functions.normalized.csv \
--apply-csv-only \
--export_format decompiled serialized
이 모드는:
--csv가 필요합니다;--func와 결합할 수 없습니다.원래 함수 식별자가 입력에 존재하지 않는 행은 무시됩니다. 로드된 파일에 적용 가능한 매핑이 CSV에 없으면 명령이 실패합니다.
정확한 전체 함수 식별자와 함께 --func를 사용하여 디오브퍼스케이션된 하나의 함수에 대한 집중적인 의미 분석을 요청하세요:
python3 deobf_ai.py \
--inp deobfuscated/app.deobf.pkl \
--func func_example_0x100001234 \
--llm_backend anthropic \
--model '<model-id>'
분석에는 제안된 이름, 동작 요약, 입력 및 반환 값, 부작용, 단계별 논리, 정리된 의사 코드, 뒷받침 증거 및 해결되지 않은 불확실성이 포함됩니다. --csv를 제공하면 로드된 코퍼스를 수정하지 않고 선택된 함수 내부의 참조에 대한 컨텍스트로 캐시된 의미 이름이 추가됩니다. --analysis-out analysis/function.md를 사용하여 보고서를 Markdown으로 저장하세요. 퍼지 일치는 제안으로만 인쇄됩니다. 요청된 함수 식별자는 정확히 일치해야 합니다.
온도, 배칭, Anthropic 사고 모드, 토큰 제한 및 사용자 지정 CSV 경로를 제어하는 옵션은 --help를 사용하세요.
LLM 생성 이름은 탐색 보조 도구이지 증거가 아닙니다. 항상 디오브퍼스케이션된 본문과 대조하여 검증하세요.
디오브퍼스케이션된 JSCeal 출력은 일반적으로 매우 큽니다. 직렬화된 출력을 View8에 다시 로드하고 더 작은 함수 트리로 분할하세요.
이 단계에서 --scope 0을 추가하세요. 범위 전파는 이미 디오브퍼스케이터에 의해 수행되었으며, 반복하면 값이 잘못 전파될 수 있습니다.
선언자 관계에 기반한 트리:
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/declarers \
--export_format decompiled \
--tree start \
--scope 0
간결한 직접 호출 개요:
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/calls \
--export_format decompiled \
--tree start \
--scope 0 \
--split_mode calls \
--inline_depth 1 \
--split_depth 5
콜백 및 할당된 핸들러를 포함한 더 넓은 참조 트리:
python3 View8/view8.py \
--input_format serialized \
--inp deobfuscated/app.deobf.pkl \
--out trees/references \
--export_format decompiled \
--tree start \
--scope 0 \
--split_mode references \
--inline_depth 1 \
--split_depth 3
다른 JSC 파일은 다른 문자열 난독화 모드를 사용할 수 있습니다.
관찰된 가장 간단한 모드는 인덱스 이동을 사용하며 deobf_str1.py로 처리됩니다. 가장 일반적인 JSCeal 모드는 Base64, RC4, 청크 문자열 및 변환된 인덱스를 사용하며 deobf_str2.py로 처리됩니다.
전체 파이프라인은 기본적으로 변형 2를 선택합니다. 필터는 테스트를 위해 독립적으로 실행할 수도 있습니다.
deobf_str2.py사용 가능한 모든 모드와 옵션을 표시하려면 --help를 사용하세요:
python3 deobf_str2.py --help
직접 문자열 디오브퍼스케이션 실행은 다음으로 시작할 수 있습니다:
python3 deobf_str2.py \
--inp decompiled/app.dec.pkl \
--out work/app.strings.txt \
--export_format decompiled serialized
실행 중에 스크립트는 문자열 디코더 함수를 식별하고, 유효한 캐시된 구성을 로드하고, 누락된 것을 해결하고, 결과 CSV를 저장하고, 문자열을 디코딩합니다. 두 번째 실행은 필요하지 않습니다.
deobf_str2.py를 직접 사용할 때 기본 CSV 이름은 resolved_funcs.csv입니다. --csv 또는 -c로 샘플별 경로를 선택하세요:
python3 deobf_str2.py \
--inp decompiled/app.dec.pkl \
--out work/app.strings.txt \
--csv decompiled/app.dec.resolved_funcs.csv \
--export_format decompiled serialized \
--verbosity 1
개별 필터를 연결할 때 이후 패스가 View8 객체에서 계속 작동할 수 있도록 단계 간에 직렬화된 출력을 보존하세요.
deobf_all.py는 다음 단계를 순서대로 적용합니다:
LLM 지원 함수 이름 변경은 선택 사항이며 구조적 디오브퍼스케이션 후에 별도로 실행됩니다.
저장소에는 scripts/ 아래에 완전한 헬퍼 워크플로우가 포함되어 있습니다. 모든 스크립트는 한 디렉토리에 유지되며 동일한 중앙 집중식 구성을 소싱합니다.
scripts/config.sh 공유 도구 및 작업 공간 경로
scripts/copy_payloads.sh JSCeal app.jsc 파일 수집 및 MD5 이름 지정
scripts/unpack_all.sh Brotli 압축 해제
scripts/disasm_all.sh 배치 V8 디스어셈블리
scripts/decompile_all.sh 배치 View8 디컴파일
scripts/deobfuscate_all.sh 결합 로그가 있는 배치 디오브퍼스케이션
scripts/run_unattended.sh 분리된 디오브퍼스케이션 및 검증
scripts/collect_output.sh 디코더 캐시 및 문자열 목록 수집
제공된 scripts/config.sh에는 예제 환경의 경로가 포함되어 있습니다:
JSC_DEOBF_ROOT="$HOME/jsc_deobfuscator"
V8DASM="$HOME/code/v8/v8dasm"
설치 경로, 일치하는 V8 디스어셈블러, 작업 공간 디렉토리, 외부 명령, 로그 경로 및 수집 레이아웃을 구성하려면 해당 파일을 한 번 편집하세요. 작업 공간은 기본적으로 헬퍼 스크립트가 시작된 디렉토리입니다.
모든 값은 환경 변수를 통해 재정의할 수도 있습니다. JSC_HELPER_CONFIG는 다른 구성 파일을 선택할 수 있습니다.
일반적인 배치 실행은 다음과 같습니다:
scripts/copy_payloads.sh
scripts/unpack_all.sh
scripts/disasm_all.sh
scripts/decompile_all.sh
scripts/deobfuscate_all.sh
scripts/collect_output.sh
스크립트는 발견된 app.jsc 파일을 Brotli 압축 페이로드로 처리하고 MD5로 이름을 지정하는 것을 포함하여 JSCeal 코퍼스에 사용된 규칙을 보존합니다. 워크플로우를 관련 없는 샘플에 적용하기 전에 scripts/README.md를 검토하세요.
긴 배치의 경우 scripts/run_unattended.sh는 nohup으로 디오브퍼스케이션을 시작하고, 타임스탬프가 있는 로그, PID 및 상태 파일을 작성하고, 캐시된 문자열 디코더 함수에 대한 해결되지 않은 참조가 있는지 각 생성된 출력을 검증합니다:
scripts/run_unattended.sh
선택된 샘플을 명시적으로 제공할 수 있습니다:
scripts/run_unattended.sh \
decompiled/sample1.dec.pkl \
decompiled/sample2.dec.pkl
View8/ View8 디컴파일러 및 함수 트리 내보내기
Utils/decompress-jsc.js Windows용 Brotli 압축 해제 폴백
Utils/disasm/v8dasm.cpp V8 디스어셈블러 소스
Utils/disasm/patches/ 디스어셈블러에 필요한 V8 패치
Utils/check_unresolved_decoder_references.py
출력 검증 헬퍼
deobf_all.py 완전한 기본 디오브퍼스케이션 파이프라인
deobf_str1.py 간단한 문자열 인덱스 이동 필터
deobf_str2.py 인덱스 복구가 있는 RC4/Base64 문자열 필터
deobf_scope2.py 범위 및 사전 전파
deobf_unflattener.py 제어 흐름 평탄화 해제
deobf_replace_ops.py 프록시 및 연산 래퍼 대체
deobf_globals.py 전역 전파
deobf_inline_temporaries.py 보수적인 최종 정리
deobf_ai.py 선택적 LLM 지원 함수 이름 변경
scripts/ 구성 가능한 배치 및 검증 헬퍼
모든 주요 패스는 테스트를 위해 별도로 실행할 수 있습니다. 선택한 스크립트를 --help와 함께 실행하여 전체 인터페이스를 확인하세요:
python3 deobf_str1.py --help
python3 deobf_str2.py --help
python3 deobf_scope2.py --help
python3 deobf_unflattener.py --help
python3 deobf_replace_ops.py --help
python3 deobf_globals.py --help
python3 deobf_inline_temporaries.py --help
javascript-obfuscator 출력에서 관찰된 패턴을 인식합니다. 새로운 변형에는 추가 감지기 또는 변환이 필요할 수 있습니다.파이프라인은 관련 연구에 사용된 JSCeal 코퍼스에 대해 회귀 테스트되었습니다. 기본 릴리스 검사에는 다음이 포함됩니다:
python3 -m compileall -q .
python3 deobf_all.py --help
python3 deobf_str2.py --help
python3 deobf_ai.py --help
python3 View8/view8.py --help
각 코퍼스 샘플에 대해 실행이 다음을 수행하는지 확인하세요:
.pkl 및 .txt 출력을 모두 작성합니다;무인 헬퍼 스크립트는 최종 디코더 참조 검증을 자동화합니다.
javascript-obfuscator가 생성한 패턴을 대상으로 합니다.이 프로젝트를 위해 작성된 JSC 디오브퍼스케이터 소스 코드는 GNU General Public License 버전 2 또는 (선택에 따라) 이후 버전(GPL-2.0-or-later)에 따라 라이선스가 부여됩니다. 전체 라이선스 텍스트는 LICENSE를 참조하세요.
Copyright (C) 2026 Aleksandra "Hasherezade" Doniec @ Check Point Research.
View8 하위 모듈은 별도의 프로젝트입니다. Utils/disasm/ 아래의 제3자 파생 디스어셈블러 자료는 기존 출처를 유지하며 위 저작권 고지에 의해 재라이선스되지 않습니다.