PDA

View Full Version : [C++] Protezione libreria statica


sottovento
19-03-2015, 09:55
Ho un problema piuttosto strano: il cliente finale ha commissionato un'applicazione "a pezzi", nel senso che
- le librerie "core" ha deciso di comprarle presso la mia azienda;
- il resto dell'applicazione (HMI, ...) dall'azienda concorrente.

In realta' non e' molto strano: in azienda ci siamo sempre focalizzati nel risolvere il problema centrale (non spiego perche' irrilevante) nel migliore dei modi, mentre i concorrenti hanno sempre puntato di piu' su un'interfaccia grafica accattivante e facilita' d'uso.
Per questa applicazione dobbiamo quindi creare delle librerie statiche (.lib) usando Visual Studio e consegnarle alla concorrenza.

E' naturale quindi che ci siano un po' di paure: in primis per il riuso delle stesse in altri progetti, e poi per un eventuale reverse engineering.
Il reverse engineering preoccupa decisamente meno, ma... come evitare che le librerie vengano utilizzate piu' e piu' volte? Oltre al danno ci sarebbe la beffa!!
Non sarebbe un problema nemmeno comprare le chiavette di protezione, ma come essere sicuri che non possano essere facilmente rimosse? Ovviamente nessuna protezione e' perfetta, ma l'idea e' quella di rendere la vita di chi vuole copiare il software molto piu' difficile, in modo che non sia conveniente farlo

tomminno
19-03-2015, 12:33
Ho un problema piuttosto strano: il cliente finale ha commissionato un'applicazione "a pezzi", nel senso che
- le librerie "core" ha deciso di comprarle presso la mia azienda;
- il resto dell'applicazione (HMI, ...) dall'azienda concorrente.

In realta' non e' molto strano: in azienda ci siamo sempre focalizzati nel risolvere il problema centrale (non spiego perche' irrilevante) nel migliore dei modi, mentre i concorrenti hanno sempre puntato di piu' su un'interfaccia grafica accattivante e facilita' d'uso.
Per questa applicazione dobbiamo quindi creare delle librerie statiche (.lib) usando Visual Studio e consegnarle alla concorrenza.

E' naturale quindi che ci siano un po' di paure: in primis per il riuso delle stesse in altri progetti, e poi per un eventuale reverse engineering.
Il reverse engineering preoccupa decisamente meno, ma... come evitare che le librerie vengano utilizzate piu' e piu' volte? Oltre al danno ci sarebbe la beffa!!
Non sarebbe un problema nemmeno comprare le chiavette di protezione, ma come essere sicuri che non possano essere facilmente rimosse? Ovviamente nessuna protezione e' perfetta, ma l'idea e' quella di rendere la vita di chi vuole copiare il software molto piu' difficile, in modo che non sia conveniente farlo

Alcune ipotesi (ovviamente non conoscendo esattamente il contesto sono molto generiche):
Rendere le funzioni della vostra libreria come un "servizio" separato dall'applicazione
Usare una dll
Abilitare l'esecuzione solo su hardware "noto"
Applicare un metodo "phone home": la libreria non funziona se non ottiene un codice di sblocco da un server remoto.

A prescindere, offuscare una libreria è veramente un casino.
Essere nella condizione per cui loro hanno in mano il vostro lavoro e voi non avete niente del loro è certamente un problema di non poco conto.

sottovento
19-03-2015, 16:37
Alcune ipotesi (ovviamente non conoscendo esattamente il contesto sono molto generiche):

Hai ragione; tuttavia la nostra libreria fa solo un mucchio di conti: prende degli input numerici e restituisce degli output. In teoria puo' girare su qualsiasi computer.


Rendere le funzioni della vostra libreria come un "servizio" separato dall'applicazione
Usare una dll

un servizio o una dll sono piu' facili da proteggere? Scusa la domanda, non sono esperto di protezioni dalla copiatura.


Abilitare l'esecuzione solo su hardware "noto"
Applicare un metodo "phone home": la libreria non funziona se non ottiene un codice di sblocco da un server remoto.

Mi sto orientando su quest'ultimo metodo: phone home. Il codice di sblocco potra' essere generato utilizzando anche il mac address.
Inoltre, pensavo di fare una cosa leggermente piu' sofisticata: il software contenuto nella libreria ha bisogno di un set di parametri per funzionare correttamente. Avrei intenzione di generare il "codice di sblocco" in maniera criptata, che contenga sia un codice di sicurezza sia i parametri (costanti) per quella determinata applicazione.

Motivo: se metto solo un codice ed ogni tanto verifico che il file-chiave sia sul file system, potrei facilmente aprire un monitor/deassembler e scrivere delle NOP nel punto in cui vedo che il software va a controllare che il codice sia giusto. E' un po' macchinoso ma si puo' fare.
Se pero' il file-chiave contiene anche le costanti che servono a funzionare, mettere delle NOP fara' andare in crash l'applicazione o comunque la fara' malfunzionare.
Cosa ne pensi? In linea di principio, come potrei implementare la cosa? Ovviamente i dati dovranno essere criptati ma decodificabili dalla mia libreria...



A prescindere, offuscare una libreria è veramente un casino.
Essere nella condizione per cui loro hanno in mano il vostro lavoro e voi non avete niente del loro è certamente un problema di non poco conto.
Purtroppo hai pienamente ragione. L'idea e' di rendere la vita difficile cosi' che non valga la pena tentare il riutilizzo

les2
19-03-2015, 17:09
ciao,
non so che servizio core voi dobbiate dare ma ti chiedo subito se siete costretti a farlo in locale oppure potenzialmente anche in remoto (via rete, internet, intranet etcc...) come webservice ?

perchè io spesso lavoro quasi al contrario, c'è un fornitore che non ha sviluppato le interfacce grafiche e creiamo il software basandoci sulle sue librerie, dopo averle importate/decriptate, riscritte, migliorate etc...
insomma, avevamo la pappa pronta all'inizio ;)


se non potete farlo web anche in locale è possibile avere un servizio attivo su una porta o qualcosa del genere?
la licenza con il solo ip o mac address non basta, perchè è sufficiente cambiarlo e settarlo uguale alla licenza ;)

sottovento
19-03-2015, 17:29
ciao,
non so che servizio core voi dobbiate dare ma ti chiedo subito se siete costretti a farlo in locale oppure potenzialmente anche in remoto (via rete, internet, intranet etcc...) come webservice ?

perchè io spesso lavoro quasi al contrario, c'è un fornitore che non ha sviluppato le interfacce grafiche e creiamo il software basandoci sulle sue librerie, dopo averle importate/decriptate, riscritte, migliorate etc...
insomma, avevamo la pappa pronta all'inizio ;)


se non potete farlo web anche in locale è possibile avere un servizio attivo su una porta o qualcosa del genere?
la licenza con il solo ip o mac address non basta, perchè è sufficiente cambiarlo e settarlo uguale alla licenza ;)

