Reversing e cracking di una applicazione java
(2 lezione)

Data

by "epokh"

�

22/10/2004

UIC's Home Page

Published by Quequero

Wong Long il fondatore dello stile Tang Lang disse:

Grazie epokh questi tute torneranno davvero utili!

"Il fine di una tazza è nel suo essere vuota"

....

E-mail: [email protected]

....

Difficolt�

( )NewBies (X)Intermedio ( )Avanzato ( )Master

�
�

Introduzione

Questa è la seconda lezione sul Java Reversing. Questa lezione è collegata con la precedente per evitare di ripetere alcune procedure perciò se non lo avete già fatto leggetevi la prima.

Tools usati

 
Dj java decompiler 3.7
j2sdk
 

URL o FTP del programma

 
crack me
cracked me
 

Notizie sul programma

Il programma è una applicazione java tipo crack me che per essere registrata richiede un seriale.

Essay

 

Ho deciso di scrivere questo nuovo tutorial quando mi sono imbattuto in alcune protezioni "strane" che ho trovato in alcune applicazioni Java. Java infatti sfrutta le possibilità offerte dalla programmazione ad oggetti per nascondere le funzioni di controllo per la registrazione.

In questa lezione esporremo il concetto di base di questa protezione tramite un semplice programma, in modo da chiarire l'approccio che si deve usare in questi frangenti.

L'applicazione è distribuita in un file jar come l'altra volta: lanciamo il programma, java -jar crack_me.jar e proviamo a registrarci.La routine di controllo del seriale è cambiata quindi bisogna reversare il programma. Listiamo il contenuto del file jar con jar tf crack_me.jar, i file sono:

Come possiamo notare ci sono due nuove classi ControlloF e ControlloP, il cui nome è abbastanza eloquente, ricordiamo però che in una applicazione vera i nomi possono essere meno sospettosi tipo ImageHandler e FigureHandler in modo da disorientare il reverser.

Estraiamo il contenuto del file jar con WinZip nella cartella crack_me ed apriamo il manifesto nella cartella META-INF. Il manifesto è il seguente:

Manifest-Version: 1.0
Main-Class: crack_me.Applicazione
Decompiliamo la classe Applicazione nella cartella crack_me, per scoprire che instanzia un oggetto di tipo Main che eredita da JFrame, la classe che manipola le finestre di Windows

 
package crack_me;

import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.UIManager;

// Referenced classes of package crack_me:
// Main

public Applicazione() <-costruttore di Applicazione
{
....
Main frame = new Main(); <- costruisce un oggetto di tipo Main
....
}

public static void main(String args[])
{
....
new Applicazione();<- costruisce se stessa
}

Decompiliamo allora anche Main.class
Decompiliamo allora anche Main.class :
 
 
package crack_me;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import javax.swing.*;

// Referenced classes of package crack_me:
// Main_jMenuFileExit_ActionAdapter, Main_jMenuHelpAbout_ActionAdapter, Main_jMenuRegister_actionAdapter, Main_AboutBox,
// Register

public class Main extends JFrame {

private void jbInit() throws Exception
{
...
jMenuRegister.setText("Registrati");
jMenuRegister.addActionListener(new Main_jMenuRegister_actionAdapter(this));

...
}

}

Il gestore degli eventi per l'item del menu che si chiama "Registrati" è l'oggetto instanza della classe Main_jMenuRegister_actionAdapter. Nella lezione 1 non ho spiegato bene questa cosa: la classe Main_jMenuRegister_actionAdapter implementa l'interfaccia ActionListener in modo da gestire gli eventi dell'oggetto Main, infatti se la decompiliamo otteniamo:

package crack_me;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// Referenced classes of package crack_me:
// Main

class Main_jMenuRegister_actionAdapter implements ActionListener
{

Main_jMenuRegister_actionAdapter(Main adaptee)
{
this.adaptee = adaptee;
}

public void actionPerformed(ActionEvent e) <- implementa il metodo ActionPerformed
{
adaptee.jMenuRegister_actionPerformed(e); <- richiama questo metodo dell'oggetto Main
}

Main adaptee;
}


Come possiamo vedere dal codice la classe Main_jMenuRegister_actionAdapter implementa il metodo actionPerformed dell'interfaccia ActionListener dicendo che il gestore del click sull'item "Registrati" è il metodo jMenuRegister_actionPerformed(e) della classe Main.

