1. Frida는 뭘까요
2024년 11월 3일
서론 #
출처 :
https://learnfrida.info/
추가1. 스토커의 해부학
추가2. frida document
이 글에서는 툴 사용법에 대한 내용은 담지 않을 것이기 때문에 사용법을 보려면 출처의 링크에서 확인하거나 frida document에서 확인할 수 있다.
Frida 란? #
Dynamic Binary Instrumentation(동적 바이너리 계측)을 지원하는 툴로 프로그램 런타임에 코드를 삽입해서 동작을 분석하거나 메모리를 수정할 수 있는 도구이다.
intel의 PIN과 DynamoRIO 와 비슷한 도구이지만, PC, 모바일, 여러 아키텍쳐 등 지원 범위가 넓고 C/C++ 코드 작성 및 컴파일 없이 자바스크립트 코드 상태로 쉽게 인젝트 할 수 있는 무료 오픈소스 도구라는 것이 큰 장점이다.
DBI 플로우 #
보통 어플리케이션을 계측할때 플로우는 아래 그림과 같다.
- 컨트롤 스크립트에서 계측을 위한 스크립트를 버퍼에 읽어온다.
- 컨트롤 스크립트에서 타겟 프로세스를 스폰하고 suspend 상태로 만든다.
- 컨트롤 스크립트는 타겟에 계측 스크립트를 인젝트하고, 추가적인 콜백을 리슨한다.
- on_message : 타겟에서 컨트롤 스크립트로 데이터를 전송할 수 있도록 등록하는 콜백 (send 나 console.log 같은것)
- on_child_added : 자식프로세스가 생성되면 보내주는 콜백이고, 이걸 이용해서 자식프로세스 생성 시점을 확인할 수 있어서 자식프로세스 추가 후킹이 가능해진다.(child-gating)
- 계측 스크립트는 타겟 프로세스에서 실행되면서 여러 데이터를 컨트롤 스크립트로 전달한다.
- 컨트롤 스크립트는 전달받은 데이터를 처리한다.(로그 저장이나 RPC 호출 등)
- 컨트롤 스크립트는 모든 작업이 끝나면 계측을 해제하고 타겟 프로세스를 정상 상태로 복원한다
frida 주요 프로젝트 #
frida 는 기능별(네이티브 후킹, js지원, cpp지원 등)로 여러 프로젝트로 나뉘어 있고 원한다면 각각의 프로젝트 중 필요한 프로젝트만 사용할 수 있지만, frida 전체 프로젝트를 빌드하면 모든 프로젝트 기능들이 합쳐져서 frida-server 바이너리에 포함되는 구조이다.
frida-tools #
frida-server에 명령을 보내는 cli 도구로, frida-server가 받는 프로토콜에 맞춰서 쉽게 요청을 보내도록 미리 작성된 코드들이다.
frida-server #
루팅된 장치에서 실행되는 서버로, frida-core 코드를 내장하고 그 기능을 클라이언트에게 제공한다. frida-server 프로젝트는 없고, frida-core를 빌드할때 아키텍쳐별로 frida-server 바이너리 파일이 빌드된다.
frida-core #
타겟 프로세스에 frida-agent 라이브러리를 주입하고 통신을 처리하면서 Frida의 API들을 사용자에게 제공한다.
frida-agent #
frida-core에 의해 주입된 공유 라이브러리 frida-agent-64.so 이며, js 코드를 실행시킬 수 있는 런타임이 포함되어 계측을 위한 js 스크립트를 실행시키거나 네이티브 후킹을 위한 gum 코드가 포함된다.
frida-core와 IPC로 통신하며 gum이나 v8을 통한 함수를 호출해준다.
frida-gum #
네이티브 코드 후킹이나 메모리 조작, 명령어단위 추적을 위한 실제 코드가 아키텍쳐마다 구현되어 있고, 바인딩된 gumpp, gumjs에서 호출할 수 있도록 인터페이스가 노출되어 있다.
gumjs(+v8) #
타겟 프로세스에 주입된 js 런타임(v8기반)을 말하며 js 코드의 실행을 담당하고, js로 구현된 API를 frida-gum의 C++ 함수와 연결해준다.
gumpp #
gumjs 는 js 기반이라면 c++을 이용해서 frida를 사용할 수 있도록 만들어진 환경이 gumpp 이다.
Frida API #
주요 모듈 #
Thread #
스레드를 동작, 중지, 백트레이스 얻을때 사용한다.
Process #
프로세스의 정보를 제공하며 아키텍쳐, 포인터 크기, 코드서명 정책, 스레드 ID, 로드된 모듈(라이브러리), 실행되는 모든 스레드 정보, 메모리맵 등을 얻어올 수 있다.
Memory #
메모리에서 문자열, 숫자, 포인터, 구조체 등을 읽고 쓸 수 있는 기능을 제공하며, 메모리덤프 및 스캔해서 패턴을 검색, 권한설정 등의 기능이 있다.
Module #
로드된 모듈에서 정보를 검색하거나 외부 모듈을 로드하는 등의 작업이 가능하다
Kernel #
커널모드의 API에 대한 액세스를 제공하고 커널영역에서 사용하는 Memory, Process 모듈의 기능을 합친 느낌이다.
C Module #
C 소스코드 조각을 메모리에 인젝트하고, js 런타임에서 사용할 수 있도록한다.
C의 구조체를 파싱할때도 좋은 방법일 수 있다.
Stalker 동작 방식 #
코드 추적용 엔진으로, 호출되는 모든 명령어나 함수를 추적할 수 있다.
그냥 라인바이 라인으로 후킹해서 추적을 한다면 너무 느리기 때문에 동적 재컴파일 기술을 사용한다.
위 그림처럼 원래 실행되어야 하는 코드에 Stalker동작을 위한 코드를 추가한 사본을 만들고 이 사본을 실행시키는 방식으로 변경해서 원래 코드의 체크섬을 해치지 않는 방식으로 동작한다.
Stalker 로 전달한 실제 필요한 옵션(명령어 트레이스, 함수호출 트레이스 중 원하는 것만)에 대한 코드만 call로 포함돼서 재컴파일되기 때문에 속도도 다른 방식에 비해 빠르다.
또다른 점은 이전 함수의 call에 대한 리턴주소 또한 push 되고, 호출할 함수의 주소가 call 되는 것을 볼 수 있는데, 안티디버그나 기존 동작 보존 모두를 위한 방법이다.
Interceptor 동작 방식 #
함수 후킹을 통해 호출을 가로채서 흐름을 검사하거나 수정할 수 있는 API 인데, 트램폴린 기반 인라인 후킹을 사용한다.
function_A를 후킹해서 call function_B 를 추가하고 function_B 가 끝날때 trampoline으로 점프해서 기존 function_A 에서 덮어쓰여진 코드를 실행한 후 function_A 로 점프하는 방식이다.