Skip to Content
Nuova versione 12 disponibile 🎉
ObfuscatorRidenominazione dei simboliRidenominazione cross-assembly

Ridenominazione cross-assembly

Durante il processo di offuscamento, Babel Obfuscator rinomina tutti i simboli che non sono visibili all’esterno dell’assembly, cioè i simboli privati e interni. Babel cambia quindi i nomi di campi, metodi, classi e altri elementi del codice a cui non si deve accedere dall’esterno dell’assembly.

Babel non rinomina i simboli visibili all’esterno dell’assembly, come i simboli pubblici. I simboli pubblici sono infatti destinati a essere usati da altri assembly, e rinominarli comprometterebbe il funzionamento dell’applicazione. Babel rinomina quindi solo i simboli a cui gli altri assembly non devono accedere, così l’applicazione continua a funzionare come previsto.

Babel permette tuttavia di offuscare i membri sia pubblici sia interni tra più assembly. Per farlo corregge, tramite i file map XML, i nomi dei simboli offuscati referenziati in ciascun assembly.

Quando un assembly viene offuscato, infatti, i nomi dei suoi simboli cambiano. Ogni riferimento a questi simboli da parte di un altro assembly va quindi aggiornato con i nuovi nomi. Se specifichi i file map XML di input e di output, Babel Obfuscator li usa per correggere i riferimenti incrociati ai nomi tra tutti gli assembly coinvolti. In questo modo il codice offuscato funziona correttamente e non si rompe a causa di nomi di simboli errati.

È importante mantenere privati i file map e non distribuirli in nessun caso con l’applicazione offuscata, perché possono essere usati per risalire all’offuscamento e compromettere la sicurezza dell’applicazione.

Configurare la ridenominazione cross-assembly

Per configurare la ridenominazione cross-assembly devi considerare tutti gli assembly che partecipano al processo di ridenominazione. Prendi l’assembly principale dell’applicazione, MainAssembly.dll, che usa l’interfaccia pubblica di due componenti esterni: Library1.dll e Library2.dll. Anche Library1.dll deve accedere all’interfaccia pubblica di Library2.dll, secondo lo schema seguente:

  • MainAssembly.dll
    1. Library1.dll
    2. Library2.dll
  • Library1.dll
    1. Library2.dll

Questa configurazione mette in evidenza le relazioni tra gli assembly coinvolti nel processo di offuscamento. Il primo passo è configurare Babel perché offuschi i simboli pubblici di Library1.dll e Library2.dll. Puoi farlo aggiungendo al codice sorgente di entrambe le librerie il seguente attributo personalizzato a livello di assembly:

[assembly: System.Reflection.ObfuscateAssembly(true)]

Questo attributo indica a Babel di offuscare i simboli pubblici dell’assembly specificato senza bisogno di file di regole XML esterni. Impostando il parametro Boolean su true, l’interfaccia pubblica dell’assembly viene trattata come privata e i nomi dei membri pubblici possono essere offuscati in sicurezza.

In alternativa, puoi configurare Babel perché rinomini l’interfaccia pubblica di un assembly con un file di regole XML. Questo metodo offre maggiore flessibilità e controllo, perché ti permette di offuscare in modo selettivo parti dell’interfaccia pubblica. Di seguito trovi un esempio di file di regole XML, chiamato public.xml, che forza l’offuscamento dei nomi di tutti i membri pubblici:

<Rules> <Rule name="obfuscate public" exclude="false"> <Access>Public</Access> <Pattern isRegEx="false">*</Pattern> <Description>Obfuscate all public symbols.</Description> </Rule> </Rules>

Rispetto all’attributo ObfuscateAssembly, le regole XML offrono un controllo più granulare su quali simboli pubblici offuscare. Con l’espressione dell’elemento Pattern puoi specificare quali parti dell’interfaccia pubblica devono essere offuscate, e definire così strategie di offuscamento su misura.

A questo punto Library1.dll e Library2.dll sono configurati per usare l’attributo ObfuscateAssembly oppure il file di regole XML (in questo caso, public.xml):

  • MainAssembly.dll
  • Library1.dll (configurato con public.xml)
  • Library2.dll (configurato con public.xml)

Per ogni assembly configurato per rinominare la propria interfaccia pubblica, devi abilitare la generazione di un file map XML.

Questo file contiene la corrispondenza tra i nomi originali dei simboli e quelli offuscati. Il file map XML viene usato da tutti gli assembly che partecipano al processo di offuscamento e che referenziano almeno un assembly con l’interfaccia pubblica rinominata. Così i nomi vengono risolti correttamente tra gli assembly offuscati.

Per offuscare Library1.dll e Library2.dll, usa la seguente sintassi della CLI:

babel Library2.dll --rules public.xml --mapout

Questo primo comando offusca Library2.dll e genera un file map XML chiamato Library2.map.xml, che contiene la corrispondenza tra i nomi originali dei simboli e i nomi offuscati.

Poiché Library1.dll referenzia Library2.dll e ne usa l’interfaccia pubblica, quando offuschi Library1.dll devi fornire in input il file Library2.map.xml, così i simboli offuscati di Library2.dll vengono mappati correttamente. Inoltre, dato che vuoi offuscare l’interfaccia pubblica di Library1.dll, configura Babel perché carichi il file di regole public.xml e generi il file map XML corrispondente per Library1.dll.

