
Technische Analyse und Proof-of-Concept für CVE-2022-32932, eine Double-Fetch-Schwachstelle im ANE-Kernel-Treiber von Apple, die durch Manipulation des gemeinsam genutzten Speichers zu einem Schreibzugriff außerhalb der Grenzen führt.
CVE-2022-32932 ist eine weitere Schwachstelle, die ich im ANE-Kernel-Interface entdeckt habe; es handelt sich um ein Double-Fetch-Problem, das zu einem interessanten Out-of-Bounds-Schreibzugriff führte.
H11ANEIn::patchMutableSurface() (erreichbar über H11ANEIn::ANE_ProgramSendRequest_gated) wird aufgerufen, wenn das Modell model.hwx über eine veränderbare Prozedur und auch einen initInfo-Abschnitt verfügt. Ich suchte nach einem solchen Modell, konnte aber keines finden, also habe ich eines der vorkompilierten Modelle modifiziert und CVE-2022-32845 verwendet, um es zu laden. Bitte beachten Sie, dass CVE-2022-32845 nicht erforderlich ist, um den anfälligen Codepfad aus der Standard-App-Sandbox zu erreichen; es reicht aus, ein benutzerdefiniertes mlmodel zu kompilieren, um die gleichen Ergebnisse zu erzielen. Weitere Details zu CVE-2022-32845 finden Sie in meinen Präsentationsfolien.
ZinComputeProgramUpdateMutables() ist eine weitere Funktion, die von H11ANEIn::patchMutableSurface() aufgerufen wird, und der Funktionsprototyp sieht wie folgt aus:
ZinComputeProgramStatus __cdecl ZinComputeProgramUpdateMutables(
uint64_t procedureId,
const ZinComputeProgramInitInfo *init_info,
const ANECMutableProcedureInfo *mutable_procedure_info,
uint64_t mut_procedure_info_size,
void *MUTK_kernel_section,
uint64_t MUTK_kernel_section_size);
init_info: ist der initInfo-Abschnitt, der eine serialisierte Eingabe enthält. Die Serialisierungsfunktion finden Sie in serialize_initinfo_section() im Quellcode des weightBufs-Exploits. mutable_procedure_info: ist ein gemeinsam genutzter IOSurface-Puffer, der vom Angreifer bereitgestellt wird; er wird im weightBufs-Exploit auch als weightsBuffer bezeichnet. mut_procedure_info_size: gibt die Größe des mutable_procedure_info-Oberflächenpuffers an. MUTK_kernel_section: (oder MUTK) ist ein Mapping-Puffer eines IOSurface-Objekts, das vom Kernel während der Programm-Ladephase erstellt wird. MUTK_kernel_section_size: ist die Größe des veränderbaren Kernel-Abschnitts.

Die Schleife 88-92 berechnet die Anzahl der MutableWeight-Objekte innerhalb des mutable_procedure_info-Objekts und dann die Allokationsgröße des MutableWeight-Arrays bei 93. Danach wird das ANECMutableWeight-Array von Objekten bei 100 allokiert und dann in der Schleife 111-127 mit den entsprechenden Gewichtspuffer/Größe-Paaren durch ANECGetMutableWeight() befüllt.
ANECGetMutableOperationInfo() gibt ein Objekt opsInfo aus unserem gemeinsam genutzten Speicher zurück:
opsInfo *__fastcall ANECGetMutableOperationInfo(const ANECMutableProcedureInfo *MutableProcedureInfo, unsigned int id)
{
unsigned int weight_buffer_size; // w8
opsInfo *opInfo; // x0
weight_buffer_size = MutableProcedureInfo->header.weight_buffer_size;
if ( !weight_buffer_size )
return 0LL;
opInfo = (opsInfo *)((char *)MutableProcedureInfo + MutableProcedureInfo->wb_offsets[id]);
while ( opInfo->op_index != id )
{
if ( !--weight_buffer_size )
return 0LL;
}
return opInfo;
}
Der Pseudocode von ANECGetMutableWeight ist der folgende:
void __fastcall ANECGetMutableWeight(
const ANECMutableProcedureInfo *procedure_info,
weightInfo *a2,
ANECMutableWeight *a3)
{
uint64_t wi_size; // x9
wi_size = a2->wi_size;
a3->_weightBuf = (char *)procedure_info + a2->wi_off;
a3->_weightBufSize = wi_size;
}
Der Pseudocode von ANECGetMutableWeightInfo ist der folgende:
weightInfo *__fastcall ANECGetMutableWeightInfo(
const ANECMutableProcedureInfo *MutableProcedureInfo,
opsInfo *a2,
unsigned int a3)
{
if ( a2->op_count <= a3 )
return 0LL;
else
return (weightInfo *)((char *)MutableProcedureInfo + a2->op_offsets[a3]);
}
Das Format von ANECMutableProcedureInfo habe ich bereits in den Folien „Angriff auf Apples Neural Engine“ beschrieben; lesen Sie diese gerne, falls Sie es noch nicht getan haben. Die Strukturdefinition finden Sie im weightBufs-Exploit unter „aneProgram.h“.
Wenn Sie aufgepasst haben: ANECGetMutableOperationInfo()->op_count wird zweimal abgerufen: einmal zur Berechnung der Größe für die Allokation des ANECMutableWeight-Arrays und einmal zum Befüllen dieses Arrays.
Da der mutable_procedure_info-Puffer gemeinsam genutzter Speicher ist, könnte ein Angreifer einen separaten Thread verwenden, um den Wert von opsInfo->op_count zwischen der ersten und zweiten Nutzung zu ändern, was zu einer Größeninkonsistenz führt und einen interessanten Out-of-Bounds-Schreibzugriff in einer kalloc var Zone, dem kheap default oder der Kernel-Map verursacht.
Die Schwachstelle kann auf viele interessante Arten ausgenutzt werden. Beispielsweise könnte ein Angreifer total_count = 0x1000 setzen; in Zeile 93, dann opsInfo->count auf einen größeren Wert erhöhen, was dazu führt, dass Daten bei ANECGetMutableWeight() außerhalb der Grenzen kopiert werden.
Der Kernel wird mit einem Absturz an der unten gezeigten Anweisung enden, wenn der OOB-Schreibzugriff einen nicht zugeordneten Speicherbereich erreicht:
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 EXPORT _ANECGetMutableWeight
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 _ANECGetMutableWeight ; CODE XREF: _ZinComputeProgramUpdateMutables+270↓p
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D08 LDP X8, X9, [X1,#8]
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D0C ADD X8, X0, X8
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D10 STP X8, X9, [X2] // <---- Kernel-Absturz
com.apple.driver.AppleH11ANEInterface:__text:FFFFFE0008913D14 RET
Dieser Fehler bietet ein starkes Primitiv, da er zwei 64-Bit-Werte schreibt: eine Kerneladresse, die auf unseren gemeinsam genutzten Benutzerpuffer zeigt, und einen (halb-)arbiträren 64-Bit-Wert.
Der Proof-of-Concept bleibt als Übung für den Leser. Der weightBufs-Exploit enthält jedoch alles, was benötigt wird, um den anfälligen Codepfad zu erreichen. Viel Glück :-).