An introduction to code generation routines: reversing Teleport Pro v1.29
The last beginners approach on fravia's site
Not Assigned
14th May 1998
by Prophecy
Courtesy of Fravia's page of reverse engineering
slightly edited
by fravia+
Prophecy thought this as a "beginner" essay, which is true... it is nevertheless a good essay. Yet this is THE LAST beginner essay I will ever publish on my site (unless the techniques change radically, which I doubt :-). Yes, I will not publish any "beginner" essays anymore. In fact I believe there is now enough material on my (and some other) pages to help anyone to grow from beginner to intermediate... if the reader has at least a little will, that is. Beginners have had enough. Basta, finito, pass over to the next stage: it's about time to draw a line IMO (correct me if you reckon I'm wrong). This essay is definitely NOT an "useless" beginner essay btw, it's an interesting article for any beginner reversers ans protectors alike... and don't snarl at beginners (I can't stand snotty 'elite' crackers the beginners of today are the masters of tomorrow (yet I'm decided... I won't publish any "beginners" essay any more :-) Enjoy Prophecy's good work!
There is a crack, a crack in everything That's how the light gets in
(x)Beginner ( )Intermediate ( )Advanced ( )Expert

This essay illustrates how a simple code generation routine based upon the
user's name works, and describes a clear approach to reversing this target.
Many of the techniques described in this essay can be used to reverse other
targets... this essay was written by a beginner, for beginners.

An introduction to code generation routines: reversing Teleport Pro v1.29
The last beginners approach on fravia's site
Written by Prophecy

Table of contents: (use this once you've already read through the essay and you
only want to reference specific sections)

About the target...
Tools required...
Target's URL...
Let's get started...
Setting up SoftIce...
The main body of the essay...
The C source code for the key generator...
Final words...

Note:  I can be contacted at:


This essay is dedicated to fravia, the #cracking4newbies crew, and to those
who have contributed to fravia's academy...	

I am very grateful to all the people who have written essays, and shared their
knowledge of cracking with everyone else.  Now that I've gained a bit of
experience, I feel that I am now ready to contribute a small something back
to the cracking community.

The contents of this essay is aimed at beginners, and you shouldn't have much
trouble following it, just don't go too fast, and make sure you read everything!

I'm going to show you how the target generates the serial numbers so that you
can work out a serial number for your name and so that you can make a key
generator.  What I hate about a lot of essays is the cracker who writes them
assumes you know the same amount as him/her, leaving beginners like me and you
confused and annoyed.  Throughout this essay, I have explained everything to
the best of my ability (remember I'm only a beginner too and I can't explain


We are going to reverse Teleport Pro 1.29 (Build 622).  This is a nice app which
lets you download entire web pages like the entire academy at etc...
the shareware version, however, is crippled because it only lets you download
up to 500 threads, hence our need to crack it.

Tools required
Numega SoftIce (I use v3.22)
C compiler if you want to modify my source code to make your own key generators

Target's URL/FTP
You can obtain the target from: OR

Program History
History is not relevent here.

Okay!  Let's get started by having a look round the target...:

Before rushing headfirst into SoftIce, let's have a little look round the
target.  First of all, load it up and click on Help.  Ahh, a 'register...'
option... let's check it out.  Looks like a pretty standard name and serial
number protection.  Okey, let's investigate: click on the 'Mail/Email/Fax'
button.  First, you'll notice the company field is optional, so we can assume
that the target doesn't use that field to generate the serial number, and we can
leave that field blank.  Ok, now click on 'Save to Disk' button... what does it
say?  It says "Please enter a name because we need it to generate your serial
number!" (suprise, surprise).  Ok, enter a small name like bob, and click 'Save
to Disk'.. what does it say now?  "Our name is too short".. hmm okay, we soon
determine that the minimum length name is 5 letters long.  So our snooping has
led us to these conclusions: our name must be at least 5 letters long and is
used to generate the code, and we can leave the company field blank.

Setting up SoftIce...: Okey, if your SoftIce is already sweetly set up, you can skip this section. When SoftIce loads with it's default values, it is in a sorry state, you only get 25 lines of code, the Registers window isn't there, and a whole lot of other stuff is missing remedy this, I suggest you use my settings. To use my settings open up the winice.dat file in the SoftIce directory. You should see (round about line 20) INIT="X;". Replace that with the two INIT lines below... if you have INIT="a whole lot of stuff like above" then chances are it's already ok, and you don't have to replace them. You'll need to restart your computer for the changes to take effect. INIT="lines 60;code on;wd 13;wc 25;wr;ww 6;wl;dex 1 ss:esp;faults off;" INIT="altkey ctrl d;watch es:di;watch eax;watch *es:di;set mouse 3;cls;X;" So what does all this stuff do you ask? Here's a quick rundown: lines 60 - sets SoftIce to use 60 lines code on - displays the hexidecimal byte code next to the disassembled listing wd 13 - enables the data window and sets it to 13 lines wc 25 - enables the code window and sets it to 25 lines ww 6 - enables the watches window and sets it to 6 lines watch bla - displays the value of bla in the watch window set mouse 3 - puts mouse speed on full (yeeehaaaa) cls - clears the screen faults off - means when your computer crashes, SoftIce doesn't kick in (you don't want faults ON because when SoftIce pops up because of a fault it won't let you out again) altkey ctrl d - this is the default value for switching to softice - set it to whatever you want dex 1 ss:esp - not quite sure :) Note: sometimes, when you switch from SoftIce back to Windows95 it crashes, and displays a whole bunch of vertical lines on your monitor... this is probably due to incompatibility with your video card and can be fixed by running SoftIce in a window. Tu run SoftIce in a window, go to the the SoftIce from the startup menu and click 'Display Adapter Setup', then check the 'Universal driver' box. You can then configure (in SoftIce) the number of lines by typing lines x, where x ranges from 25-128 and width y, where y ranges from 80-160. You can set the font by typing set font n, where n = 1, 2 or 3. If you use SoftIce in a window, you should modify the winice.dat INIT lines with the new settings... (see the readme.txt file in the \softice directory for more details). One more thing that's important, is that you need to export the functions from the standard windows functions, otherwise you won't be able to breakpoint on anything. To make sure the functions of these libraries are exported to softice, load up the winice.dat file and go down near the bottom of the file until you see ;*** Examples of export symbols that can be included for Windows 95 ***. Okey, now remove the semi-colon from in front of the the kernel32.dll and user32.dll export statements, and make sure the path points to the right windows system directory. Now, you'll have most of the main functions available to you, another good one to export is advapi.dll. Okey, let's test our SoftIce setup.. hit Ctrl-D, you should see (rough sketch): +------------------------------------------------------------------------------+ | EAX=... This is the registers window, activate it | | EDI=... by typing wr | +------------------------------------------------------------------------------+ | es:di=... This is the watch window, activate it by typing ww. To watch | | something, type watch bla, eg watch eax | +------------------------------------------------------------------------------+ | xxxx:yyyyyyyy 01 02 03 04 05 06 07 08-09 10 11 12 13 14 15 16 ...............| | xxxx:yyyyyyyy 01 02 03 04 05 06 07 08-09 10 11 12 13 14 15 16 ...............| | | | This is the data window, activate it by typing wd. It is here that you can | | see what's stored in memory. | +------------------------------------------------------------------------------+ | 0028:C000A010 7902 JNS C000A014 (JUMP )| | 0028:C000A012 33C0 XOR EAX,EAX | | 0028:C000A014 83E81F SUB EAX,1F | | | | This is the code window, where the assembly commands the target is executing | | are displayed. Activate this window by typing wc. | +------------------------------------------------------------------------------+ |:< type your commands here > | | | | Well this is where you type your commands, simple huh? | +------------------------------------------------------------------------------+ (I got a lot of this information from Mammon_'s excellent SoftIce tutorial, which is availabe at Anyway, now we're ready to rock'n'roll! Let's break into SoftIce and see what happens...: (Some crackers would prefer to 'dead list' the target first using w32dasm but I'm rash, and want to get straight to the action. If I fail with SoftIce, then I have a look round with w32dasm, but I always prefer the more eloquent solution of a valid serial number rather than a patch that changes '74' to '75'.) We want to work out how the target generates the serial number right? And we know there's a good chance that our name is going to be used in the process (unless the author is lying). It should be noted that finding the serial number for the name you entered isn't too hard (it only took me 5 hours hehe), but we're not interested in that, we want to get to the bottom of the code generating routine and see how this target really works, then we can write a key generator, and our curiousity will be appeased and the world will live happily ever after. Okey then, let's enter a name in the Name box, eg Prophecy, and a bogus code, eg 666777888. Now we need to set a breakpoint in SoftIce so that we pop into SoftIce at a point close to where the target is going to generate the code and compare it to our bogus code. Okay, let's pop into SoftIce (Ctrl-D or whatever) and set a breakpoint: BPX getwindowtexta. This means SoftIce will pop up on execution of the getwindowtexta command, which is a common command a target uses to read info supplied by a user (eg name and (bogus) serial number). Okey, hit < F5 > to go back to the target and click OK. Bang! we're in SoftIce. Press < F11 > to trace the call back to the target. Now, have a careful look at the registers...: EAX=8 (this is the length of our name) Hrmm, so there's not much going on round here. Let's find our name in memory: type s 0 l ffffffff "Prophecy". Right, you should see your name in the data window like so: 013F:00FB266C 50 72 6f 70 68 65 63 79-00 00 00 00 00 00 00 00 Prophecy........ ^^^^^^^^^^^^^ (these numbers will probably be different to yours) So the address of my name is fb266c. (there may be more than one instance of your name in memory, typing s will display the next match in memory. If you are having trouble finding your name, try typing a name that you KNOW won't be in memory eg PrinceCharles, then repeat the search process). Okey, now we want SoftIce to break whenever the target accesses the memory containing your name, to do this, we must use the bpr (break when a range of memory is accessed) command by typing: bpr fb266c fb266c+8 rw. Since we're interested in seeing how the target manipulates our name to generate the serial number, we no longer need the the breakpoint on getwindowtexta. To get rid of it type bc 0. Now let's continue and see what happens to our name... press < f5 > and you should see this: (Note that throughout the assembly listing, comments that begin with '?' are ones I'm not sure about, but which I think are a possibility). 0137:BFF7117E F2AE REPNZ SCASB ;?finds length of your name 0137:BFF71180 83C8FE OR EAX,-02 ;? 0137:BFF71183 2BC1 SUB EAX,ECX ;eax=eax-ecx 0137:BFF71185 5F POP EDI ;pops edi from the stack 0137:BFF71186 59 POP ECX ;pops ecx from the stack 0137:BFF71187 C9 LEAVE ;let's leave this call Okey, a bit of 'zen' (intuition) tells me that this part of the code isn't very interesting (how do I do suspect it isn't interesting? Well, after looking at lots of lines of code, you can begin to 'feel' the code, and draw accurate assumptions from it- you will be able to as well, just go through lots of essays and tutorials). So lets move on: press < f10 > to step past the REPNZ SCASB line until the OR EAX,-02 line is selected, then press < f5 > to continue: 0137:004415E8 80240800 AND BYTE PTR [ECX+EAX],00 ;? 0137:004415EC C20400 RET 0004 ;return from the call Well this isn't very interesting either (you can always have a snoop round yourself by press < f10 > to trace down. Anyway, don't despair, the good bit is coming right up, let's hit < f5 > again and we end up here: ----------------+ | (Now, if you're pretty sharp, you'll notice something I missed: hint: it's in | one of the registers. You found it? Yep, it's that EBP register alright! | Not convinced? Type ?ebp, and what value is it? Our bogus code... okey, so | keep an eye on ebp.) | | /* start of 'dummy' code generating routine */ <-- ignore this for the moment | | 0137:004287D0 8B01 MOV EAX,[ECX] <-----------------------+ ^ This line moves the content of ECX ([ECX]) into EAX. What's [ECX]? Type d ecx: 013F:00FB266C 50 72 6f 70 68 65 63 79-00 00 00 00 00 00 00 00 Prophecy........ Our name... hmmm, suspicious. It's important to understand how [ECX] gets transferred to EAX: EAX consists of 8 numbers, made up of 4 bytes. A byte is just the pairs of numbers you see in the data window, eg 50, 72 and 6f are examples of bytes. Now, EAX must read 4 bytes from [ECX]. It reads these in reverse order starting at 70, then 6f, 72 and finally 50, giving the new value of EAX=706f7250 (which you can see by looking at the EAX value in the registers window). So now EAX is equal to the first four letters of our name. 0137:004287D2 BAFFFEFE7E MOV EDX,7EFEFEFF ;edx=7efefeff 0137:004287D7 03D0 ADD EDX,EAX ;edx=edx+eax ^ EDX is now equal to (7efefeff (a possible magic number?) plus EAX). 0137:004287D9 83F0FF XOR EAX,-01 ^ letters of our name get XORed with -01, result is stored in EAX. 0137:004287DC 33C2 XOR EAX,EDX ^ letters of our name get XORed with (possible magic number+EAX). 0137:004287DE 83C104 ADD ECX,04 ^ ECX = ECX+4 , meaning that we have already read 4 bytes of our name, and next time it will start reading at the 5th byte (letter) of our name. 0137:004287E1 A900010181 TEST EAX,81010100 ^ finished encrypting our name? 0137:004287E6 74E8 JZ 004287D0 ;yes/no 0137:004287E8 8B41FC MOV EAX,[ECX-04] ^ Hrmm EAX has now been overwritten by the content of ECX-4... what was the point of XORing EAX in the first place? 0137:004287EB 84C0 TEST AL,AL ;not quite sure what 0137:004287ED 7432 JZ 00428821 ;all this stuff does 0137:004287EF 84E4 TEST AH,AH ;but it basically checks 0137:004287F1 7424 JZ 00428817 ;to see how far thru the 0137:004287F3 A90000FF00 TEST EAX,00FF0000 ;encrypting of our name 0137:004287F8 7413 JZ 0042880D ;the target is. 0137:004287FA A9000000FF TEST EAX,FF000000 0137:004287FF 7402 JZ 00428803 0137:00428801 EBCD JMP 004287D0 0137:00428803 8D41FF LEA EAX,[ECX-01] ;let eax=[ecx-1] 0137:00428806 8B4C2404 MOV ECX,[ESP+04] ^ Type D esp+4 and you'll see something like: 013F:006FF488 6C 2C FB 00 bla bla bla... now doesn't that fb2c6c look familiar? Yep, it's the location of our name (remember, stuff is read in into registers in blocks of 4 bytes, starting from right to left). 0137:0042880A 2BC1 SUB EAX,ECX ^ This calculates the length of our name and stores the result in EAX 0137:0042880C C3 RET etc, etc... /* end of 'dummy' code generating routine */ <-- ignore this for the moment Well, anyway, I'm getting pretty suspicious by now because all sorts of stuff is happening to our name. At this point, I traced carefully through the code for ages, noting down what was going on. This is pretty slow and hard work, but it's good practice for a beginner like me and it also ensures I don't miss any important points. Okey, you do the same: hit < f10 > and slowly trace the code, you eventually hit a RET command and end up here: 0137:00422FCE 59 POP ECX ;pop ecx from the stack 0137:00422FCF EB02 JMP 00422FD3 0137:00422FD1 33C0 XOR EAX,EAX 0137:00422FD3 83F805 CMP EAX,05 ^ Compares length of our code (EAX) with 5 0137:00422FD6 7304 JAE 00422FDC ^ Jump if EAX is greater than or equal to 5... remember our snooping? We already knew our name had to be 5 or greater... 0137:00422FD8 33C0 XOR EAX,EAX ;set eax=0 0137:00422FDA EB2B JMP 00423007 0137:00422FDC BEA4E4FE5D MOV ESI,5DFEE4A4 ^ move 5dfee4a4 (another possible magic number?) into ESI 0137:00422FE1 33DB XOR EBX,EBX ;set ebx=0 0137:00422FE3 85FF TEST EDI,EDI ;?did we enter a name? ^ Have you checked what EDI is? (Type D edi)... it's our name! 0137:00422FE5 7409 JZ 00422FF0 ;yes/no 0137:00422FE7 57 PUSH EDI ^ This pushes our name to a function. It is important to know how functions work: (some) functions require parameters. For example, consider this function here: sum(a,b). This function gets two numbers, a and b and adds them. a and b are the parameters of the function, sum. Now in assembler this would look like: PUSH a ;eg PUSH 30 PUSH b ;eg PUSH 12 CALL sum ;this would actually be some memory location which points to the ;function sum Anyway, now that you've got the general idea you can see the importance of the above PUSH EDI: 0137:00422FE8 E8C3570000 CALL 004287B0 ^ This calls a function, which has our name as it's only parameter! Okey, so this function could be important, so we want to step into it and investigate: select the CALL 004287B0 line and hit < f8 >. Now let's see where we end up: 0137:004287B0 8B4C2404 MOV ECX,[ESP+04] ^ set up ECX so that it points to our name 0137:004287B4 F7C103000000 TEST ECX,00000003 ;? 0137:004287BA 7414 JZ 004287D0 0137:004287BC 8A01 MOV AL,[ECX] ^ move first byte of our name into AL 0137:004287BE 41 INC ECX ;ecx=ecx+1 0137:004287BF 84C0 TEST AL,AL ;?did we enter a name 0137:004287C1 7440 JZ 00428803 ;yes/no 0137:004287C3 F7C103000000 TEST ECX,00000003 ;?finished encrypting 0137:004287C9 75F1 JNZ 004287BC ;our name yet? yes/no. 0137:004287CB 0500000000 ADD EAX,00000000 ;seems pretty pointless. 0137:004287D0 8B01 MOV EAX,[ECX] ^ Move the first 4 letters of our name into EAX Well now, what have we here? Looks like we're back to the start of the 'dummy' code generating routine... I call this the 'dummy' code generating routine because it doesn't seem to have a purpose. I think that the programmer may have put it in to send a naive cracker down the wrong track (fat chance hehe)... anyway, maybe I missed the subtle point... let's continue: 0137:004287D2 BAFFFEFE7E MOV EDX,7EFEFEFF 0137:004287D7 03D0 ADD EDX,EAX 0137:004287D9 83F0FF XOR EAX,-01 . . 0137:0042880C C3 RET ;let's leave the 'dummy' routine Okay, perserverence is the key to success, so let's forge on, hit < f10 > until you reach RET, and you end up here: 0137:00422FED 59 POP ECX ;pop ecx from the stack 0137:00422FEE EB02 JMP 00422FF2 0137:00422FF0 33C0 XOR EAX,EAX ;set eax=0 0137:00422FF2 83C0FC ADD EAX,-04 ^ ?this is probably used to keep a check on how far through the 'dummy' (or even the real code) generating routine the target is... 0137:00422FF5 3BD8 CMP EBX,EAX ^ EBX was a counter used in the 'dummy' routine. ?Compares to see if we are finished the routine yet... 0137:00422FF7 730C JAE 00423005 ;yes/no 0137:00422FF9 33343B XOR ESI,[EDI+EBX] ^ Okey, now this looks interesting! ESI (a possible magic number remember?) is XORed with the contents of EDI+EBX and the result is stored in ESI... now what is [EDI+EBX]? type d edi+ebx... well, well, well, if it isn't our name. We'll have to keep a close eye on our friend ESI... now keep tracing and you'll end up here: 0137:00422FE3 85FF TEST EDI,EDI ;?did we enter a code? 0137:00422FE5 7409 JZ 00422FF0 ;?yes/no 0137:00422FE7 57 PUSH EDI ;push our name to the stack 0137:00422FE8 E8C3570000 CALL 004287B0 ^ Well, no prizes for guess what routine this CALL is to... yep, our 'dummy' code generating routine. Well at this stage you can just step over this routine rather than into it, but you'll need to disable your breakpoint on your name which can be done by typing bd 1 (otherwise you'll just pop into the routine anyway, because our name is being accessed by it). Okey, now that you've stepped over the routine (or you can step into it if you want, it'll just take longer- and that's the way I did it, because I guess I wasn't thinking hard enough, and I was just methodically stepping into all the interesting calls) you should reenable the breakpoint on your name by typing be 1. 0137:00422FED 59 POP ECX 0137:00422FEE EB02 JMP 00422FF2 0137:00422FF0 33C0 XOR EAX,EAX ;set eax=0 0137:00422FF2 83C0FC ADD EAX,-04 ;eax=eax-4 0137:00422FF5 3BD8 CMP EBX,EAX ;finished dummy routine? 0137:00422FF7 730C JAE 00423005 ;yes/no 0137:00422FF9 33343B XOR ESI,[EDI+EBX] ^ Ok, now we end up here, which is again interesting. Typing d edi+ebx reveals that our name has now been shifted accross one and so the contents of EDI+EBX are the letters 2-5 inclusive or our name, namely 'roph'. So ESI is XORed with the letters 2-5, and the result is stored in ESI... do we sense a pattern here? I think so! The pattern seems to be that our ESI starts out as the magic number 5dfee4a4, it then gets XORed with the first 4 letters of name, and the result is stored in the new ESI. Then the new ESI is XORed with the letters 2-5 of our name, (and then 3-6, 4-7, 5-8...?). Anyway, for each XOR ESI, [EDI+EBX], the 'dummy' routine is called. Okey, let's confirm our theory, by continuing to trace downwards... (remember if you see a PUSH EDI, CALL 004287B0, you don't need to bother stepping into it, just don't forget to disable the breakpoint of your name and reenable it after you've stepped over the call)... okey, we reach this interesting point in the code: 0137:00422FF9 33343B XOR ESI,[EDI+EBX] ^ XOR ESI with letters 3-6 of our name, which confirms our theory doesn't it? 0137:00422FFC F6C340 TEST BL,40 ;? 0137:00422FFF 7401 JZ 00423002 0137:00423001 43 INC EBX 0137:00423002 43 INC EBX ^ this adds 1 to EBX so that at the next XOR ESI,[EDI+EBX] our name has been shifted accross 1. Ok, so by now things are becoming pretty obvious... keep tracing but be careful, as we are nearing the end of our name, you don't want to miss any important bits! Ok, now we hit yet another XOR ESI,[EDI+EBX], this time the contents of EDI+EBX are letters 4-7 of our name. Well, let's keep tracing... hey, we've reached new section of code: 0137:00423005 8BC6 MOV EAX,ESI ^ ESI, which by now, seems like it has a high chance of being the 'valid' code is moved into EAX 0137:00423007 5F POP EDI ;pop edi off the stack 0137:00423008 5E POP ESI ;pop esi off the stack 0137:00423009 5B POP EBX ;pop ebx off the stack 0137:0042300A C3 RET ;let's get outta here!! Well, we leave that routine and pop up here: 0137:00422713 3BE8 CMP EBP,EAX ^ Well, well, well what have here? Do you remember what EBP was? If you can't, check it out now... type ?ebp, yup, it's our bogus code, and we're pretty sure it's being compared to the 'valid' code! (Well, this programmer's efforts have been substantially minimized by leaving an unencrypted 'bogus' code lying around, and then comparing it with what we believe is the valid one... the programmer should have been smarter and first of all encrypted our bogus code, then encrypted the valid code and then compared the two encrypted codes... but no, he was too lazy, and it cost him! < evil laughter >). (Note that at this point, you can simply type ?eax and this would display what we believe is our valid code (for me, I got 1139597721), and a cracker who was just after a serial number could have quickly obtained it from here, however, we were interested in disecting the code generating routine to bits, and eventually writing a key generator (which is a much better and more worthwhile exercise than quickly rushing in and finding the serial number!) 0137:00422715 59 POP ECX 0137:00422716 750F JNZ 00422727 ^ if the codes don't match, then go to 'naughty cracker', otherwise continue. Anyway, I bet your dying to see if EAX is really the valid code, so hit < F10 > until you reach the JNZ 00422727. Okay, we want to skip the jump, so that we can check if that EAX is the real code. How do we do this? Okay, if you notice in the upper right part of the register window, we have a small 'z', this means that the zero flag isn't set, (ie the two codes didn't match)... we want to force the flag so that we fool the target into thinking the codes matched... we do this by typing r fl z. Okey, now comes the test, let's clear all the breakpoints we've set by typing bc * and leave SoftIce by hitting < f5 >... and we're back in Teleport Pro and *boom* "Thankyou, your copy of Teleport Pro is now registered blablabla". Yeehaa! Okey, so let's recap on how the code is generated using our name: We start off with a magic number (5DFEE4A4) and this gets XORed with the first 4 letters of our name and the result is stored in ESI. Then ESI is XORed with the letters 2-5 of our name and a new value is stored in ESI. This process keeps going until letters (n-4)-(n-1) have been read, where n represents the length of your name. (Try entereing a name of different length to the one you used through out the essay, and you'll see this is indeed the case). So now we know exactly how the valid code is calculated based upon our name. I have written a key generator in C for the target, and you are free to use and modify my source code for your own key generators! (I apologize in advance to the C gurus out there, because my code is probably not written in the best of ways (hey, I'm only a beginner at C too), however, I find that when you try and write efficient C, it becomes rather cryptic and hard to follow, and because this essay is aimed at beginners, I wanted it as easy as possible to follow... So, without further ado, here is my C source code, fully commented so that it may be easily understood: --------------------------------start tprokgen.c-------------------------------- /* Your first keygen... yeehaa! * * This code can be used by anyone except Bill GAYtes (haha)... */ /* Note: because this proggie uses 32bit unsigned long integers, you might not * have any luck get a DOS executable going because DOS is only 16 bit (there * probably is a way, but I didn't find it), so you'll have to compile it to * run under win32... good luck! */ #include <stdio.h> /* import the standard i/o library */ int main() { /* start of key generator */ /* Set up the variables... * your_name is the string where your name is stored (up to 508 characters (remember, C terminates all strings by a null character). (509 is the minimum length string that C compilers must support.. hehe, damn I'm a geek) * *p is a pointer to your_name * length_of name is self explanatory, as is your_code * buffer is where the characters making up the user's name are read into (much like EAX, ECX etc... * i,j,k are counter variables used in the loops */ unsigned char your_name[509], *p; unsigned long int buffer, your_code; int i,j,k,length_of_name; /* Initialize the variables... * your_code starts off as the "magic number" but quickly changes as it gets XORed with the characters of the your name * set initial length of name = 0 * set p to point to your_name * the sum starts off = 0 * set up counter variables so that the code is calculated correctly (these values become more apparent as you move further on) */ your_code=0x5dfee4a4; length_of_name=0; p=your_name; buffer=0; i=3; j=4; k=0; /* Introductory blurb etc */ printf("U─────── ░ ─── ▄ ─────── ░ ────────────┐\n"); printf("_▀UU▓▀UUU▓▀UU▓▀UU▓▄ ▄▓U▓ ▀▓UU▓▀UUU▓▀ 3\n"); printf("3 ▀░ UUU▓ U░ UUU▀▓▄ UUU▓ UUU▓ UUU▓ 3\n"); printf("3 ░UUU▓ ░UUU UUUUU▓ ░UUU▓ UUU▓ 3\n"); printf("3 ▄▓UUU▓▄ ▄▓UUU▓▄ ▀▓UU▓▄▓UUU▓▄▓UU▓▄ 3\n"); printf("A───────────────────── ▀▀▓ ────────────U\n"); printf("\nKey Generator for Teleport Pro v1.29 (Build 662)"); printf("\nWritten by Prophecy [TNO]\n\n"); /* Get the name */ tryagain: printf("Please enter your name: "); /* Store your name in your_name */ gets(your_name); /* Calculate the length of your name... \0 represents the NULL character which is at the end of any C string, and hence used to find length of strings...*/ while (*p != '\0') { p++; length_of_name++; } p=your_name; /* Set p so that it points back to the start of your_name */ /* Our name must be at least 5 characters long remember? If your name isn't at least 5 characters long, then you get to enter your name again */ if (length_of_name 5) { printf("Your name must be at least 5 characters long! Try again... \n\n"); goto tryagain; /* Enter your name in again */ } /* Ok, here starts the code generation routine... there are two while loops, an outer one, and an inner one. The outer one checks to see if we're one away from the end of the string, while the inner one reads in the characters of the name so that the code can be generated. */ while (j <= length_of_name-1) /* start of outer loop */ { while(i >= k) /* start of inner loop */ { /* The buffer works like this: it starts off as 0, then you add to it the first char of your name (p[0]). Then you multiply it by 0x100 which creates space for the next char to be added into to the buffer. This repeats 4 times until the first 4 chars (chars 1-4) have been read in reverse order (this is how numbers are stored in registers (EAX etc) remember?). The buffer is then XORed as described in the essay. Then k increases by 1, and i is increased by j+4, and the chars 2-5 are read and XORed. This keeps going until chars (n-4)-(n-1) have been read, where n represents the length of your_name. */ buffer=(buffer*0x100LU) + p[i]; /* read in the characters of your name */ i--; /* decrease i by 1 */ } /* end of inner loop */ your_code=(your_code^buffer); /* XOR your_code with the buffer */ j++; /* increment j */ k++; /* increment k */ i=j+4; /* increase i */ buffer=0; /* reset the buffer to 0 */ } /* end of outer loop */ /* Print the code to the screen */ printf("Your code is: %u ",your_code); return 0; /* Tells environment that the programme finished normally */ } /* end of key generator */ ---------------------------------end tprokgen.c--------------------------------- Credits: Well folks, that's about it, but of course, an essay can't be complete with all the necessary credits...: These people (or the stuff they've written) have helped me out a lot (in no particular order): natzgul, Y, cruehead, gij, corn2, niabi, aescalapius, tkc, mammon_, the contributers to fravia's academy, the #cracking4newbies crew and probably a whole bunch of others I missed... These sites were also of great help:

Final Notes

I hope that this essay has helped you and has been easy to follow... I certainly
went to great lengths to ensure it was as simple and as error-free as possible.
You should now be less afraid of SoftIce and overbloated protection schemes like
this one... if this essay has helped, then I am satisfied.  Good luck with your
future cracks, and may the mighty zen force of the older ones be with you!

You can mail me here to tell me what you thought of my essay and to suggest

Veni vidi vici.

Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell.

You are deep inside fravia's page of reverse engineering, choose your way out:

redhomepage redlinks redsearch_forms red+ORC redstudents' essays redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_fravia+
redIs reverse engineering legal?