Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
AudioServer-Voip-Recorder — 🔬 libaudioflinger.so를 동적으로 후킹(hooking)하여 실시간 VoIP 오디오 캡처(Uplink/Downlink)를 수행하는 고급 Android 연구 도구입니다. Android 14의 WhatsApp, Signal, Telegram에서 테스트 및 구축되었습니다. | Kitploit
도구/GitHubGitHub/nighthawkk/audioserver-voip-recorder
Android SecurityReverse EngineeringMobile Security
GitHubnighthawkk/audioserver-voip-recorder

AudioServer-Voip-Recorder

🔬 libaudioflinger.so를 동적으로 후킹(hooking)하여 실시간 VoIP 오디오 캡처(Uplink/Downlink)를 수행하는 고급 Android 연구 도구입니다. Android 14의 WhatsApp, Signal, Telegram에서 테스트 및 구축되었습니다.

저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
9시간 28분 전아직 검토되지 않음

목표: Android의 audioserver(특히 libaudioflinger.so)를 후킹하고 시스템이 통화(communication) 모드에 있을 때 업링크(마이크) 및 다운링크(스피커) PCM 버퍼를 기록하여 VoIP 스트림 캡처를 시연합니다.

프로젝트 설계 및 방법론

아키텍처:

  • 컨트롤러 앱 (Android)
    SELINUX 정책 설정, 페이로드 주입, 데이터 이동, 재생을 관리하는 9개의 버튼이 있는 UI입니다.

  • 페이로드 (libaudiohook.so)
    앱 프로젝트의 일부로 빌드되는 C++ 공유 라이브러리로, Dobby를 사용하여 내부 AudioFlinger 메서드를 후킹하고 원시 PCM 버퍼를 세션 디렉터리에 기록합니다.

  • 후처리
    추가 도구인 tools/audioparser.py는 원시 .ac(다운링크)/.bc(업링크) 파일을 WAV로 변환합니다. 앱의 파일 관리자도 앱 내에서 변환 및 재생할 수 있습니다.

  • 연구 유틸리티
    초기 함수 추적 및 오프셋 발견을 위한 Frida 스크립트; 심볼/오프셋 및 기타 스니펫을 위한 분석 파일.

컨트롤러 앱

이 Android 애플리케이션은 audioserver를 통한 VoIP 녹음을 관리하기 위한 그래픽 인터페이스를 제공합니다. Android 오디오 스택을 후킹하여 VoIP 애플리케이션의 마이크 및 스피커 오디오를 캡처하는 네이티브 페이로드와 통합됩니다.

이 앱은 필요한 SELinux 정책 주입, 모니터링 시작/중지, 기록된 데이터 관리, 캡처된 VoIP 오디오 파일 재생을 할 수 있는 제어 센터 역할을 합니다.

기능

메인 액티비티에는 9개의 제어 버튼이 있습니다:

  1. 정책 주입
    audioserver와 이 앱이 함께 작동하는 데 필요한 SELinux 정책을 주입합니다.

  2. 모니터링 시작
    공유 라이브러리 페이로드를 audioserver에 주입하여 RecordTrack 및 PlaybackTrack을 후킹함으로써 VoIP 오디오 캡처를 활성화합니다. 프로세스 주입에는 **AndKittyInjector**를 사용합니다.

  3. 모니터링 중지
    audioserver 프로세스를 다시 시작하여 모니터링을 중지하고 주입된 후크를 제거합니다.

  4. 데이터 복사
    캡처된 원시 PCM 오디오를 임시 디렉터리 /data/local/tmp/voip에서 /sdcard/voip로 복사합니다.

    • 그 후 임시 디렉터리를 정리합니다.
  5. 로그 보기
    주입, 후킹, 녹음 상태와 관련된 로그를 표시합니다.

  6. SELinux 활성화
    SELinux 강제(enforcing) 모드를 복원합니다.

  7. SELinux 비활성화
    SELinux를 허용(permissive) 모드로 설정합니다. 주입된 정책이 실패할 때 사용합니다.

  8. 오디오 재생
    사용자 지정 VoIP 파일 관리자(/sdcard/voip/)를 엽니다:

    • 원시 PCM 파일을 메모리에서 WAV 형식으로 변환합니다.
    • 변환된 오디오를 앱 내에서 직접 재생합니다.
  9. 데이터 삭제
    /data/local/tmp/voip 및 의 모든 오디오 데이터를 삭제합니다. : 데이터 삭제 후에는 데이터를 저장할 디렉터리 생성을 위해 에 다시 주입해야 합니다.