Il metodo jMenuRegister_actionPerformed(e) è il seguente:

void jMenuRegister_actionPerformed(ActionEvent e)
{
Register dlg = new Register(this);
.....

dlg.show();

}

Il metodo non fa altro che instanziare un oggetto di tipo Register che eredita a sua volta da JDialog, la classe che gestisce i dialoghi. In modo analogo individuiamo il metodo che gestisce il click sul bottone Registra che si chiama

La classe Register è presente nel package locale quindi la decompiliamo:

void BottoneReg_actionPerformed(ActionEvent e)
{
String user = TextUtente.getText();
String serial = TextSeriale.getText();
ControlloF ctrl = new ControlloF(user, serial);
boolean check = ctrl.check();
if(check)
{
JOptionPane.showMessageDialog(null, "OK", "Applicazione registrata", 1);
main.MainInfo.setText("Applicazione registrata");
main.jMenuRegister.disable();
} else
{
JOptionPane.showMessageDialog(null, "No", "Il seriale non \350 corretto", 0);
}
dispose();
}

Questa volta il controllo viene effettuato da un oggetto apposito, come richiedeuna buona progettazione ad oggetti, ctrl instanza della classe ControlloF. Il costruttore di ControlloF ha come parametri formali due oggetti di tipo stringa che corrispondono al nome dell'utente e al seriale. Il metodo check di ControlloF ritorna un valore booleano che indica se il seriale è corretto oppure no.

A questo punto decompiliamo la classe ControlloF

package crack_me;

// Referenced classes of package crack_me:
// ControlloP

public class ControlloF extends ControlloP
{

ControlloF(String utente, String serial)
{
super(utente, serial);
}
}

Ma come è possibile? Il metodo check non è presente in ControlloF mentre il costruttore si. Il trucco è semplice: i programmatori hannno nascosto il metodo di controllo sfruttando l'ereditarietà. La classe ControlloF eredita da ControlloP, quindi il metodo sarà nella superclasse che andremo a decompilare.

// Source File Name: ControlloP.java

package crack_me;

public class ControlloP
{

public ControlloP(String utente, String seriale)
{
this.utente = utente;
this.seriale = seriale;
}

public boolean check() <- ecco il metodo nascosto
{
int len1 = utente.length();
int len2 = seriale.length();
return len1 + len2 > 10 && len1 + len2 < 15;
}

private String utente;
private String seriale;

}

Bingo, abbiamo trovato il metodo nascosto check. Il controllo è banale: si sommano le lunghezze delle stringhe di nome utente e seriale e si controlla se la somma è compresa tra 10 e 15, estremi esclusi. Un esempio di seriale corretto è:

Utente: Paolo (6 caratteri) Seriale: Diprox

Modifichiamo allora la classe ControlloP in modo che restituisca sempre TRUE:

public boolean check() <- ecco il metodo nascosto
{
int len1 = utente.length();
int len2 = seriale.length();
return TRUE;
}

2.salviamo il sorgente modificato in un cartella con lo stesso package delle classi, nel mio caso F:\ToCrack\crack_me. Nella stessa cartella copiamo il jar originale crack_me.jar

3.ricompiliamo solo la classe ControlloP usando le classi che stanno nel package, nella cartella crack_me creata :

F:\ToCrack\crack_me\> javac -classpath crack_me.jar ControlloP.java

4.aggiungiamo la classe ControlloP ricompilata nel jar dalla directory superiore, questo è importante altrimenti la classe non verrà aggiunta nel package corretto:

G:\ToCrack>jar uf crack_me/crack_me.jar crack_me/ControlloP.class

5.verifica

G:\ToCrack\crack_me\>java -jar crack_me.jar

Nella lezione 1 ho scritto javac invece che java, chiedo perdono :->, molti avranno bestemmiato!

L'applicazione viene registrata con qualsiasi nome e seriale.

 

������������������������� ������������������������������������������������������������������������������� ...::: EPOKH :::...

Note finali

Nelle prossime lezioni ci divertiremo alla grande visto che inizieremo a reversare delle applicazioni "vere".

Disclaimer

Vorrei ricordare che il software va comprato e� non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento � stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.