REALPLUS G2 KEYGENERATOR
Do it yourself !
by +TsehP


This is a harder essay, not really intended for newbies, but if someone of you thinks he's ready to do something more this is a good starting point. This is about a keygen (my favourite subject, as you know ;)) and has both a well commented code and a source that will help you to bettern learn keygen programming.



This essay will help to get inside the core of the algorythm to generate a
serial for realplus g2. Don't expect me to explain everything to you in this
essay 'cause it's designed to be read by intermediate crackers. I will only
guide you to make you understand how it works and if you know how to program
in C or another language, you'll build your own keygenenerator. A source of
my own program is appended at this essay.


                                 Introduction 


Well thanks to Hellraiser and spirit for their previous essay on realplus 4.0;
I just wanted this essay to make a deeper approach, the purpose is to write a
keygen and not use the original routines taken from the prog.

Why is this, because if the program evolves, you will be able easily to change
your own soft !

                                Tools required 


Tools used:

    Softice 3.22
    Windasm 8.9
    Microsoft visual c++ compiler (or any other)
    Aspirin brain++ (Viagra tablets doesn't work here ;-) )


                               Target's URL/FTP

Realplayer plus G2,downloadable if you make a ftpsearch with r32ppg2(xxx)
(read +fravia's tips for search)
I will not give the link I used 'cause it will surely not be available at the
time you will practice my essay, learn to search with fravia's essays:
http://fravia.org/search.htm


                               Program History 


Realplayers are king of old, previous versions were 1.0 2.0 and so until 5.0
Now G2 with improved sound and video, the world's most important player on
internet.

                                    Essay

To start :
fire Sice, bpx getwindowtexta and follow the code you entered with various
bpm xxxx.

Watch out it is copied in memory several times, to remove the '-' for
examples.

If you make a good work, you will land here in sete3260.dll if you are in
installation process.

You can do it by enter serial option when realplus is installed in demo mode
but the adresses will not be correct.

You can bpx on 10009e9e to shorten all the easy part...


You land here :

:10009E9E FFD5          call ebp ;ascii to bin code conversion
:10009EA0 833822        cmp dword ptr [eax], 00000022 ;beggar of if your code > 0x19999999
:10009EA3 7457          je 10009EFC
:10009EA5 53            push ebx ;push offset to hex code
:10009EA6 E865020000    call 1000A110 ;encrypt + check routine
:10009EAB 8B742418      mov esi, dword ptr [esp+18]
:10009EAF 83C404        add esp, 00000004
:10009EB2 85C0          test eax, eax ;if eax=0 beggar off !
:10009EB4 8906          mov dword ptr [esi], eax
:10009EB6 7436          je 10009EEE
:10009EB8 3DBFEA2101    cmp eax, 0121EABF ;first limit of crypted result
:10009EBD 772F          ja 10009EEE ;must be lower (not the right limit)
:10009EBF 8B17          mov edx, dword ptr [edi]
:10009EC1 52            push edx
:10009EC2 50            push eax
:10009EC3 E8E8000000    call 10009FB0 ;second check with tables
:10009EC8 83C408        add esp, 00000008
:10009ECB 85C0          test eax, eax ;eax=1 good guy!
:10009ECD 7411          je 10009EE0

the first place to go is call 1000a110, this is the most interesting part.
This routine use the hex conversion of your entered code to generate a number
that will be checked at the second call with lookup tables. Well lets go to
this part that was kind of complicated to me.

I will not explain to you all the details of this check 'cause this is left
as an exercise to the reader, you will have the complete source of my keygen
at the end of my project but I'll leave you some spots to help you build your
own keygenerator or/and to improve mine (that is an great example of poor C
programming !).

* Referenced by a CALL at Addresses:
|:10009EA6 , :10009F28 
|
:1000A110 83EC14        sub esp, 00000014
:1000A113 53            push ebx
:1000A114 55            push ebp
:1000A115 56            push esi
:1000A116 8B742424      mov esi, dword ptr [esp+24]
:1000A11A 81FEE8CD9A3B  cmp esi, 3B9ACDE8 ;fake dummy hex code
                                    ;this was present in versions 4.0 and 5.0
                                    ;this returns eax=1 but it's a fake check
                                    ;to loose newbies ! 
:1000A120 57            push edi
:1000A121 750D          jne 1000A130 ;we go there !

* Possible Reference to String Resource ID=00001: "Configuration file
RNSETUP.CFG is missing or corrupted. Setu"
|
:1000A123 B801000000    mov eax, 00000001
:1000A128 5F            pop edi
:1000A129 5E            pop esi
:1000A12A 5D            pop ebp
:1000A12B 5B            pop ebx
:1000A12C 83C414        add esp, 00000014
:1000A12F C3            ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A121(C)
|
:1000A130 33C9          xor ecx, ecx
:1000A132 3BF1          cmp esi, ecx
:1000A134 750A          jne 1000A140 ;we go there !
:1000A136 33C0          xor eax, eax
:1000A138 5F            pop edi
:1000A139 5E            pop esi
:1000A13A 5D            pop ebp
:1000A13B 5B            pop ebx
:1000A13C 83C414        add esp, 00000014
:1000A13F C3            ret

ATTENTION ! This is the real part.Study this place very carefully because
there's a lot of fake checks a a few good ones.

To explain how it works, roughly, here's an example of code :1000666000
each digit is analysed from right to left (follow it with softice)
and you've got a number generated with their hex value and two counters (one
that is the sum of them, progressive and another thats like a=a*8+a.

You'll have to discover the mathematical process and write it to make your
keygen !

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A134(C)
|
:1000A140 83C8FF        or eax, FFFFFFFF
:1000A143 894C2418      mov dword ptr [esp+18], ecx
:1000A147 894C2414      mov dword ptr [esp+14], ecx

* Possible Reference to String Resource ID=00001: "Configuration file
RNSETUP.CFG is missing or corrupted. Setu"
|
:1000A14B BB01000000    mov ebx, 00000001
:1000A150 894C2410      mov dword ptr [esp+10], ecx ;various inits of vars
:1000A154 894C2428      mov dword ptr [esp+28], ecx ;used to generate the
:1000A158 8944241C      mov dword ptr [esp+1C], eax ;magic number...
:1000A15C 89442420      mov dword ptr [esp+20], eax
:1000A160 8D7C241C      lea edi, dword ptr [esp+1C]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A1CA(C)
|
:1000A164 8BC6          mov eax, esi
:1000A166 33D2          xor edx, edx

* Possible Reference to String Resource ID=00010: "Configuring system..."
|
:1000A168 BD0A000000    mov ebp, 0000000A
:1000A16D F7F5          div ebp
:1000A16F 80FA06        cmp dl, 06 ;check if code digit <>6
:1000A172 751E          jne 1000A192
:1000A174 837C242802    cmp dword ptr [esp+28], 00000002 ;is there more than
                                                        ;2 6 in your code ?
:1000A179 0F8D84000000  jnl 1000A203 ;if yes beggar off !
:1000A17F 8B542428      mov edx, dword ptr [esp+28]
:1000A183 0FBEC1        movsx eax, cl
:1000A186 42            inc edx
:1000A187 8907          mov dword ptr [edi], eax
:1000A189 89542428      mov dword ptr [esp+28], edx ;it's a count of occurences of 6.
:1000A18D 83C704        add edi, 00000004
:1000A190 EB27          jmp 1000A1B9

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A172(C)
|
:1000A192 8B6C2410      mov ebp, dword ptr [esp+10]
:1000A196 0FBEC2        movsx eax, dl
:1000A199 03E8          add ebp, eax
:1000A19B 80FA06        cmp dl, 06 ;check for 6 again !
:1000A19E 896C2410      mov dword ptr [esp+10], ebp
:1000A1A2 7E02          jle 1000A1A6
:1000A1A4 FECA          dec dl ;hex code -1 if above
                                ;used to generate the number
                                ;with a multiplication later.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A1A2(C)
|
:1000A1A6 0FBED2        movsx edx, dl
:1000A1A9 0FAFD3        imul edx, ebx
:1000A1AC 8B442414      mov eax, dword ptr [esp+14]
:1000A1B0 8D1CDB        lea ebx, dword ptr [ebx+8*ebx] ;a=a*8+a var used in the algo...
:1000A1B3 03C2          add eax, edx
:1000A1B5 89442414      mov dword ptr [esp+14], eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A190(U)
|
:1000A1B9 B8CDCCCCCC     mov eax, CCCCCCCD ;this is no encryption
:1000A1BE F7E6           mul esi ;provided to check your code
:1000A1C0 C1EA03         shr edx, 03 ;digit by digit, stored in edx (see with sice)
:1000A1C3 FEC1           inc cl
:1000A1C5 8BF2           mov esi, edx
:1000A1C7 80F90A         cmp cl, 0A ;0x0a stands for lenght of your code
:1000A1CA 7C98           jl 1000A164
:1000A1CC 8B4C2410       mov ecx, dword ptr [esp+10]
:1000A1D0 8B048D30410110 mov eax, dword ptr [4*ecx+10014130] ;very important, look in
:1000A1D7 8B0C8D50420110 mov ecx, dword ptr [4*ecx+10014250] ;2 tables with an index
                    ; to help ecx stores the sum of all the digits 1+1+0+6 etcc...
:1000A1DE 3BC1           cmp eax, ecx
:1000A1E0 8BD0           mov edx, eax
:1000A1E2 7C02           jl 1000A1E6
:1000A1E4 8BD1           mov edx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A1E2(C)
|
:1000A1E6 3BC1          cmp eax, ecx
:1000A1E8 7F02          jg 1000A1EC
:1000A1EA 8BC1          mov eax, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A1E8(C)
|
:1000A1EC 3954241C      cmp dword ptr [esp+1C], edx ;esp+1c contains the index of
                                                ;first '6' encountered in your code...
:1000A1F0 7511          jne 1000A203 ;must be egal to table value,otherwise beggar off!
:1000A1F2 39442420      cmp dword ptr [esp+20], eax ;idem for the second 6.
:1000A1F6 750B          jne 1000A203
:1000A1F8 8B442414      mov eax, dword ptr [esp+14]
:1000A1FC 3DBFEA2101    cmp eax, 0121EABF ;not the final check but made to confuse you !
:1000A201 7604          jbe 1000A207 ;if greater, beggar off,first purpose of algorythm.

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:1000A179(C), :1000A1F0(C), :1000A1F6(C)
|
:1000A203 8B442418      mov eax, dword ptr [esp+18];sets eax to 0 and beggar off.

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1000A201(C)
|
:1000A207 5F            pop edi ;good if you land here !
:1000A208 5E            pop esi ;but that's not finished yet.
:1000A209 5D            pop ebp
:1000A20A 5B            pop ebx
:1000A20B 83C414        add esp, 00000014
:1000A20E C3            ret

Ok we're almost finished.Now you've got in eax the value generated by the
algo that will be tested in the second call that we have there:


* Referenced by a CALL at Addresses:
|:10009DB4 , :10009EC3 , :10009F46 
|
:10009FB0 8B442408 mov eax, dword ptr [esp+08]
:10009FB4 50 push eax

* Possible Indirect StringData Ref from Data Obj ->"PlayerPlus"
|
:10009FB5 68E0400110    push 100140E0 ;this is used as an index for the final check.
:10009FBA E821000000    call 10009FE0 ;not very important...
:10009FBF 83C408        add esp, 00000008
:10009FC2 85C0          test eax, eax
:10009FC4 7416          je 10009FDC
:10009FC6 8B4C2404      mov ecx, dword ptr [esp+04]
:10009FCA 8B5008        mov edx, dword ptr [eax+08]
:10009FCD 3BCA          cmp ecx, edx
:10009FCF 720B          jb 10009FDC
:10009FD1 3B480C        cmp ecx, dword ptr [eax+0C] ;this is the final check
                                            ;it looks if the generated number
                                            ;is greater than 9999999, this is
                                            ;a fixed value.
:10009FD4 7706 ja 10009FDC ;beggar off !

* Possible Reference to String Resource ID=00001: "Configuration file
RNSETUP.CFG is missing or corrupted. Setu"
|                                           ;an example of windasm trash, if ida
|                                           ;was more window based...sic...
|
:10009FD6 B801000000    mov eax, 00000001 ;if you're here so everything is OK and
                                            ;your code is fine
:10009FDB C3 ret


Why do you have to write a Keygen ?

Because If you patch this code,it will install realplus ok but when the
program will load it will see that the code you typed is wrong and will stay
in demo mode. So you could check to patch this crap again but believe me, it
will not work when you will automatically upgrade without asking you anything!
I know this is difficult work so I provide you my keygen in C so you will
study it and maybe improve it.

MY KEYGEN IN C++ SOURCE :
Courtesy of +TsehP from Paris 24/08/1998

#include 
#include 
#include 
#include 
#include 
#include 


#include 
int tab1[200] =
{6,6,6};


int tab2[200] =
{6,6,6};

// a "satanic" way to make lamerz' life less easy... try to compile THIS! >:-)

main()

{ 
srand( (unsigned)time( NULL ) );
unsigned long val=0,a=1,sum=0,c;
char key[20],trav[20],*e,buf[2],rep[2];
int i,k=0,d=0,r=0,g,pos1,pos2,nb6=0,al,ok=0,res6;

cout << "Realplayer plus g2 keygenerator" << endl; cout << " By +TsehP " << endl; cout << "To find it, try ftpsearch with " << endl; cout << "R32PPG2xxx as a file... " << endl; cout << "or download on www.real.com... " << endl; cout << " Finished the 24/08/1998 " << endl; cout << endl; cout << "Press Return to generate a serial." << endl; gets (key); a="1;" do { val="0;a=1;sum=0;c=0;i=0;k=0;d=0;r=0;g=0;pos1=0;pos2=0;nb6=0;al=0;res6=0;" for (i="1;i<11;i++)" { do { al="rand()" % 10; } while (al!="0" & al!="1)" ; _itoa (al,buf,10); strncpy (key+i-1,buf,1); *(key+i)="0x00;" }; for (i="1;i<3;i++)" { do {al="rand()" %10;} while (al="=0" & al="=10" & al="=res6);" _itoa (6,buf,10); strncpy (key+al,buf,1); res6="al;" } for (i="1;i<11;i++)" { strcpy (trav,key); e="(trav+(11-i)-1);" *(e+1)="0x00;" val="atoi" (e); c="val;" if (c="=6" & nb6="=0)" {pos1="i;nb6++;}" else if (c="=6" & nb6="=1)" {pos2="i;nb6++;};" if (c!="6)" { sum+="c;" if (c>6) c-=1;
d=c*a;
a=a*8+a;
r=k+d;
k=r;
};
};
d=tab1[sum];
g=tab2[sum];
if (r<<9999999) { printf ("Et voila !!!\n"); strcpy (trav,key); if ((d+1)!="pos1){strncpy" (trav+10-(d+1),key+10-pos1,1);strncpy(trav+10-pos1,key+10-(d+1),1);}; strcpy (key,trav); if ((g+1)!="pos2){strncpy" (trav+10-(g+1),key+10-pos2,1);strncpy(trav+10-pos2,key+10-(g+1),1);}; printf ("Enter this serial : "); puts (trav); cout << "Do you want another one ? (Y/N)" << endl; gets (rep); if (*rep="='n')" ok="1;" } else {r="0;};" } while (!ok); return 0; };>                                 Final Notes 


Legal stuff : This is made for educationnal purpose, I'm not responsible if
this is used to avoid paying for this program, I'm not either responsible of
what I write, of me and Monica Lewinsky loss of virginity . 


Courtesy of +TsehP from Paris 24/08/1998



(c) +TsehP 1998.
WARNING: this tutorial is published for EDUCATIONAL PURPOSES only! Nobody except you is responsible for what you do with the things you read here. Also, if you intend to use shareware programs for a period longer than the allowed one remember that you have to BUY them!