Grazie per la dritta. Si tratta di una serie di calcoli per il setpoint di una macchina ad alta produttivita': dati una serie di ingressi (caratteristiche del prodotto che si vuole ottenere, composizione chimica, tolleranze, ecc) ed una serie di parametri fissi (caratteristiche dell'impianto, motori, distanze fra le stazioni di lavoro, ecc), produce in uscita una serie di output (velocita' dei motori, potenza impiegata, corrente utilizzata, forze necessarie per la lavorazione, usura stimata delle parti in movimento, ecc) per ottenere il prodotto desiderato con la qualita' impostata, ottimizzando l'uso di energia e materie prime.

Fortunatamente ci sono dei parametri fissi, che dipendono dal layout dell'impianto e che non varieranno mai nei prossimi 20 anni, o quasi. Per questo stavo pensando alla soluzione di cui sopra.
Per motivi di sicurezza, ovviamente, i computer non sono collegati ad internet.

Certo e' che il tuo post mi ha un po' spaventato.... qualche consiglio?

cdimauro
19-03-2015, 19:44
L'ideale, come ti è stato già suggerito, sarebbe utilizzare un server remoto, così si risolverebbe a monte ogni problema. Tra l'altro mi pare di aver capito che i parametri di input e l'output non siano tantissimi; insomma non c'è una mole di dati da trasferire avanti e indietro.

Però se non c'è connessione a internet... amen!

Se i calcoli da fare non sono molti, si potrebbe pensare a una chiavetta USB dotata di un processore che esegua effettivamente i calcoli, tenendo ben chiuso il codice (il firmware dei SoC embedded in genere si può proteggere dalla lettura esterna). Per cui a questo punto si potrebbe fornire una libreria/dll/so che faccia semplicemente da proxy con la chiavetta USB.

Infine, riguardo all'uso di un file criptato, a questo punto anziché patchare determinati punti con le costanti appropriate, si potrebbe fornire la libreria interamente criptata col mac address E il seriale dell'hard disk (che è più difficile da contraffare), e che viene decriptata al volo soltanto in memoria tramite un'apposita API esposta dalla libreria stessa. In buona sostanza, tutto il codice della libreria è criptato con la chiave MAC+HD, fatta eccezione per la piccola porzione relativa all'API che "sblocca" la libreria. Quest'API si occupa di usare la chiave per decriptare il codice (calcolando anche un checksum per segnalare qualche problema, evitando di far eseguire codice casuale), ed eseguendo il flush della cache codice prima di restituire il controllo al chiamante.

Se i calcoli da eseguire non sono pesanti, se vuoi far impazzire un eventuale reverse engineer potresti anche implementare una piccola macchina virtuale / emulatore di un processore con architettura custom che ti crei apposta allo scopo. Sarà la VM a eseguire il codice vero e proprio. Magari con gli opcode criptati (MAC+HD) e che decodifichi al volo prima di eseguire il codice che implementa il particolare opcode.

sottovento
20-03-2015, 09:00
L'ideale, come ti è stato già suggerito, sarebbe utilizzare un server remoto, così si risolverebbe a monte ogni problema. Tra l'altro mi pare di aver capito che i parametri di input e l'output non siano tantissimi; insomma non c'è una mole di dati da trasferire avanti e indietro.

Però se non c'è connessione a internet... amen!

Purtroppo non c'e'. Ma si puo' sempre ovviare al problema: inizialmente il software non funziona ma viene fornito un programma che genera un file di partenza (contentente mac+hd id+....). E questo file viene spedito. Pensavo di fare cosi'.



Se i calcoli da fare non sono molti, si potrebbe pensare a una chiavetta USB dotata di un processore che esegua effettivamente i calcoli, tenendo ben chiuso il codice (il firmware dei SoC embedded in genere si può proteggere dalla lettura esterna). Per cui a questo punto si potrebbe fornire una libreria/dll/so che faccia semplicemente da proxy con la chiavetta USB.

I calcoli da fare sono molti, ma l'idea e' comunque buona. Stavo proprio pensando a questo. Magari fare una parte dei conti sul processore embedded e parte sul pc....



Infine, riguardo all'uso di un file criptato, a questo punto anziché patchare determinati punti con le costanti appropriate, si potrebbe fornire la libreria interamente criptata col mac address E il seriale dell'hard disk (che è più difficile da contraffare), e che viene decriptata al volo soltanto in memoria tramite un'apposita API esposta dalla libreria stessa. In buona sostanza, tutto il codice della libreria è criptato con la chiave MAC+HD, fatta eccezione per la piccola porzione relativa all'API che "sblocca" la libreria. Quest'API si occupa di usare la chiave per decriptare il codice (calcolando anche un checksum per segnalare qualche problema, evitando di far eseguire codice casuale), ed eseguendo il flush della cache codice prima di restituire il controllo al chiamante.

Se i calcoli da eseguire non sono pesanti, se vuoi far impazzire un eventuale reverse engineer potresti anche implementare una piccola macchina virtuale / emulatore di un processore con architettura custom che ti crei apposta allo scopo. Sarà la VM a eseguire il codice vero e proprio. Magari con gli opcode criptati (MAC+HD) e che decodifichi al volo prima di eseguire il codice che implementa il particolare opcode.
Buona idea, ma non sono esperto di queste cose. Dovrei leggere un sacco di roba e raggiungere un minimo livello di expertise prima di fare un'operazione del genere.

Grazie mille, Cesare

cdimauro
20-03-2015, 19:37
Di nulla. Se dovesse interessarti l'ultima soluzione, ne potremmo discutere, visto che è un pallino che coltivo da tempo.

Comunque la soluzione più papabile al momento è rappresentata dalla chiavetta USB. Oggi sono a disposizioni processori embedded abbastanza potenti, per cui è probabile che possano gestire in scioltezza tutti i calcoli, senza delegare alcunché al PC.

les2
22-03-2015, 16:24
quella della chiavetta dongle non è male :)
io non conosco assolutamente, anche perchè usiamo tecnologie differenti e questo forse un po' dovrebbe rincuorarti:
io lavoro in un mondo dove i linguaggi sono web e basi dati
(e sono tutti decriptabili con più o meno lavoro :( )


puoi anche farla al contrario...
ovvero usi sì un dogle che genera un codice univoco o simili e il tuo software funziona solo in presenza di dongle ;)
(è potenzialmente copiabile e cracckabile, vedi i programmi audio con i relativi dongle emulator, ma forse è più facile da implementare)

