NFTP 1.62 - 2 modi diversi di registrarlo
Pubblicato da blAAd! il 20/04/2001
Livello base

Introduzione

Salve a tutti. In questo tutorial essenzialmente per Newbies, mostrero' 2 modi di registrare l'ottimo ftp client NFTP 1.62 (che fa' richiesta di nome/seriale), sia attraverso la creazione di una patch, sia ottenendo il giusto seriale. Per quest'ultimo punto, utilizzeremo il comando 'ltrace', gia' presente in molte distribuzioni Linux, ma che potete scaricare anche dal sito RACL.
L'URL di NFTP e' : "http://www.ayukov.com/nftp".

Programmi usati

Iniziamo

Dopo aver scompattato il file, ed esguito installazioni varie, si puo' notare subito che esistono 2 versioni del programma. Quella da shell "nftp", e quella tramite XServer "xnftp". Consideriamo quest'ultima (il discorso e' identico per "nftp").
Facciamo una copia del file originale (/usr/bin) in una directory che ci fa' comodo, e disassembliamo il file con :


./dasm.pl xnftp xnftp.out
Cerchiamo una maniera per controllare comodamente le stringhe di testo, all'interno del disassemblato 'xnftp.out'. Da shell semplicemente scriviamo :

egrep \" xnftp.out | sort > stringhe.xnftp
Ora nel file stringhe.xnftp, avremo le stringhe di riferimento ordinate alfabeticamente (esistono comunque diverse opzioni per 'sort', che danno diversi tipi di ordinamento). Editiamo il file con un qualsiasi editor, e diamo uno sguardo a cio' che puo' interessarci. Troveremo subito le stringhe "registration-code" e "registration-name". Non vi dice nulla?
Editiamo ora il file xnftp.out (vi consiglio Vim), ed avviamo la ricerca <Find> per "registration-name" e "registration-code". Queste stringhe vengono ripetute piu' di una volta, e quindi si troveranno in parti diverse del programma. Con un po' di intuito pero' (e un po' di conoscenza assembler AT&T), capirete sicuramente che la parte di codice che ci interessa e' :

Possible reference to string:
"registration-name"

0x0806e04e push   $0x808d681 ---> riferimento fisico alla nostra stringa
0x0806e053 push   $0x0
0x0806e055 call   0x080828fc ---> stampa la stringa
0x0806e05a mov    %eax,0xfffffdfc(%ebp)
0x0806e060 add    $0xfffffff8,%esp

Possible reference to string:
"registration-code"

0x0806e063 push   $0x808d693
0x0806e068 push   $0x0
0x0806e06a call   0x080828fc ---> stampa la seconda stringa
0x0806e06f mov    %eax,0xfffffdf8(%ebp)
0x0806e075 add    $0x20,%esp
0x0806e078 mov    0xfffffdfc(%ebp),%esi

Possible reference to string:
"darKwING"

0x0806e07e mov    $0x808d6a5,%edi
0x0806e083 mov    $0x9,%ecx
0x0806e088 cld    
0x0806e089 test   $0x0,%al
0x0806e08b repz cmpsb %es:(%edi),%ds:(%esi)
0x0806e08d je     0x0806e146 ---> se il nome inserito e' "darKwING" esce
0x0806e093 mov    0xfffffdfc(%ebp),%esi

Possible reference to string:
"dustie of blizzard"

0x0806e099 mov    $0x808d6ae,%edi
0x0806e09e mov    $0x13,%ecx
0x0806e0a3 cld    
0x0806e0a4 test   $0x0,%al
0x0806e0a6 repz cmpsb %es:(%edi),%ds:(%esi)
0x0806e0a8 je     0x0806e146 ---> se il nome inserito e' "dustie of blizzard" esce
0x0806e0ae mov    %eax,%esi

Possible reference to string:
"1230000000000000000000000"

0x0806e0b0 mov    $0x808d6c1,%edi
0x0806e0b5 mov    $0x1a,%ecx
0x0806e0ba cld    
0x0806e0bb test   $0x0,%al
0x0806e0bd repz cmpsb %es:(%edi),%ds:(%esi)
0x0806e0bf je     0x0806e146 ---> se il codice inserito e' "12300...." esce
0x0806e0c5 mov    0xfffffdfc(%ebp),%eax
0x0806e0cb cmpb   $0x0,(%eax)
0x0806e0ce je     0x0806e146 ---> se non e' stato inserito alcun codice esce
0x0806e0d0 mov    0xfffffdf8(%ebp),%eax
0x0806e0d6 cmpb   $0x0,(%eax)
0x0806e0d9 je     0x0806e146 ---> se non e' stato inserito alcun nome esce
0x0806e0db mov    %eax,%edi
0x0806e0dd mov    $0x0,%al
0x0806e0df cld    
0x0806e0e0 mov    $0xffffffff,%ecx
0x0806e0e5 repnz scas %es:(%edi),%al
0x0806e0e7 mov    %ecx,%eax
0x0806e0e9 not    %eax
0x0806e0eb dec    %eax
0x0806e0ec cmp    $0x3,%eax ---> il nome deve essere lungo almeno 3 caratteri
0x0806e0ef jbe    0x0806e146
0x0806e0f1 add    $0xfffffffc,%esp
0x0806e0f4 lea    0xfffffe00(%ebp),%ebx
0x0806e0fa push   %ebx ---> salva sullo stack
0x0806e0fb mov    0xfffffdf8(%ebp),%eax
0x0806e101 push   %eax ---> salva sullo stack
0x0806e102 mov    0xfffffdfc(%ebp),%eax
0x0806e108 push   %eax ---> salva sullo stack
0x0806e109 call   0x0806e154 ---> salta alla routine di creazione del seriale
0x0806e10e add    $0x10,%esp
0x0806e111 add    $0xfffffff8,%esp
0x0806e114 push   %ebx
0x0806e115 mov    0xfffffdf8(%ebp),%eax
0x0806e11b push   %eax

Reference to function : strcmp

0x0806e11c call   0x08049b64 ---> confronta il seriale corretto con il nostro 'fake'
0x0806e121 add    $0x10,%esp
0x0806e124 test   %eax,%eax
0x0806e126 jne    0x0806e146 ---> se i seriali non sono uguali esce
0x0806e128 movl   $0x1,0x8093ee0
0x0806e132 add    $0xfffffff4,%esp
0x0806e135 mov    0xfffffdfc(%ebp),%eax
0x0806e13b push   %eax

Reference to function : __strdup

0x0806e13c call   0x08049fc4
0x0806e141 mov    %eax,0x8093f20

Referenced from jump at 0806e03b ; 0806e08d ; 0806e0a8 ; 0806e0bf ; 0806e0ce ; 0806e0d9 ; 
0806e0ef ; 0806e126 ;

0x0806e146 lea    0xfffffdd8(%ebp),%esp
0x0806e14c pop    %ebx
0x0806e14d pop    %esi
0x0806e14e pop    %edi
0x0806e14f mov    %ebp,%esp
0x0806e151 pop    %ebp
0x0806e152 ret
Cio' che succede sopra e' semplice. Dopo aver inserito (dal menu' principale andate su 'Options'->'Registration code...') nome e seriale, verranno fatti alcuni semplici controlli, e si passera' alla creazione del seriale vero tramite la routine chiamata in 0x0806e126. Al ritorno da questa, verra' confrontato il nostro seriale 'fake' con quello appena generato. Cio' ci suggerisce ovviamente di 'noppare' il salto alla routine di keygen, ed il gioco e' fatto.
Ecco il codice della semplice patch, che andra' inserita ed eseguita nella stessa directory di 'xnftp' :

#include <stdio.h>

char *nomefile="xnftp";

int main()
{
 long patch_byte_offset=0x00026126;
 FILE *fp;
 unsigned int x = 0x9090;

 fp=fopen(nomefile,"r+");
 if (!fp)
 {
  printf("Devi posizionare la patch nella stessa directory di XNFTP\n");
  exit(-1);
 }
 
 fseek(fp,patch_byte_offset,SEEK_SET);
 fwrite(&x,2,1,fp);
 fseek(fp,0,SEEK_END);
 fclose(fp);
 return 0;
}
Piuttosto semplice, no? Il codice C non fa' altro che aprire il file e posizionarsi al byte indicato dalla variabile 'patch_byte_offset' 0x00026126, che rappresenta il 'jne 0x0806e146' tramite l'istruzione fseek, e 'nopparlo'. Personalmente odio 'patchare' i programmi, e, come in questo caso, preferisco ottenere il seriale esatto. I metodi sono 2. O ci costruiamo la keygen sapendo che in 0x08049b64 inizia la routine di creazione del seriale (e questo e' un buon algoritmo in stile CrackMe, da studiare, soprattutto per chi inizia con l'assembler), oppure 'farci dare il seriale'. Ma come?
Qui entra in gioco LTRACE, un pacchetto Debian utile per tracciare le chiamate, alle funzioni delle 'shared libraries' (grosso modo le funzioni classiche utilizzate dai programmi C).
Trovate gia' alcuni tutorials che trattano questo comando (e anche le shared libraries), quindi per approfondimenti vi rinvio ad altri testi. Qui ci basta conoscere le funzioni principali del comando 'LTrace' :
-i : visualizza l'indirizzo in cui avviene la chiamata tracciata
-s : setta la lunghezza della stringa relativa alla chiamata da tracciare
-e : seleziona quale funzione deve essere tracciata
-o : l'eventuale file di output per visualizzare i risultati
Queste sono le opzioni strettamente necessarie. Comunque con un semplice 'ltrace --help' potrete visualizzare la lista completa dei comandi.
Chi viene dal reversing sotto Windows, ed ha utilizzato programmi come SmartCheck per la scansione dei programmi in Visual Basic, trovera' una familiarita' notevole di questo tool col prodotto della Numega.
Nel nostro caso avviamo Xnftp (possibilmente non patchato) tramite il comando:

ltrace -o /eventuale_directory/file_controllo -i -e strcmp /eventuale_directory/xnftp
Il file 'file_controllo', conterra' la scansione di tutte le chiamate alla funzione 'strcmp' tramite l'opzione -e (ho trascurato -s). Mi sono riferito al controllo sulla funzione 'strcmp', perche', come potete notare dal disassemblato d'inizio, all'indirizzo 0x0806e11c e' presente dopo la creazione del seriale, la chiamata alla funzione 'strcmp'. Quindi e' tutto chiaro...
Il programma partira' subito dopo aver premuto [Invio] alla riga evidenziata sopra. Entriamo nella sezione di registrazione inserendo il nome col seriale, ed usciamo. Sempre da console scriviamo:

egrep 806e11c /eventuale_directory/file_controllo
Questo stampera' le righe in cui e' avvenuta la scansione della chiamata alla funzione 'strcmp', che evidenziera' il nostro seriale inserito, accanto a quello corretto.
Se avete registrato il programma una prima volta, e poi correggete il nome (sempre dopo aver impartito il comando 'ltrace'), troverete 2 righe di 'check' stampate. Questo perche' ogni volta che avviate il programma, ci sara' un controllo sul file di registrazione e un nuovo 'check' sul codice inserito. Quindi la seconda riga che vi apparira' sara' quella col nuovo codice corretto!
Questo e' quanto...
byz by blAAd!

Conclusioni

Non molto da dire. Semplicemente spero di esser stato chiaro, e che questo tutorial sia utile ai Newbies. Un saluto alla RACL e a tutta la Mailing List RACL.

Attenzione

Questo tutorial e' a solo scopo informativo. Ne io, ne i possessori del sito, siamo responsabili di un eventuale abuso di cio' che e' stato trattato, per scopi di pirateria e violazione di copyright. In qualsiasi caso rubare e' sbagliato, e i vari tutorial presenti sul sito dovrebbero aiutare a comprendere l'impegno profuso da parte dei programmatori, per la creazione d'ogni singolo programma.