
제로 의존성 리눅스 메모리 포렌식: 커널 내장 BTF 및 kallsyms를 활용하여 외부 디버그 정보 없이 타입 인식 메모리 분석을 수행합니다.
mquire는 memory와 inquire 단어를 합친 것으로, osquery에서 영감을 받은 메모리 쿼리 도구입니다.
mquire는 외부 디버그 심볼 없이 Linux 커널 메모리 스냅샷을 분석할 수 있습니다.
분석에 필요한 모든 것은 메모리 덤프 자체에 이미 포함되어 있습니다. 즉, 다음을 분석할 수 있습니다:
커널 버전 요구 사항:
scripts/kallsyms.c 형식 변경으로 인해)mquire는 최신 Linux 커널에 내장된 두 가지 유형의 정보를 읽어 커널 메모리를 분석합니다:
/proc/kallsyms에서 사용하는 동일한 데이터).유형 정보와 심볼 위치를 결합함으로써 mquire는 다음과 같은 복잡한 커널 데이터 구조를 찾고 읽을 수 있습니다:
이를 통해 디스크에서 삭제된 경우에도 커널의 파일 캐시에서 직접 파일을 추출할 수 있습니다.
Kallsyms 스캐너는 커널 소스의 scripts/kallsyms.c 데이터 형식에 의존합니다. 향후 커널 버전에서 이 형식이 변경되면 스캐너 휴리스틱을 업데이트해야 할 수 있습니다.
mquire는 시스템의 다양한 측면이나 도구 자체의 상태를 쿼리하기 위한 SQL 테이블을 제공합니다.
mquire는 데이터베이스가 아닙니다. 각 쿼리는 메모리를 스캔하고 포인터를 따라가며 커널 데이터 구조를 재구성합니다. 미리 계산된 인덱스나 캐시된 결과는 없습니다. 모든 테이블 액세스는 커널 데이터를 순회하는 것입니다. 중복 스캔을 방지하려면
AS MATERIALIZED를 사용하고(Query Optimization 참조),task_open_files및memory_mappings와 같은 프로세스별 테이블을 쿼리할 때는task와 같은 제약 조건을 제공하여 단일 프로세스로 스캔을 제한하세요.
설계 원칙: 가상 주소를 조인 키로 사용. 테이블은
virtual_address(기본 데이터 구조의 커널 주소)를 표준 조인 키로 사용합니다.pid나 다른 사용자에게 보이는 식별자가 아닙니다. 이는 의도적인 것입니다. 동일한 PID가 여러 검색 소스와 루트 작업에 걸쳐 여러 번 나타날 수 있지만, 가상 주소는 특정 커널 객체를 고유하게 식별하기 때문입니다. SQL 테이블과 기본LinuxOperatingSystemAPI 모두 이 규칙을 중심으로 구축되었습니다.
/proc/kallsyms와 동일한 데이터)dmesg 명령어와 동일한 데이터)task 제약 조건을 제공하거나 모든 작업을 한 번에 쿼리)task 제약 조건을 제공하거나 모든 작업을 한 번에 쿼리)task 제약 조건이 필요하므로 tasks/processes와 조인하세요 (예: JOIN task_capabilities c ON c.task = p.virtual_address).task 제약 조건이 필요합니다.mem 항목. kernel_module 제약 조건이 필요하므로 kernel_modules와 조인하세요 (예: JOIN kernel_module_mem_entries r ON r.kernel_module = m.virtual_address).ftrace_ops_list 심볼에서부터 탐색한 struct ftrace_ops 노드 목록. 단일 노드를 읽으려면 virtual_address를 제한하고, 임의의 노드에서부터 탐색하려면 start_vaddr(선택적으로 end_vaddr로 범위 지정)를 제한하세요.mquire는 세 가지 주요 명령어를 제공합니다:
mquire shell - 메모리 스냅샷을 쿼리하기 위한 대화형 SQL 셸 시작mquire query - 단일 SQL 쿼리 실행 및 결과 출력 (JSON 또는 테이블 형식 지원)mquire command - 메모리 스냅샷에서 사용자 정의 명령어 실행 (예: .task_tree, .system_version, .dump)mquire는 SQL 쿼리와 구분하기 위해 점(.)으로 시작하는 특수 명령어를 제공합니다.
이 명령어들은 대화형 셸과 mquire query에서 작동합니다:
.tables - 사용 가능한 모든 테이블 나열.schema - 모든 테이블의 스키마 표시.schema <table> - 특정 테이블의 스키마 표시.commands - 사용 가능한 모든 사용자 정의 명령어 나열.exit - 대화형 셸 종료 (셸 전용)이 명령어들은 대화형 셸과 mquire command에서 작동합니다:
--help를 사용하여 사용 가능한 옵션과 사용 정보를 확인하세요. 예: .task_tree --help
.system_version운영 체제 버전 정보를 표시합니다.
이 명령어는 SELECT * FROM os_version과 동일하지만, 형식화된 출력을 제공하는 편의 명령어입니다.
.task_treeLinux의 pstree 명령어와 유사하게 실행 중인 프로세스 및 스레드의 계층 트리를 표시합니다.
옵션:
--show-threads - 프로세스 외에 스레드도 포함합니다. 활성화되면 각 항목에 대해 TGID와 TID를 모두 표시합니다.--use-real-parent - 트리 구조를 작성할 때 parent 대신 real_parent 필드를 사용합니다. real_parent 필드는 재부모화 전의 원래 부모 프로세스를 보여줍니다 (부모 프로세스가 종료된 후에도 프로세스 생성 체인을 추적하는 데 유용).참고:
[TGID TID], 스레드 숨김 시 [TGID]입니다. TGID(Thread Group ID)는 일반적으로 PID라고 불리는 것입니다. 메인 스레드(TGID == TID인 경우)는 두 값이 동일합니다..carve가상 메모리 영역을 디스크로 추출합니다. 이 명령어는 주어진 페이지 테이블을 사용하여 특정 가상 주소 범위에서 원시 메모리 내용을 추출하며, 프로세스 메모리, 힙 내용 또는 기타 메모리 영역을 추출하는 데 유용합니다.
인수:
ROOT_PAGE_TABLE - 루트 페이지 테이블의 물리적 주소 (선택적 0x 접두사가 있는 16진수 문자열). 변환에 사용할 주소 공간을 결정합니다.VIRTUAL_ADDRESS - 추출을 시작할 가상 주소 (선택적 0x 접두사가 있는 16진수 문자열).SIZE - 추출할 바이트 수.DESTINATION_PATH - 추출된 메모리가 기록될 출력 파일 경로.참고:
.dump커널의 파일 캐시에서 파일을 추출하여 메모리에서 직접 파일을 복구합니다. 이 명령어는 모든 작업과 해당 열린 파일 디스크립터를 반복하며 페이지 캐시에서 파일 내용을 추출합니다.
인수:
OUTPUT - 추출된 파일의 출력 디렉터리. 파일은 TGID별로 구성됩니다 (예: tgid_1234/path/to/file).참고:
mquire는 다음을 위해 설계되었습니다:
사전 빌드된 패키지는 CI 실행의 산출물로 제공됩니다. Actions 탭에서 성공적인 워크플로 실행을 선택하고 산출물을 다운로드하여 받을 수 있습니다. 다음 패키지 형식을 사용할 수 있습니다:
.deb 패키지.rpm 패키지.tar.gz 아카이브mquire는 Rust로 작성되었습니다. 빌드하려면:```bash
git clone https://github.com/trailofbits/mquire cd mquire
cargo build --release
## 지원되는 스냅샷 형식
mquire는 다음 메모리 스냅샷 형식을 지원하며, 파일 확장자로 감지됩니다:
| 형식 | 확장자 | 설명 |
|--------|-----------|-------------|
| Raw | `.raw` | 평면 물리 메모리 덤프 (물리 주소 공간의 바이트 단위 복사본) |
| LiME | `.lime` | 주소 범위 헤더가 있는 [Linux Memory Extractor](https://github.com/504ensicsLabs/LiME) 형식 |
| ELF 코어 | `.elf` | PT_LOAD 세그먼트가 포함된 ELF 코어 덤프 (`virsh dump` 또는 QEMU `dump-guest-memory`에서 생성된 형태) |
## 메모리 스냅샷 획득
### AVML 사용 (권장)
라이브 Linux 시스템에서 메모리 스냅샷을 획득하려면 [AVML](https://github.com/microsoft/avml)을 권장합니다. 이전에는 [LiME](https://github.com/504ensicsLabs/LiME)가 제안되었으나 더 이상 적극적으로 유지 관리되지 않습니다.```bash
sudo avml output.lime
중요: mquire용 스냅샷을 획득할 때
--compress를 사용하지 마십시오. mquire는 압축된 AVML 스냅샷을 지원하지 않습니다. 압축된 스냅샷이 있는 경우 먼저avml-convert를 사용하여 압축을 해제하십시오:avml-convert compressed.lime uncompressed.lime
추가 옵션은 AVML 문서를 참조하십시오.
libvirt/KVM 가상 머신의 경우 virsh dump를 사용하여 ELF 코어 덤프를 생성하십시오:```bash
virsh -c qemu:///system dump output.elf --memory-only --format elf
VM은 덤프 중에 일시 중지되고 이후에 재개됩니다. `--live`를 추가하면 일시 중지를 피할 수 있지만, 스냅샷 일관성이 떨어집니다.
## 시작하기
메모리 스냅샷을 얻으면 SQL 쿼리와 사용자 정의 명령을 사용하여 상호작용할 수 있습니다. mquire는 스냅샷과 상호작용하는 세 가지 방법을 제공합니다:
### 대화형 셸