Présentation du logiciel
On s'interesse ici à la version 4.4.1006.
FTP Rapide est dévellopé par Jean-Claude Mariotte (jcmariotte@kiriasse.fr), société Kiriasse (www.kiriasse.fr).
J'ai trouvé ce logiciel dans PC Shareware N°4, un mag avec des cds tout pleins de sharewares à cracker (quoique un peu trop de freewares à mon gout :-)).
Ce mag est un peu vieux (novembre 2001) mais on est là pour apprendre ;-)
La présentation qu'ils donnent du logiciel est la suivante :
Ce logiciel client FTP permet de télécharger logiciels et documents depuis un serveur FTP. (nan c vrai ??)
Limité en version non enregistrée à ceux acceptant les accès anonymes (login: anonymous / password: guest), il est extrémement simple à utiliser. S'il en est limité dans ces fonctions, il permet  cependant de suivre les chargements avec des indications de taille, de progression et de vitesse. Mais ses principaux attraits reposent dans la recherche intégrée d'adresse FTP sur http://ftpfind.voila.fr et surtout dans la possibilité de créer des raccourcis avce une ligne de commande intégrant toutes les informations pour charger directement un fichier. Pratique donc pour récupérer régulièrement et d'un double-click des fichiers souvent mis à jours.

Bon pour ce qui est de la communication avec le ftpfind de voila g pas pu tester car g pas de connexion internet perso (comme moi je ne cracke pas pour ma pomme ;-)
A noter aussi que le logiciel possède une petite musique qui tourne en boucle : le canon de Pashenbel (je sais pas si ça s'écrit comme ça), enfin pour les pas culturés (car la cultivation c pour les patates), il s'agit de la musique de fond sur le "Je me souviens" de Ménélik. Cette musique, très agréable au demerant peu devenir très énervante si vous débuggez le logiciel (entendre le meme morceau pendant une heure c saoulant) alors baissez le son si vous le déplombez !!

Le prix de la licence est de 150F Français, ce que personellement je trouve trop cher, enfin faut dire que j'utilise la commande FTP sous dos :-)

Etude du logiciel
Bon on fait comme d'hab, on provoque le logiciel : on le démarre, il nous met "version non enregistré" (ou un truc du style) alors nous on est poli, on clique sur "s'enregistrer", il nous demande un username (g pris niicolas ou sirius_black... selon les essais que g fait) puis ensuite il nous demande le password (le tout dans des InputBox différentes) la j'entre sirius01 ou 666fuckyou...

Apparemment le logiciel n'aime pas : invalid name...
On note sa Jérémiade et on désassemble le prog avec Win32Dasm (version 8.93 chez moi). On clique sur String Data References et là : Horeur !!! Ya que dalle sinon "VB5".
Faut pas démoraliser parce que comme a dit intruder mexelite97 dans son tut "happy vb5 cracking" : "IF VISUAL BASIC THEN CRACKED AT ONCE".
En effet les progs vb étaient de véritables merdes dans les versions 1, 2 et 3 du langage visual basic. Because il suffisait de posséder le Dodi's VB Discompiler et on se retrouvait avec la source du programme... LoL !!! Avec le VB5 ca va être plus dur !!!

Quand g commence a déplombé le prog j'avais pas encore Smartcheck donc j'ai utilisé le VBREF de la team Execution Council. Le principe ? Vous enregistrer la decompilation dans un .alf avec w32dasm puis avec vbref vous générez un .vbr avec le prog et le .alf et vous obtenez à peu près ce que donne w32 mais avec les strings. Mais la navigation est disons... plus archaique avec vbref. Quoique il en soit on trouve les strings qui nous interesse dans vbref :

On clique sur "Le nom d'utilisateur et/ou la clef..." (juste au dessus de Username and/or key are not valid.) Si on clique plusieurs fois on voit que ya qu'une occurence donc c'est cool.
En gros on tombe sur :

Nom d'utilisateur (User name)
:0042C897 mov dword ptr [ebp+FFFFF38], 0040B1F0

Veuillez saisir votre nom d'utilisateur de Ftp Rapide.
:0042C8EA push 0040B11C

MSVBVM60.rtcInputBox, Ord:0254h username en 00471fc8 (adresse dans eax) //première input box (username)
:0042C973 Call dword ptr [004010A4]

MSVBVM60.__vbaStrCmp, Ord:0000h // hehe
:0042C9E4 Call dword ptr [004010EC]

Clef pour (Key for) Ftp Rapide
:0042CA58 mov dword ptr [ebp+FFFFFF38], 0040B314

Veuillez saisir votre clef (mot de passe pour Ftp Rapide).
:0042CAA7 push 0040B230

MSVBVM60.rtcInputBox, Ord:0254h pass en00468d88 //seconde input box (password)
:0042CB30 Call dword ptr [004010A4]

MSVBVM60.__vbaStrCmp, Ord:0000h //hinhin
:0042CBA1 Call dword ptr [004010EC]
test eax, eax
je 0042D0E9 <- celui la ?
:0042CBAF lea ecx, dword ptr [ebp-1C] -> adress password
:0042CBB2 lea edx, dword ptr [ebp-28] -> adresse login
:0042CBB5 push ecx
:0042CBB6 push edx
  ...
:0042CBB7 call 0041FBB0
test ax, ax
jne 0042CE61 <- vers Valid username and key.(tiens c'est celui là)
:0042CBC5 call 0041EE30

:0042CBE5 Bad Boy
Alors comment ca marche ? Ben on debugge le prog avec w32 sur cette zone avec les options sur les apis et on regarde :
Il commence par créer une inputbox qui demande le user name. Une fois rentré, le prog compare avec la chaine vide (vérifie que l'on a tapé kekchose). Puis il fait pareil avec la clé.
Ca devient donc interessant à partir de :0042CBAF. Si on débugge on verra rien du tout dans la fenêtre de documentaion API et pour cause le call 0041FBB0 est une fonction crée le concepteur. En fait cette fonction utilise des variables locales qui sont stockées en ebp-1C et ebp-28. Et comme par hazard ya le username et la key !!
Ca fait un tas de calcul puis après ca regarde si ax vaut zéro. Si c'est le cas les codes ne sont pas bons et on poursuit sinon c'est que c'est bon et on va en 0042CE61.

J'en voient déjà qui disent : ca y est il va mettre un jmp 0042CE61 après la routine. Ben non !! Parce que le prog vérifie les clés (stockées dans la base de registre) au démarrage c'est pour ca qu'il nous affiche que l'on est pas enregistré au départ. Il se peut que ce soit la meme routine utilisé au démarrage et dans les box, dans ce cas il faut faire en sorte qu'elle renvoie toujours 1.
Mais j'ai pas regarde (d'ailleurs faudra que je regarde). Moi je préfère ne pas toucher au prog et faire un keygen. Enfin j'ai quand meme essayé de le reverser pour qu'il crache la clé correspondante au username qu'on lui file. Ca marche la première fois que la fonction est appele mais apres c'est du nimportenawak (la pile n'est pas remise comme il faudrait, et puis le code n'est pas facilement détournable dans notre cas).

En débuggant (toujours sans Smartcheck) on voit qu'il commence par :

__vbaStrCopy(57f18b56,8dec8b55,0,0,0,0,0,0)=004566a4->"RAPIDFTP"// met RAPIDFTP en mémoire et dan eax
API Address=0041FC71, API Return Address=0041FC77

__vbaStrCmp("",004566ec->"sirius01",6602465b,66025324,0,0,0,0)=1 // on vérifie que une clé a été entrée
API Address=0041FC88, API Return Address=0041FC8A

__vbaStrCmp("",00468ae4->"niicolas",6602465b,66025324,0,0,0,0)=1 // on vérifie qu'un username a été entré
API Address=0041FC9D, API Return Address=0041FC9F

__vbaStrCat(00468ae4->"niicolas",004086dc->"KIRIASSE",6602465b,66025324,0,0,0,0)=00468d2c->"KIRIASSEniicolas"
//concaténation
API Address=0041FCB5, API Return Address=0041FCBB

__vbaStrMove(6602465b,66025324,0,0,0,0,0,0)=00468d2c->"KIRIASSEniicolas" et eax //mise en mémoire
API Address=0041FCC6, API Return Address=0041FCC8

rtcRightCharBstr(00468ae4->"niicolas",8,6602465b,66025324,0,0,0,0)=00468d88->"niicolas"
//on prend les 8 derniers car du login (dans mon cas yen a deja 8)
API Address=0041FCCD, API Return Address=0041FCD3

__vbaStrMove(6602465b,66025324,0,0,0,0,0,0)=00468d88->"niicolas" //mise en mémoire
API Address=0041FCD8, API Return Address=0041FCDA

rtcUpperCaseBstr(00468d88->"niicolas",6602465b,66025324,0,0,0,0,0)=00468cb8->"NIICOLAS" //mise en majuscule
API Address=0041FCDB, API Return Address=0041FCE1

__vbaStrMove(6602465b,66025324,0,0,0,0,0,0)=00468cb8->"NIICOLAS" //mise en mémoire
API Address=0041FCE6, API Return Address=0041FCE8

__vbaFreeStr(6602465b,66025324,0,0,0,0,0,0)=20 //libération de l'espace
API Address=0041FCEB, API Return Address=0041FCF1
Ouais je sais j'ai mis un peu trop de détail, j'en met un peu moins maintenant :
rtcMidCharBstr(00468cb8->"NIICOLAS",1,0067e2f0,6602465b,66025324,0,0,0)=00468d88->"N"
//on prend le premier caractère a partir du début
API Address=0041FD4B, API Return Address=0041FD51
__vbaStrMove(6602465b,6602465b,66025324,0,0,0,0,0)=00468d88->"N" //mise en mémoire
API Address=0041FD56, API Return Address=0041FD5C
__vbaStrCopy(6602465b,66025324,0,0,0,0,0,0)=00471fec->"N" //mise en mémoire
API Address=0041FD66, API Return Address=0041FD6C

Ca recommence ensuite avec les 7 lettres qui restent de notre login.
Puis il fait la meme chose (mise en memoire de lettres) avec la chaine de caractères "RAPIDFTP".
Une fois cette partie effectuée il prend la première lettre de RAPIDFTP, puis la compare au lettres de l'alphabet mises dans un ordre spécial. Quand il l'a trouvé il s'arrête de comparer et calcule en nombre. Ensuite il passe à la lettre suivante etcetera
Au départ j'avais classé les lettres de cette alphabet spécial en fonction de leur proximité dans la mémoire, j'avais obtenu :

par zone de chaine
1,2,3,4,5,6,7,8,9,0,A,K,U,B,L,V,C,
M,W,
D,N,X,
E,O,Y,F,
P,
Z,G,Q,H,R,I,S,J,T,#,$
ce qui ne m'avait pas vraiment arrangé !! Alors je me suis dit : chaque fois qu'une lettre trouve sa correspondance, le programme en déduit une valeur. Il faut donc que je classe par "conséquence". En effet certaines lettres renvoient le même nombre. J'ai donc fait un regroupement par "jump" suivant les lettres et j'ai obtenu :
par saut
1,2,3,4,5,6,7,8,9,0, -> 00420332
A,K,U, 004202f0 ->"1"
B,L,V, 004202ab
C,M,W, 00420266
D,N,X, 00420221 ->"4"
E,O,Y, 004201dc
F,P,Z, 00420197 ->"6"
G,Q, 00420152
H,R, 0042010d ->"8"
I,S, 004200c8 ->"9"
J, 00420083
T, 004203a8 ->"0"
#,
$
Voilà qui est plus lisible !! Premier problème que l'on remarque dans le programme : un calcul inutile !!! A quoi bon calculer un code à partir d'une chaine qui est toujours la même :(
A moins que... a moins que cette fonction soit utilisé dans d'autres programmes du même développeur et dans ce cas si on arrive à faire un keygen pour FTP Rapide, il suffira de changer la chaine "magique" (RAPIDFTP) par TRUCFTP si on faire un keygen pour TrucFTP !! On verra ca quand j'aurais fini le tut :-)

Reprennons, RAPIDFTP donne en nombres : 81694606.
Voyons ce qu'il fait avec notre name

rtcR8ValFromBstr(471eb4->"8")=10 //toujours pris dans w32dasm puis modifier pour la lecture

rtcAnsiValueBstr(00468de4->"N",,,,,,,)=4e // transformation en ascii de la première lettre

__vbaFpI2(6602465b,66025324,0,0,40538000,4e,0067e2b0,bff6a26e)=56 // 4E + 8 = 56

rtcBstrFromAnsi(56,6602465b,66025324,0,0,40538000,4e,0067e2b0)=00471f68->"V" // valeur de "V" ? 56 evidemment
API Address=004205DA, API Return Address=004205E0
Il fait donc une addition avec toutes les lettres. Mais si on calcule le serial comme ca, ca ne marchera pas... Il fait des calculs en plus. Alors je suis passé sur smartcheck pour la première fois et la vraiment ça vaut le coup !!
Voici quelques images de quoi faire la config de smartcheck (si c'est pas déjà fait).


Au lancement de startcheck je vous conseille d'avoir le bouton avec le carre bleu enfoncé (pas trop de détail). Puis vous loaddez FTP Rapide, vous entrez le username et la clé puis quand il affiche "username and/or key not valid" vous cliquez pas !!! Vous cliquez sur stop dans smartcheck. Ainsi on aura le minimum de code utile. Vous vous retrouvez devant :

Il faut alors développer tous les derniers trucs. On commence par le load. On descent tout en bas, ya un "_Click". On le développe puis on recommence avec AniGIF1_Click (toujours en bas). Ne développez pas la message box après (message d'erreur). Vouz voyez :


On a un peu de mal car Smartcheck met des décimaux et non de l'hexa : "V" vaut 86. On peut se repérer avec les marteaux. "niicolas" donne donc "VJOLSRAY". Mais c'est pas fini. On clique sur la bulle jaune dans le menu de SC et on a les appels API.
On remarque le strcmp final dans cette fonction locale : strcmp("666fuck","VJ$LSRAY");
Ben ça alors !! Notre 'O' se transforme en '$' !! On regarde avec notre 'S' (dernière lettre) : il prend la lettre et l'additionne avec le dernier chiffre (6) ce qui donne 'Y', normal.
Mais après ya un tas de comparaison : avec les chiffres puis avec 'O'. On comprend qu'il traite des cas particuliers. Pour le 'O' voilà ce qu'il se passe.


Pas de calcul, juste parce que c'est un 'O' on le remplace par '$'. L'expérience nous montreras que pour les caratères non lettres capitales, il les remplace par les chiffres du magic code+1.
Si on rentre 01234567 il renvoie 927#4606 (je rapelle que le magic code est 81694606). On note que le 9 est remplacé par '#'.


Récapitulatif :
il prend le nom 'niicolas'
il le met en majuscules 'NIICOLAS'
il fait l'addition avec '81694606'
ce qui nous donne 'VJOLSRAY'
On enleve les 'o' etc 'VJ$LSRAY'
Voilà !!
D'autres exemples : sirius_black donne 9T7KPGCQ
57463201 donne 927#5717
Un petit keygen. Allez on le fait en C :
/* Keygen by sirius_black
+ FTP Rapide v4.4.1006
* Pure 3133t3 c0d3Z
+ F34R m3 !!!
+ Yah !!!
+ Pr0uT !!
+ Sex, Punk & CrackZ
+ Enjoy
*/
#include <stdio.h>
#include <stdlib.h>
void calcul(char *x){
int i;
char *y=x;
for (i=0;i<strlen(x);i++){
if (*y<123 && *y>96)*y=(char)((*y)-32);
y++;
}
}
int is_alpha(char *y){
if (*y>64 && *y<91)return 1;
else return 0;
}
void calcul2(char *x){
char *y=x;
if (is_alpha(y) && (*y)+8<91)*y=(*y)+8;
else *y='9';
y++;
if (is_alpha(y) && (*y)+1<91)*y=(*y)+1;
else *y='2';
y++;
if (is_alpha(y) && (*y)+6<91)*y=(*y)+6;
else *y='7';
y++;
if (is_alpha(y) && (*y)+9<91)*y=(*y)+9;
else *y='#';
y++;
if (is_alpha(y) && (*y)+4<91)*y=(*y)+4;
else *y='5';
y++;
if (is_alpha(y) && (*y)+6<91)*y=(*y)+6;
else *y='7';
y++;
if (!is_alpha(y))*y='1';
y++;
if (is_alpha(y) && (*y)+6<91)*y=(*y)+6;
else *y='7';
}
void fuck_hOokers(char *x){
int i;
char *y=x;
for (i=0;i<8;i++){
if (*y=='O')*y='$';
y++;
}
}
int main()
{
int taille;
char * username;
int i;
username=malloc(16);
printf("Crack de FTP Rapide 4.4.1006\n");
printf("par sirius_black\n");
printf("\nEntrez votre username (pas d\'espaces) : ");
scanf("%s",username);
while(strlen(username)<8){
printf("\nEntrez votre username (au moins 8 caracteres) : ");
scanf("%s",username);
}
calcul(username);
taille=strlen(username)-8;
for(i=0;i<taille;i++)username++;
calcul2(username);
fuck_hOokers(username);
*(username+8)='\0';
printf("Votre serial est :\n%s\n",username);
free(username);
system("PAUSE");
return 0;
}