root@kitploit:~
+----------------------+    
|                      |    
|   App MainActivity   |    
|                      |    
|                      |    
|(9 Control Buttons UI)|    
|                      |    
|                      |    
+----------+-----------+    
           |                
           |                
           |                
+----------v-----------+    
|                      |    
|       JNI Layer      |    
|                      |    
| Selinux, Process Inje|    
| ction,               |    
|                      |    
|                      |    
+----------------------+    

후킹 페이로드

이 공유 라이브러리는 **audioserver**에 주입되어 AUDIO_MODE_IN_COMMUNICATION을 감지하고 미리 정의된 패키지 이름 집합에 대해 Android 오디오 스택에서 직접 VoIP 오디오 스트림을 캡처합니다.

libaudioflinger.so 내부의 중요한 메서드를 가로채기 위해 Dobby 인라인 후킹 프레임워크를 사용합니다.
업링크(마이크) 및 다운링크(스피커) 오디오 스트림이 모두 캡처되어 이후 처리를 위해 세션 파일에 기록됩니다.

후킹 지점

이 라이브러리는 AudioFlinger 및 관련 클래스 내부의 다음 함수에 후크를 설치합니다:

대상 애플리케이션

이 라이브러리는 UID → 패키지 매핑을 기반으로 스트림을 필터링합니다.

현재 모니터링되는 앱:

  • com.whatsapp
  • com.whatsapp.w4b (WhatsApp Business)
  • org.thoughtcrime.securesms (Signal)
  • org.telegram.messenger
  • org.telegram.messenger.web

audioserver_hook.cpp 안에 다른 애플리케이션을 추가할 수도 있습니다:

root@kitploit:~
static const char* kTargetPackages[] = {  
    "com.whatsapp",  
    "com.whatsapp.w4b",  
    "org.thoughtcrime.securesms",  
    "org.telegram.messenger",  
    "org.telegram.messenger.web"  
};

파일 출력

  • 세션 디렉터리는 audioserver에 주입할 때 다음 경로 아래에 생성됩니다: /data/local/tmp/voip/audioserver_session_<timestamp>/

  • 파일은 처음에 .tmp 확장자로 생성된 후 트랙 중지 시 이름이 변경됩니다:

    • 업링크 (마이크) → <packageName>_<sampleRate>_<timestamp>.bc
    • 다운링크 (스피커) → <packageName>_<sampleRate>_<timestamp>.ac
  • 예시 세션:

root@kitploit:~
	/data/local/tmp/voip/audioserver_session_1725389200/
	├── com.whatsapp_48000_1725389201_123456.ac
	├── com.whatsapp_48000_1725389201_123789.bc
	

오프셋

대상 라이브러리가 스트리핑(stripped)되어 libaudioflinger.so에 메서드가 내보내지지 않으므로, 성공적인 후킹을 위해 메서드 및 기타 관련 구성 요소의 정확한 오프셋이 필요합니다.

이러한 오프셋은 IDA-PRO를 사용한 정적 분석 또는 Frida를 사용한 동적 분석으로 추출할 수 있습니다. 오프셋을 알게 되면 offsets.h 헤더 파일 안에서 교체할 수 있습니다.

필요한 오프셋:
메서드:
  1. AUDIOFLINGER_SETMODE_OFFSET
    • 메서드: android::AudioFlinger::setMode(audio_mode_t)
    • 맹글드 이름: _ZN7android12AudioFlinger7setModeE11audio_mode_t
  2. RECORDTRACK_GETNEXTBUFFER_OFFSET
    • 메서드: android::AudioFlinger::RecordThread::RecordTrack::getNextBuffer(android::AudioBufferProvider::Buffer *)
    • 맹글드 이름: _ZN7android12AudioFlinger12RecordThread11RecordTrack13getNextBufferEPNS_19AudioBufferProvider6BufferE
  3. TRACK_GETNEXTBUFFER_OFFSET
    • 메서드: android::AudioFlinger::PlaybackThread::Track::getNextBuffer(android::AudioBufferProvider::Buffer *)
    • 맹글드 이름: _ZN7android12AudioFlinger14PlaybackThread5Track13getNextBufferEPNS_19AudioBufferProvider6BufferE
  4. TRACK_STOP_OFFSET
    • 메서드: android::AudioFlinger::PlaybackThread::Track::stop(void)
    • 맹글드 이름: _ZN7android12AudioFlinger14PlaybackThread5Track4stopEv
