개요
REA는 MCP를 통해 AI 프로그래밍 에이전트에 리버스 엔지니어링 기능을 연결하여, 소스 코드 없이도 네이티브 바이너리, JavaScript/Electron 애플리케이션, .NET 어셈블리 및 웹사이트를 분석할 수 있습니다. Hopper 및 Ghidra와 통합하여 심층 정적 분석을 수행하고, 로컬에서 실행되며 증거와 한계 설명이 포함된 결론을 제공하며, 명령줄 도구로 독립적으로 사용할 수도 있습니다.
README 미리보기
\n\n**English** · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)\n\n# REA: Reverse Engineer Anything\n\n### One MCP for reverse engineering across binaries, applications, and runtime behavior.\n\n**See a feature you like. Understand how it works, down to the binary level.**\n\n[](https://www.npmjs.com/package/rea-agents)\n[](https://github.com/morluto/rea/actions/workflows/ci.yml)\n[](#tool-catalog-for-investigation)\n[](https://nodejs.org/)\n[](LICENSE)\n[](https://discord.gg/GkcryMnJDM)\n\n\n\n[Quick start](#quick-start) · [Current status](#current-status) · [Investigation model](#the-investigation-model) · [Tool catalog](#tool-catalog-for-investigation) · [Roadmap](#roadmap) · [How it works](#how-it-works)\n\nnpx rea-agents setup\n\n\n\n\n\n\n\n\n\n\n \n \n Join the Reverse Engineering Community\n \n Discord · Q&A · Show and Tell\n\n\n\n\n\n\n\n\n---\n\nSee a feature in an app that you want in your own product? Ask your agent to investigate it with REA. It can inspect the app without its source code, explain how the feature works, show the evidence, and build a version for your project.\n\nREA connects your agent to tools for inspecting native binaries, JavaScript and Electron apps, .NET assemblies, and websites. You can also use the same tools from your terminal. Analysis runs locally, and results include the evidence and limitations behind each conclusion.\n\nSetup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper or Ghidra installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs neither engine.\n\n## Quick start\n\n### Run setup (recommended)\n\nSet up REA with your agent:\n\n```bash\nnpx rea-agents setup\n```\n\nChoose which supported agents should use REA, then review the exact paths and changes before approving. Existing REA registrations are selected by default; newly detected agents are avail
FAQ (5)
문제 해결Ghidra MCP 응답(예: list_procedures)이 겨우 ~20k 행에서 10 MiB resource_constraint 제한에 도달하는 이유는 무엇이며, 중복된 raw_result 데이터는 어떻게 수정할 수 있나요?
이것은 REA ≤6.7.0의 버그였습니다: Ghidra 어댑터(GhidraProviderClient.ts projectExecution)는 브리지 응답이 normalized_result와 바이트 단위로 동일했음에도 불구하고 이를 무조건 raw_result에 복사했습니다. 결과적으로 각 Evidence 레코드는 결과를 두 번씩 담게 되었고, MCP 응답은 Evidence를 텍스트와 구조화된 콘텐츠 양쪽 모두에 포함하기 때문에 응답에는 약 4개의 복사본이 존재했습니다. 이로 인해 10 MiB 응답 예산에 들어갈 수 있는 인벤토리가 절반으로 줄었습니다(대규모 인벤토리는 ~40k 행이 아니라 ~20k 행에서 resource_constraint로 실패했습니다). 수정 방법: normalized_result와 raw_result가 바이트 단위로 동일할 때마다 raw_result를 null로 설정하는 PR #5355가 포함된 빌드로 업그레이드하세요(AnalysisProvider.ts 및 docs/mcp-contracts.md의 계약에 따르면 raw_result는 result와 구별되는 프로바이더 표현만 담아야 합니다). 래퍼의 limitations는 이미 Evidence limitations에 병합되어 있으므로 데이터 손실은 없습니다. 주요 변경 사항: raw_result.value를 통해 analyze_function 출력을 파싱하던 클라이언트는 normalized_result로 전환해야 합니다. 이제 이러한 작업에서는 raw_result가 null이기 때문입니다.
문제 해결rizin_debug_session_status가 CJK 또는 emoji 출력에 대해 16KB 최근 출력 예산보다 더 많이 유지하는 이유는 무엇인가요?
최근 프레임 히스토리가 UTF-8 바이트가 아닌 코드 포인트 수로 잘려, 雪와 같은 3바이트 CJK 문자가 유지되는 크기를 세 배로 만들었습니다(16,384가 아닌 49,152바이트). 또한 잘라낼 때 이모지의 서로게이트 페어가 분할되어 잘못된 형식의 UTF-8이 남을 수 있었습니다. 이 문제는 PR #5246을 통해 버전 6.8.0에서 수정되었습니다. 6.8.0 이상으로 업그레이드하세요. 이 수정은 바이트 길이를 측정하고(예: TextEncoder().encode) 코드 포인트 경계에서만 잘라내어, CJK 출력을 16,384바이트 예산 내로 유지하고 이모지 접두사가 올바른 형식을 유지하도록 합니다.
문제 해결Rizin의 recent_output이 CJK 또는 이모지 출력 시 16 KB 프레임 제한을 초과하는 이유는 무엇이며, UTF-8 바이트 버짓의 3배를 유지하면서 잘림 문제를 해결하는 방법은 무엇인가요?
근본 원인: src/rizin/RizinDebugSessionManager.ts(1068-1078행)에서 최근 프레임 절단 로직이 디코딩된 JS 문자열인 frame.text를 슬라이스하므로, String.prototype.slice가 바이트가 아닌 UTF-16 코드 유닛을 기준으로 개수를 셉니다. MAX_RECENT_FRAME_BYTES = 16 * 1024인 경우 3바이트 CJK 문자가 코드 유닛 1개로만 계산되므로, 하나의 프레임이 최대 49,152바이트(예산의 3배)까지 유지하게 되고, 64개 프레임 링은 의도한 1 MiB에서 3 MiB로 부풀어 오릅니다.
수정: Buffer를 사용하여 바이트 기준으로 슬라이스하고 UTF-8 연속 바이트(continuation bytes)를 뒤로 거슬러 올라가는 방식을 사용합니다. 이는 1046-1052행의 #startupCapturedOutput에서 이미 사용하고 있는 것과 동일한 접근 방식입니다:
const bytes = Buffer.from(frame.text, "utf8");
let end = Math.min(bytes.length, MAX_RECENT_FRAME_BYTES);
// avoid splitting a multi-byte sequence: back off continuation bytes (0b10xxxxxx)
while (end > 0 && (bytes[end] & 0xc0) === 0x80) end--;
const kept = bytes.subarray(0, end).toString("utf8");
const historyFrame =
frameBytes > MAX_RECENT_FRAME_BYTES || frame.truncated
? `${kept}[recent frame truncated]`
: frame.text;
참고: 기존 테스트는 ASCII(코드 유닛 == 바이트인 경우)만 다루기 때문에 이 회귀가 발견되지 않았습니다. CJK/이모지 절단 테스트를 추가하세요. 이 이슈(#5242)는 #5091의 중복이므로, 수정 사항은 해당 이슈에서 추적하세요.
문제 해결rea에서 React 번들을 분석할 때 발생하는 'Owned JavaScript worker exhausted its heap' 오류를 해결하는 방법
이는 PR #4243(commit 42fc6c53a)에서 도입된 rea의 JavaScript member-mutation pass에 존재하는 알려진 리그레션입니다. 순환 감지가 바인딩에서 개별 초기화식으로 이동하면서, alias 순환 내부의 결과가 전혀 메모이제이션되지 않고 분석이 초기화식 순서를 모두 열거하게 되어, React 스타일 번들(playwright-core, Notion 렌더러, Next.js framework-*.js 청크)에서 (4 GiB로 늘려도) 워커 힙을 고갈시킵니다.
해결 방법:
1. npm 릴리스 이후 버전으로 업그레이드하세요. 이 버그는 rea-agents@6.7.0(현재 npm latest)에 존재하지만 main의 commit e4c3d7239에서 수정되었습니다. npm 패키지 대신 main 브랜치의 빌드(58d6043에서 정상 작동 확인됨)를 설치하세요.
2. 우회 방법: #4243 이전 빌드(commit 1bd5c5c87)로 고정/다운그레이드하세요. 해당 버전은 동일한 파일을 약 1~2초 만에 분석합니다.
참고: 힙 제한을 높여도 도움이 되지 않습니다. 탐색이 지수적으로 증가하여 약 17초 만에 4 GiB를 고갈시킵니다. 수정 후에는 동일한 파일이 리소스 제약으로 인한 unknown 없이 약 430 MB RSS로 약 10초 만에 완료됩니다.
문제 해결match_native_functions가 대규모 함수 인벤토리를 거부할 때 발생하는 'AnalysisResourceConstraintError'(96 MiB 허용량)를 해결하는 방법
match_native_functions(main에만 존재, 6.7.0 릴리스에는 없음)는 호출당 고정된 96 MiB representation 허용량을 부과하며, 한쪽당 ~10k 행을 초과하는 Ghidra 형태의 인벤토리를 거부합니다(일반 address+name 행의 경우 ~19.5k 초과). 수정 사항: (1) PR #7108은 공유 인벤토리 Evidence ID가 함수당이 아닌 한 번만 청구되도록 계산 방식을 수정하여, 변경되지 않은 96 MiB 기본값에서 한쪽당 ~22k Ghidra 형태 행까지 제한을 상향합니다. (2) PR #7112는 재정의 기능을 추가합니다: config(rea setup으로 복사됨)에서 native.matching_representation_bytes를 설정하거나 REA_NATIVE_MATCHING_REPRESENTATION_BYTES 환경 변수를 설정하세요 — 기본값 96 MiB, 최대 1 GiB. 512 MiB에서 한쪽당 50,000개 행이 성공적으로 매칭되었습니다(CLI: 8.7 s, 최대 메모리 1.34 GB; MCP: 2.7 s). 거부는 재시도 불가능 상태로 유지되며 details.limit에 제한과 재정의 방법이 명시됩니다.