buona fortuna e aggiornaci :)

sottovento
23-03-2015, 08:25
Di nulla. Se dovesse interessarti l'ultima soluzione, ne potremmo discutere, visto che è un pallino che coltivo da tempo.

Sono combattuto. E' interessante ma non ho tempo da dedicarci, visto che in questo periodo sto portando avanti piu' progetti.
Vorrei proseguire il discorso, ma so che poi rimarrebbe sulla lista delle cose da fare.

Magari potrei semplicemente chiederti: hai un'idea di quanto tempo potrebbe essere necessario, per implementare una soluzione simile (occhio e croce, ovviamente)?

grazie ancora

cdimauro
23-03-2015, 22:16
Dipende tutto dal tipo di macchina virtuale che vuoi realizzare, e da come dev'essere generato il codice che deve girarci sopra.

Se si tratta di un'ISA RISC ed è abbastanza semplice, in un giorno / giorno e mezzo riesci tirare fuori i dettagli dell'architettura, definire con precisione la opcode table, e scriverti un piccolo assemblatore e un disassemblatore (questi due in Python). Provato personalmente, per gioco, tempo fa.

Per realizzare un emulatore a naso direi che in un paio di giorni te ne esci fuori (sostanzialmente si parte dal codice del disassemblatore), sempre in Python. Ma una volta che il modello funziona, portarlo in C richiederà un'altra giornata di lavoro al massimo.