기타 오프셋:
  1. SAMPLERATE_OFFSET
  2. UID_OFFSET
  3. ISOUT_OFFSET
  4. FORMAT_OFFSET
  5. CHANNELMASK_OFFSET
  6. ATTR_OFFSET

이들은 정적 분석으로 얻을 수 있습니다.

  • 라이브러리 - libaudioflinger.so
  • 메서드 - android::AudioFlinger::ThreadBase::TrackBase::TrackBase
root@kitploit:~
TrackBase::TrackBase(
        IAfThreadBase *thread,
            const sp<Client>& client,
            const audio_attributes_t& attr,
            uint32_t sampleRate,
            audio_format_t format,
            audio_channel_mask_t channelMask,
            size_t frameCount,
            void *buffer,
            size_t bufferSize,
            audio_session_t sessionId,
            pid_t creatorPid,
            uid_t clientUid,
            bool isOut,
            const alloc_type alloc,
            track_type type,
            audio_port_handle_t portId,
            std::string metricsId)

참고 사항

  • IN_COMMUNICATION 모드만 캡처됩니다. 일반 오디오(음악, 벨소리 등)는 무시됩니다.
  • Telegram 및 Signal에 대한 특별 처리는 올바른 샘플 레이트(Telegram: 48000 Hz, Signal: 8000 Hz)를 적용하여 전화 벨소리나 통화 종료음과 같은 불필요한 오디오를 무시합니다.
  • PCM은 원시 상태로 저장되며, 컨트롤러 앱은 재생을 위해 나중에 PCM → WAV로 변환합니다.
root@kitploit:~
 ┌─────────────────────────────┐
 │        VoIP Apps            │
 │  (WhatsApp / Signal / TG)   │
 └───────────────┬─────────────┘
                 │ Audio in/out
                 ▼
 ┌─────────────────────────────┐
 │       audioserver           │
 │  (libaudioflinger.so)       │
 └───────┬─────────┬───────────┘
         │         │
   uplink│         │downlink
 (mic)   │         │(speaker)
         ▼         ▼
 ┌───────────-──┐   ┌────────────-─┐
 │ RecordTrack  │   │  Track       │
 │ getNextBuffer│   │ getNextBuffer│
 └───────┬────-─┘   └───────┬────-─┘
         │                 │
   ┌─────▼─────┐     ┌─────▼─────┐
   │ hook_...  │     │ hook_...  │
   │ (uplink)  │     │ (downlink)│
   └─────┬─────┘     └─────┬─────┘
         │                 │
         └──────┬───┬──────┘
                │   │
                ▼   ▼
     ┌───────────────────────────┐
     │  /data/local/tmp/voip/    │
     │  audioserver_session_*    │
     │   - *.bc  (uplink)        │
     │   - *.ac  (downlink)      │
     └───────────────────────────┘

대상 함수 식별

사용된 프로세스:

  1. 동적 추적 - Frida:
    • Frida를 사용하여 VoIP 통화 중 모든 함수 호출을 추적했습니다.
    • 오디오 버퍼 처리를 담당하는 모든 함수를 필터링했습니다.
    • 그런 다음 오디오 버퍼를 캡처하고 처리하는 Frida 스크립트를 만들었습니다.
  2. AOSP 검토 및 클래스 매핑
    • AudioFlinger는 PlaybackThread 및 RecordThread를 통해 재생/캡처를 관리합니다.
    • 클라이언트별 오디오는 PlaybackThread::Track(다운링크) 및 RecordThread::RecordTrack(업링크)로 표현됩니다.
  3. 앱 특정 스트림으로 필터링
    • UID→패키지 매핑을 사용하여 대상 앱으로 제한했습니다.
  4. 안정성 및 오프셋
    • 최종 네이티브 페이로드는 스트리핑된 심볼을 견디기 위해 base + 하드코딩된 오프셋(app/src/main/cpp/include/offsets.h에 보관)으로 주소를 해석합니다.