Il comando della CLI per questo passo è il seguente:

babel Library1.dll --rules public.xml --mapout --mapin Library2.map.xml

In questo modo Library1.dll referenzia correttamente i simboli offuscati di Library2.dll e genera a sua volta il proprio file map, da usare nel seguito del processo di offuscamento.

Infine, per offuscare MainAssembly.dll, devi configurare Babel perché carichi i file map XML sia di Library1.dll sia di Library2.dll, dato che MainAssembly referenzia entrambi gli assembly. Così MainAssembly può risolvere correttamente, durante il processo di offuscamento, i simboli offuscati delle librerie da cui dipende.

Il comando della CLI per questo passo è:

babel MainAssembly.dll --mapin Library1.map.xml --mapin Library2.map.xml

Questo comando riceve in input i file map generati in precedenza (Library1.map.xml e Library2.map.xml), in modo che i riferimenti ai simboli offuscati di queste librerie siano gestiti correttamente in MainAssembly.

È fondamentale offuscare gli assembly nell’ordine corretto. Le librerie referenziate da altri assembly, come Library2.dll e Library1.dll, vanno offuscate per prime, per generare i file map necessari. Poi gli assembly che ne dipendono, come Library1.dll e MainAssembly.dll, possono essere offuscati usando i file map.

Configurare dal task MSBuild

Per configurare la ridenominazione cross-assembly con MSBuild, devi specificare i file map XML di input e di output per ogni assembly coinvolto nel progetto di offuscamento, oltre al file di regole XML. Ogni assembly offuscato deve generare un file map XML, che viene poi fornito in input a tutti gli altri assembly offuscati che referenziano questo assembly target.

Ecco un esempio di come configurare la ridenominazione cross-assembly tra un assembly principale e due assembly referenziati, disposti secondo lo schema seguente.

  • MainAssembly.dll
    1. Library1.dll
    2. Library2.dll
  • Library1.dll
    1. Library2.dll

Comincia dal progetto Library2, che non ha dipendenze. Poiché non dipende da altri assembly, può essere offuscato in modo indipendente, senza file map XML di input.

Progetto dell’assembly Library2

<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <GenerateMapOutFile>true</GenerateMapOutFile> </PropertyGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <RulesFile Include="path\to\referenced\public.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" RulesFiles="@(RulesFile)" GenerateMapOutFile="$(GenerateMapOutFile)" /> </Target> </Project>

Nota che, poiché Library1 referenzia Library2, il progetto di offuscamento, oltre a generare il file map XML con GenerateMapOutFile=true, deve anche fare riferimento al file map generato per Library2.

Progetto dell’assembly Library1

<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <Reference Include="path\to\referenced\Library2.dll" /> </ItemGroup> <PropertyGroup> <GenerateMapOutFile>true</GenerateMapOutFile> </PropertyGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <MapInFile Include="path\to\referenced\Library2.dll.map.xml" /> </ItemGroup> <ItemGroup> <RulesFile Include="path\to\referenced\public.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" MapInFiles="@(MapInFile)" RulesFiles="@(RulesFile)" GenerateMapOutFile="$(GenerateMapOutFile)" /> </Target> </Project>

Poiché il progetto MainAssembly referenzia le due librerie, Library1 e Library2, la cui interfaccia pubblica è stata offuscata, il task Babel va configurato perché carichi i due file map XML generati per le librerie.

Progetto dell’assembly principale

<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <Reference Include="path\to\referenced\Library1.dll" /> <Reference Include="path\to\referenced\Library2.dll" /> </ItemGroup> <Target Name="Obfuscate" AfterTargets="CoreCompile"> <ItemGroup> <MapInFile Include="path\to\referenced\Library1.dll.map.xml" /> <MapInFile Include="path\to\referenced\Library2.dll.map.xml" /> </ItemGroup> <Babel Input="$(TargetPath)" MapInFiles="@(MapInFile)" /> </Target> </Project>

In questo modo i riferimenti incrociati tra Library1 e Library2 vengono gestiti correttamente durante il processo di offuscamento. Senza il riferimento al file map XML generato per Library2, l’offuscamento di Library1 potrebbe non gestire correttamente i riferimenti incrociati tra le due librerie, con possibili problemi in fase di esecuzione. Quando configuri la ridenominazione cross-assembly è quindi essenziale che tutti i file map XML necessari siano generati e referenziati correttamente.

Configurare da Babel Desktop

Un progetto di Babel Desktop può contenere tutti gli assembly coinvolti. Sul canvas del progetto, collega ogni libreria all’assembly che la usa e scegli Passa il file di map: la libreria scrive così il proprio file map, l’assembly che la usa lo legge e la libreria viene offuscata per prima. Nell’esempio precedente, collega Library2 a Library1 e a MainAssembly, e Library1 a MainAssembly. Un collegamento con Solo ordine di esecuzione imposta l’ordine ma non passa alcun file map.

Devi comunque aggiungere a ogni libreria le regole di ridenominazione pubblica, con le regole XML o con RulesFiles. Il gruppo File map delle proprietà del target mostra le mappe che ogni target scrive e legge, e ti permette di aggiungere file map di build precedenti. Vedi Ordine di esecuzione e file map.

Last updated on