Il problema più grosso è come generare il codice da farci girare sopra. Se non è tanto, si può pensare di scriverlo in assembly e darlo in pasto all'assemblatore di cui sopra. Con un'architettura semplice è decisamente fattibile. Altrimenti bisogna passare da progetti come GCC (ma so che è un casino) o CLang/LLVM (decisamente più semplice, da quel che ho visto tempo fa). Però in questo caso non saprei quantificarti lo sforzo necessario, non avendo mai provato.

sottovento
24-03-2015, 08:47
Dipende tutto dal tipo di macchina virtuale che vuoi realizzare, e da come dev'essere generato il codice che deve girarci sopra.

Se si tratta di un'ISA RISC ed è abbastanza semplice, in un giorno / giorno e mezzo riesci tirare fuori i dettagli dell'architettura, definire con precisione la opcode table, e scriverti un piccolo assemblatore e un disassemblatore (questi due in Python). Provato personalmente, per gioco, tempo fa.

Per realizzare un emulatore a naso direi che in un paio di giorni te ne esci fuori (sostanzialmente si parte dal codice del disassemblatore), sempre in Python. Ma una volta che il modello funziona, portarlo in C richiederà un'altra giornata di lavoro al massimo.

Il problema più grosso è come generare il codice da farci girare sopra. Se non è tanto, si può pensare di scriverlo in assembly e darlo in pasto all'assemblatore di cui sopra. Con un'architettura semplice è decisamente fattibile. Altrimenti bisogna passare da progetti come GCC (ma so che è un casino) o CLang/LLVM (decisamente più semplice, da quel che ho visto tempo fa). Però in questo caso non saprei quantificarti lo sforzo necessario, non avendo mai provato.
Il codice purtroppo e' tanto, tutto sviluppato in C++ utilizzando Visual C come IDE. Oltretutto ne conosco solo una parte poiche' e' stato sviluppato in collaborazione con diversi uffici. Per complicare le cose, alcune parti che ho potuto visionare non hanno una grande qualita' (dal punto di vista informatico) poiche' sono stati sviluppate da tecnologi, i quali conoscono benissimo il processo produttivo ma sono scarsi in programmazione.
Queste persone hanno passato anni a scrivere modelli matematici in Fortran, ed ora sono stati obbligati a passare al C++. Per loro e' importante che i calcoli siano giusti (fortunatamente lo sono), nient'altro. Inoltre, alcune parti sono restate in Fortran, e vengono compilate con un compilatore prodotto dalla tua azienda ;)

Credo che il lavoro sia davvero troppo. Comunque ci pensero' se mettermi ad affrontarlo, anche se non credo.... oltretutto il mese prossimo dovro' traslocare (sono stato assegnato ad un altro dipartimento a 150 Km da qui) e non avro' troppo tempo libero. Grazie comunque!!!!!!

cdimauro
24-03-2015, 18:38
Di nulla, e buon trasloco. :)

A questo punto direi che la soluzione migliore sarebbe realizzare la libreria ad hoc che espone l'API pubblica di "open", che si occupa di decriptare al volo il codice di tutte le altre API (fornendo una chiave basata su MAC+HD), come avevo suggerito prima. Così il grosso del codice non viene toccato di una virgola.

P.S. Strano che abbiano obbligato a passare da Fortran a C++. Fortran rimane ancora il linguaggio d'elezione per applicazioni di number-crunching, con compilatori che tante volte generano codice migliore di quello C++. Inoltre si può esportare codice Fortran per essere "consumato" da applicazioni scritte in altri linguaggi.