MODE_IN_COMMUNICATION 감지

AudioFlinger::setMode(int mode)를 후킹하고 전역 상태를 유지합니다:

  • 호출마다 모드 변경을 기록하고 g_currentAudioMode를 업데이트합니다.
  • (마이크 및 스피커 후크 모두에서) 후크는 g_currentAudioMode == AUDIO_MODE_IN_COMMUNICATION인지 확인합니다.
  • 이를 통해 VoIP 세션이 활성화된 동안에만 버퍼를 덤프하여 음악/벨소리/기기 재생/마이크 녹음 등을 피할 수 있습니다.

PoC 빌드 및 실행

프로젝트 구조

root@kitploit:~
.
├── Android_App/ 
|   ├── app/                           # Android Studio project (App + Payload)
|	│   ├── src/
|	│   │   ├── main/
|	│   │   │   ├── java/              # Controller App Java/Kotlin sources
|	│   │   │   ├── cpp/               # Payload source (built with the app)
|	│   │   │   │   └── include/
|	│   │   │   │       └── offsets.h  # Function offsets for tested builds
├── tools/
│   ├── audioparser.py             # Converts .ac/.bc raw files → WAV
│   ├── frida/                     # Frida scripts for initial hook discovery
│   │   ├── host_audioserver.py
│   │   ├── agent_audioserver.js
├── app-release.apk                 # Signed release apk
└── README.md                       # Root README (design, build, run instructions)

사전 요구 사항

  • Android Studio + NDK
  • 루팅된 에뮬레이터(예: rootAVD) 또는 소유한 테스트 기기(예: Magisk)
  • 테스트할 VoIP 앱 설치(소유하거나 관리하는 동일한 앱)
  • audioparser.py용 Python

앱 빌드(페이로드도 함께 빌드됨)

  1. Android Studio에서 app/을 엽니다.
  2. NDK가 설치되어 있는지 확인합니다(SDK Manager → SDK Tools → NDK).
  3. Debug 변형을 빌드합니다. Gradle/CMake 구성은 프로젝트의 일부로 네이티브 페이로드(libaudiohook.so)를 컴파일합니다.

테스트 대상에 설치

adb install -r app/build/outputs/apk/debug/app-debug.apk 또는 제공된 app-release.apk를 설치합니다: adb install -r app-release.apk

아티팩트를 분리하는 경우 테스트를 위해 공유 라이브러리를 푸시할 수도 있습니다: adb push app/src/main/jniLibs/arm64-v8a/libaudiohook.so /data/local/tmp/

PoC 실행(에뮬레이터/소유 기기)

  1. 컨트롤러 앱을 실행 -> 메시지가 표시되면 루트 권한을 부여합니다.
  2. **"정책 주입(Inject Policies)"**을 탭합니다.
    테스트 환경에서 앱과 audioserver 상호 작용에 필요한 SELinux 규칙을 준비합니다.
  3. **"모니터링 시작(Start Monitoring)"**을 탭합니다.
    앱은 AndKittyInjector를 사용하여 audioserver에 페이로드를 주입합니다.
  4. 테스트 VoIP 통화를 겁니다(예: 본인의 WhatsApp/Signal/Telegram 계정).
  5. **"모니터링 중지(Stop Monitoring)"**을 탭합니다.
    audioserver를 다시 시작합니다.
  6. **"데이터 복사(Copy Data)"**을 탭합니다.
    세션 파일을 /data/local/tmp/voip/…에서 /sdcard/voip/로 이동합니다(임시 디렉터리를 정리합니다).
  7. 재생
    • 앱 내에서: **"오디오 재생(Play Audios)"**이 PCM → WAV로 변환하고 재생합니다.
    • 또는 오프라인:
      root@kitploit:~
       adb pull /sdcard/voip/
      python3 tools/audioparser.py voip/
      

추가 버튼:

  • "로그 보기(View Logs)": 인젝터/후크 상태를 확인합니다.
  • "SELinux 활성화" / "SELinux 비활성화": 정책이 너무 엄격한 경우 랩에서 강제/허용 모드를 전환합니다.
  • "데이터 삭제(Delete Data)": /data/local/tmp/voip/와 /sdcard/voip/를 모두 정리합니다.

