
🔬 libaudioflinger.so를 동적으로 후킹(hooking)하여 실시간 VoIP 오디오 캡처(Uplink/Downlink)를 수행하는 고급 Android 연구 도구입니다. Android 14의 WhatsApp, Signal, Telegram에서 테스트 및 구축되었습니다.
목표: 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개의 제어 버튼이 있습니다:
정책 주입
audioserver와 이 앱이 함께 작동하는 데 필요한 SELinux 정책을 주입합니다.
모니터링 시작
공유 라이브러리 페이로드를 audioserver에 주입하여 RecordTrack 및 PlaybackTrack을 후킹함으로써 VoIP 오디오 캡처를 활성화합니다. 프로세스 주입에는 **AndKittyInjector**를 사용합니다.
모니터링 중지
audioserver 프로세스를 다시 시작하여 모니터링을 중지하고 주입된 후크를 제거합니다.
데이터 복사
캡처된 원시 PCM 오디오를 임시 디렉터리 /data/local/tmp/voip에서 /sdcard/voip로 복사합니다.
로그 보기
주입, 후킹, 녹음 상태와 관련된 로그를 표시합니다.
SELinux 활성화
SELinux 강제(enforcing) 모드를 복원합니다.
SELinux 비활성화
SELinux를 허용(permissive) 모드로 설정합니다. 주입된 정책이 실패할 때 사용합니다.
오디오 재생
사용자 지정 VoIP 파일 관리자(/sdcard/voip/)를 엽니다:
데이터 삭제
/data/local/tmp/voip 및 /sdcard/voip의 모든 오디오 데이터를 삭제합니다.
참고: 데이터 삭제 후에는 데이터를 저장할 디렉터리 생성을 위해 audioserver에 다시 주입해야 합니다.
+----------------------+
| |
| App MainActivity |
| |
| |
|(9 Control Buttons UI)|
| |
| |
+----------+-----------+
|
|
|
+----------v-----------+
| |
| JNI Layer |
| |
| Selinux, Process Inje|
| ction, |
| |
| |
+----------------------+
이 공유 라이브러리는 **audioserver**에 주입되어 AUDIO_MODE_IN_COMMUNICATION을 감지하고 미리 정의된 패키지 이름 집합에 대해 Android 오디오 스택에서 직접 VoIP 오디오 스트림을 캡처합니다.
libaudioflinger.so 내부의 중요한 메서드를 가로채기 위해 Dobby 인라인 후킹 프레임워크를 사용합니다.
업링크(마이크) 및 다운링크(스피커) 오디오 스트림이 모두 캡처되어 이후 처리를 위해 세션 파일에 기록됩니다.
이 라이브러리는 AudioFlinger 및 관련 클래스 내부의 다음 함수에 후크를 설치합니다:
| Function | Purpose |
|---|---|
AudioFlinger::setMode | IN_COMMUNICATION 모드(VoIP 활성)로의 전환 및 이탈을 추적합니다. |
RecordTrack::getNextBuffer | 마이크(업링크) 오디오 프레임을 캡처합니다. |
PlaybackThread::Track::getNextBuffer | 스피커(다운링크) 오디오 프레임을 캡처합니다. |
Track::stop | 다운링크 파일을 닫고 마무리합니다. |
RecordTrack::stop | 업링크 파일을 닫고 마무리합니다. |
이 라이브러리는 UID → 패키지 매핑을 기반으로 스트림을 필터링합니다.
현재 모니터링되는 앱:
com.whatsappcom.whatsapp.w4b (WhatsApp Business)org.thoughtcrime.securesms (Signal)org.telegram.messengerorg.telegram.messenger.webaudioserver_hook.cpp 안에 다른 애플리케이션을 추가할 수도 있습니다:
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예시 세션:
/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 헤더 파일 안에서 교체할 수 있습니다.
android::AudioFlinger::setMode(audio_mode_t)_ZN7android12AudioFlinger7setModeE11audio_mode_tandroid::AudioFlinger::RecordThread::RecordTrack::getNextBuffer(android::AudioBufferProvider::Buffer *)_ZN7android12AudioFlinger12RecordThread11RecordTrack13getNextBufferEPNS_19AudioBufferProvider6BufferEandroid::AudioFlinger::PlaybackThread::Track::getNextBuffer(android::AudioBufferProvider::Buffer *)_ZN7android12AudioFlinger14PlaybackThread5Track13getNextBufferEPNS_19AudioBufferProvider6BufferEandroid::AudioFlinger::PlaybackThread::Track::stop(void)_ZN7android12AudioFlinger14PlaybackThread5Track4stopEvandroid::AudioFlinger::RecordThread::RecordTrack::stop(void)_ZN7android12AudioFlinger12RecordThread11RecordTrack4stopEv이들은 정적 분석으로 얻을 수 있습니다.
libaudioflinger.soandroid::AudioFlinger::ThreadBase::TrackBase::TrackBaseTrackBase::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)