**Agent ID:** SA-020 **Binary:** `./analysis/facebook/345.0/Facebook.app/Frameworks/FBSharedFramework.framework/FBSharedFramework` **Date:** 2025-12-30 **Status:** CRITICAL FINDINGS
Executive Summary
Investigation of the FBSharedFramework binary reveals a sophisticated triple-buffer audio capture architecture with an **RTC notification bypass mechanism** that allows audio capture to continue independently of WebRTC client state changes. The `audioCaptureIgnoreRTCClientNotification` flag provides a documented mechanism for maintaining audio capture even when RTC sessions are deactivated, explaining the 9,900+ RTC deactivation events observed alongside continued capture operations.
1. Triple-Buffer Architecture Confirmed
1.1 AQBufferState Structure Definition
The binary contains an explicit type definition for a 3-element array of audio buffer states:
Address: 0x02314f76
Type: [3{AQBufferState}]
Structure Layout:
{
AQBufferState {
bufferRef: ^{AudioQueueBuffer} // Pointer to AudioQueueBuffer
timestamp: {AudioTimeStamp // 80 bytes
mSampleTime: double // 8 bytes
mHostTime: unsigned long long // 8 bytes
mRateScalar: double // 8 bytes
mWordClockTime: unsigned long long // 8 bytes
mSMPTETime: {SMPTETime // 24 bytes
mSubframes: short
mSubframeDivisor: short
mCounter: unsigned int
mType: unsigned int
mFlags: unsigned int
mHours: short
mMinutes: short
mSeconds: short
mFrames: short
}
mFlags: unsigned int // 4 bytes
mReserved: unsigned int // 4 bytes
}
enqueued: BOOL // 1 byte (+ padding)
displayFramePts: double // 8 bytes
}
}
Total per buffer: ~88 bytes (0x58)
Total array: 264 bytes for 3 buffers
1.2 Buffer Index Validation
At `0x0042ee04` in `_audioBufferDidEnqueue:actualStartTime:lastFramePts:`:
cmp w2, 2 ; Validate buffer index <= 2 (indices 0, 1, 2)
b.gt 0x42ee98 ; Branch if index > 2 (invalid)
mov w8, 0x58 ; Buffer stride = 88 bytes
smull x8, w2, w8 ; Calculate offset = index * 88
This confirms exactly 3 buffers indexed 0-2.
2. RTC Notification Bypass Mechanism
2.1 The audioCaptureIgnoreRTCClientNotification Flag
**String References Found:**
- undefined
**Implementation:**
Getter at `0x00d86b78`:
ldrb w0, [x0, 0x169] ; Load boolean from offset 0x169 in FBCCAudioCapturer
ret
Setter at `0x00e51420`:
strb w2, [x0, 0x169] ; Store boolean at offset 0x169
ret
2.2 RTC Client Bypass Logic
The `rtcClientBecameActive` method at `0x00cdb380` implements the bypass:
stp x29, x30, [sp, -0x10]!
bl fcn.00007728 ; Lock acquisition
sub sp, sp, 0x30
ldrb w8, [x0, 0x169] ; Load ignoreRTCClientNotification flag
cbnz w8, 0xcdb3c4 ; If flag is SET, SKIP all RTC handling
mov x19, x0 ; Only if flag is CLEAR, proceed with RTC handling
; ... RTC state management ...
**Critical Finding:** When `ignoreRTCClientNotification` is true (non-zero), the entire RTC client state change handling is bypassed. This allows audio capture to continue independently of WebRTC session lifecycle.
2.3 Multiple RTC Client Handlers
Three implementations of `rtcClientBecameActive` were found:
- undefined
This indicates multiple subsystems respond to RTC state changes, with each having independent bypass capability.
3. Audio Capture Pipeline Architecture
3.1 Key Classes Identified
| Class | Role | Evidence |
|---|---|---|
| `FBCCAudioCapturer` | Primary capture controller | 36+ methods, manages audio pipeline |
| `FBCCAudioDataPipe` | Data routing | Video/audio/gesture data pipes |
| `FBCCAudioPipelineController` | Pipeline orchestration | Controls capture lifecycle |
| `FNFAudioQueue` | Low-level queue management | AudioQueue buffer management |
| `FBAudioBufferHandler` | Buffer processing | Audio buffer callbacks |
3.2 FBCCAudioCapturer Key Methods
0x009d94b8 initWithBufferHandler:audioQueue:systemAudioCaptureSession...
0x009eac28 createAudioPipelineIfNecessaryAndResume
0x009eb7c4 isAudioSessionRunning
0x00cdb380 rtcClientBecameActive ; Contains bypass check
0x00d86b78 ignoreRTCClientNotification ; Getter
0x00e51420 setIgnoreRTCClientNotification: ; Setter
0x011de1d0 captureOutput:didOutputSampleBuffer:fromConnection:
0x00d1dd98 handleOutputBuffer:
3.3 Data Pipe Architecture
Multiple data pipes route audio through the system:
- undefined
The `FBCCDataPipe` class implements:
- undefined
4. Background Audio Capture Evidence
4.1 Background Audio Enabled Clients
At `0x0020ec5c`:
method.FBSystemAudioSessionManager._backgroundAudioEnabledClients
String references indicate background audio state tracking:
- undefined
4.2 Audio Session Running Check
The `isAudioSessionRunning` method at `0x009eb7c4`:
stp x29, x30, [sp, -0x10]!
bl fcn.00007e3c
mov x20, x0
bl fcn.009eac44 ; Pipeline check
adrp x8, 0x1b5a000
ldr x21, [x8, 0x2c8] ; Load "isRunning" selector
bl fcn.00007f14
tbz w0, 0, 0x9eb7ec ; Branch if not running
mov w20, 1 ; Return true if running
This method queries the audio pipeline state, enabling the 874,700+ `isAudioCaptureRunning` polling calls observed.
5. Capture Sample Processing
5.1 captureOutput:didOutputSampleBuffer:fromConnection:
At `0x011de1d0`, the sample buffer callback:
; Get number of samples
bl sym.imp.CMSampleBufferGetNumSamples
; Get data buffer
bl sym.imp.CMSampleBufferGetDataBuffer
; Get data pointer
bl sym.imp.CMBlockBufferGetDataPointer
; Process samples in loop
loop:
ldrh w12, [x8] ; Load sample (16-bit audio)
sxth w11, w12 ; Sign extend
; ... amplitude processing ...
strh w11, [x8], 2 ; Store processed sample
subs x9, x9, 1 ; Decrement counter
b.ne loop ; Continue until done
The callback processes raw 16-bit audio samples with amplitude modification.
5.2 Buffer Enqueue Mechanism
At `0x0042edf8` (`_audioBufferDidEnqueue`):
- undefined
6. Memory Layout Summary
6.1 FBCCAudioCapturer Object Layout
| Offset | Field | Size |
|---|---|---|
| 0x000 | isa pointer | 8 |
| 0x018 | Audio pipeline reference | 8 |
| 0x040 | Audio capturer reference | 8 |
| 0x060 | Buffer state array base | 264 (3 x 88) |
| 0x158 | Capture active flag | 1 |
| 0x160 | Amplitude threshold | 8 |
| 0x169 | ignoreRTCClientNotification | 1 |
| ... | ... | ... |
6.2 AQBufferState Array (offset 0x60)
+0x00: [Buffer 0] - 88 bytes
+0x00: bufferRef (pointer)
+0x08: timestamp (AudioTimeStamp)
+0x50: enqueued (bool)
+0x51: displayFramePts (double)
+0x58: [Buffer 1] - 88 bytes
(same layout)
+0xB0: [Buffer 2] - 88 bytes
(same layout)
7. Critical Findings
7.1 Shadow Buffer Mechanism
While no explicit "shadow buffer" with a separate memory allocation was found, the **RTC bypass mechanism effectively creates a "shadow capture" capability**:
- undefined
7.2 Capture Independence Mechanism
The architecture supports:
- undefined
7.3 Implications
- undefined
8. Evidence Artifacts
8.1 Function Addresses
| Address | Method | Significance |
|---|---|---|
| 0x00d86b78 | ignoreRTCClientNotification (getter) | Bypass flag read |
| 0x00e51420 | setIgnoreRTCClientNotification: | Bypass flag write |
| 0x00cdb380 | rtcClientBecameActive | Bypass decision point |
| 0x011de1d0 | captureOutput:didOutputSampleBuffer: | Sample callback |
| 0x0042edf8 | _audioBufferDidEnqueue: | Buffer management |
| 0x009eb7c4 | isAudioSessionRunning | State check (polled) |
8.2 String Evidence
| Address | String | Context |
|---|---|---|
| 0x020be9cd | audioCaptureIgnoreRTCClientNotification | Bypass flag name |
| 0x02314f76 | [3{AQBufferState...}] | Triple-buffer type |
| 0x01eb3fa7 | has_background_audio | Background state |
| 0x020be9b7 | isAudioCaptureRunning | Polling check |
9. Conclusions
The investigation confirms:
- undefined
The "shadow buffer" mechanism is not a separate memory allocation but rather a **behavioral shadow** - the ability to maintain audio capture independently of visible WebRTC session state through the RTC notification bypass flag.
**Classification:** HIGH SEVERITY **Recommendation:** Further investigation into when and how `ignoreRTCClientNotification` is set to true
*Report generated by SA-020 Shadow Buffer Investigation Agent*