테스트된 버전 및 기기

  • 에뮬레이터: AVD API 34 (x86_64) - Android 14 - rootAVD로 루팅됨
  • 기기: 삼성 갤럭시 S22 (ARM64) - Android 14 - 빌드 S901EXXSCEYB1 - Magisk로 루팅됨

테스트된 앱

  • Whatsapp
  • Whatsapp Business
  • Signal
  • Telegram

주요 과제 및 해결 방법

  1. 스트리핑된 심볼
    • 문제: dlsym으로 심볼을 직접 찾을 수 없습니다.
    • 해결 방법: 정적 분석에서 얻은 오프셋을 사용합니다.
  2. 빌드별 다른 심볼/오프셋
    • 문제: 스트리핑된 심볼은 빌드마다 다르며, 직접 dlsym은 실패할 수 있습니다.
    • 해결 방법: 테스트된 빌드(offsets.h)에 대해 base + 하드코딩된 오프셋을 사용하고, Frida 심볼 덤프와 IDA-PRO로 검증합니다.
  3. 모드 감지 정확도
    • 문제: VoIP 세션 외부에서 녹음하면 노이즈가 많은 데이터가 생성됩니다.
    • 해결 방법: AudioFlinger::setMode(IN_COMMUNICATION)에서 캡처 후크를 걸고, 전환을 기록하며, 전역 모드 플래그를 저장합니다.
  4. SELinux
    • 문제: 임시 디렉터리에 쓰기 및 audioserver와의 IPC가 차단될 수 있습니다.
    • 해결 방법: 필요한 규칙을 추가하는 정책 주입(Inject Policies) 단계를 제공하고, 테스트 환경에서 디버깅을 위해 SELinux 활성화/비활성화 토글을 노출합니다.
  5. 파일 수명 주기 및 이름 변경
    • 문제: 스레드 중지 시 부분적/손상된 출력을 방지해야 합니다.
    • 해결 방법: 먼저 .tmp로 작성하고, stop()에서 .ac(다운링크) 또는 .bc(업링크)로 이름을 변경합니다.

참고 자료(오픈소스 및 문서)

  • Dobby (인라인 후킹 프레임워크) - https://www.github.com/jmpews/Dobby
  • AndKittyInjector (Android 프로세스 인젝터) - https://github.com/MJx0/AndKittyInjector
  • AOSP
    • frameworks/av/services/audioflinger (AudioFlinger, PlaybackThread, RecordThread)
    • system/media/audio (오디오 형식, 속성, 채널 마스크)
도구 다운로드
/sdcard/voip
참고
audioserver
FunctionPurpose
AudioFlinger::setModeIN_COMMUNICATION 모드(VoIP 활성)로의 전환 및 이탈을 추적합니다.
RecordTrack::getNextBuffer마이크(업링크) 오디오 프레임을 캡처합니다.
PlaybackThread::Track::getNextBuffer스피커(다운링크) 오디오 프레임을 캡처합니다.
Track::stop다운링크 파일을 닫고 마무리합니다.
RecordTrack::stop업링크 파일을 닫고 마무리합니다.
  • RECORDTRACK_STOP_OFFSET
    • 메서드: android::AudioFlinger::RecordThread::RecordTrack::stop(void)
    • 맹글드 이름: _ZN7android12AudioFlinger12RecordThread11RecordTrack4stopEv
  • libaudioflinger.so에 PLT 후크 없음
    • 문제: 대상 함수(RecordTrack::getNextBuffer, Track::getNextBuffer 등)는 내보내지지 않으며 libaudioflinger.so에는 이에 대한 PLT/GOT 항목이 없습니다.
      • 표준 dlsym()이나 PLT 기반 후킹 메커니즘을 사용할 수 없었습니다.
    • 해결 방법: 인라인 함수 후킹을 위해 **Dobby**를 사용했습니다.
      • 후크는 다음 공식을 사용하여 런타임에 설치됩니다:
        root@kitploit:~
        target_addr = base_addr(libaudioflinger) + offset
        DobbyHook(target_addr, hook_fn, &orig_fn)