Welcome to XLogic's Assembly KeyGen tutorial. What you will need: TASM 3.0 or higher (Comes with TD). A Good Text Editor (EDIT.COM). A Good Dos Debugger (I will use TD, S-ICE and DG are also Acceptable). A File access monitor (SCANF is included). An ASM Command Listing (go buy a book). A GOOD (intermediate) knowledge of ASM. <-- Don't bug me for help. X-Tract 1.51 (included). 1. Introduction. This was the first key generator I ever wrote. It taught me more about assembly than any book I've read, considering that I originally learned assembly from debugging stuff. This is a very easy keygen to do, but you use the same process to write other much more complex keygens. The best way of writing a keygen in my experience is: 1. Debug, dissasemble, do whatever is necessary to UNDERSTAND what the hell the program is doing. 2. Extract the relevant code, reverse it or whatever needs doing to make it ready for the keygen. 3. Write the keygen. 4. Use a key you made, debug the program, and make sure it works 101%. 2. Let's Get Started! Ok, look at the program, how it runs. See if it prompts for a reg number, if it looks for a key file, any way it gets registration in. With X-Tract, there are no prompts for reg numbers, or anything. Ok, so now you run a file access monitor, to check if it looks for a reg key. (I have included a good file access monitor with the package, SCANF. To make it put file access up on the screen, use "scanf con" to run it) Bingo. It looks for X-TRACT.KEY. Now the debugging starts. First create a file called X-TRACT.KEY in the same directory as X-Tract, and load your debugger. Step through with the file access montior loaded to see where it opens the key file. You trace over the following call, and the file monitor tells you that the key has been opened. cs:366B 2EA27908 mov cs:[0879],al cs:366F 9C pushf cs:3670 E8D71A call 514A Now you restart debugging and trace one instruction into that function call. You trace over the first function call, and notice that it displays the startup banner: X-TRACT (tm) Executable File Extractor Version 1.51 7-26-95 Copyright 1994-95 by Pablo Carboni. All Rights Reserved. The next block of code uses an Int 21h call. You notice that this is what opens the file. Int 21h's usage is as follows: ah = 3D ; Open file Handle for file access al = 02 ; file access code dx = filename offset ; Where the filename is in memory Int 21h ; Try to open the file jnb ok ; If the file exists, and has been opened, jump jmp error ; If the file hasn't been opened, jump. So what this block of code does is try and open the file. cs:5150 B8023D mov ax,3D02 cs:5153 BAFC21 mov dx,21FC cs:5156 CD21 int 21 cs:5158 7303 jnb 515D cs:515A E9ED00 jmp 524A Since you made a file called X-TRACT.KEY before you started debugging it should jump on the first jump. You then end up here: cs:515D 2EA3D805 mov cs:[05D8],ax cs:5161 B43F mov ah,3F cs:5163 2E8B1ED805 mov bx,cs:[05D8] cs:5168 B99B00 mov cx,009B cs:516B BABD00 mov dx,00BD cs:516E CD21 int 21 cs:5170 3D9B00 cmp ax,009B cs:5173 7303 jnb 5178 cs:5175 E9D200 jmp 524A The first line stores the files handle for future access from AX to memory location 05D8h. Now, we see another Int 21h call coming up. This time it is as follows: ah = 3Fh ; Read Data from the open filehandle in BX bx = [05D8h] ; get the file handle we saved just before. cx = 9Bh ; How many bytes we want to try and read. dx = 0BDh ; Where we want to put the read bytes. Int 21h ; Do the deed When this returns, AX will be the actual number of bytes read from the file. So what is this next piece of code doing? cs:5170 3D9B00 cmp ax,009B cs:5173 7303 jnb 5178 cs:5175 E9D200 jmp 524A Its checking if it could read 9Bh bytes from the file, and if it could, continue. As you should have noticed, if any of the previous tests have failed, they jump to location 524Ah. Keep this in mind when you are debugging the code. Now you hit this big lump of code: cs:5178 BEBD00 mov si,00BD cs:517B BF5521 mov di,2155 cs:517E B99A00 mov cx,009A cs:5181 0E push cs cs:5182 1F pop ds cs:5183 0E push cs cs:5184 07 pop es cs:5185 FC cld cs:5186 F3A6 rep cmpsb cs:5188 7403 je 518D cs:518A E9BD00 jmp 524A rep cmpsb....... hmmm, a byte-by-byte compare statement. how this is called is: cx = Number of bytes to compare DS:DI = First lot of bytes to compare ES:SI = Second lot of bytes to compare rep cmpsb ; do the compare je continue ; jump here it the same jmp error ; jump here if not the same So what should be at the start of the rego key? Whatever is at ES:DI. The other location has what was in the rego key that you created. Now you get to this: cs:518D AC lodsb cs:518E 3CE0 cmp al,E0 cs:5190 741B je 51AD And a few more with different compares. It is checking if one of these is equal to the byte it loaded from DS:DI (its there from after the 1st compare). Could it be checking for the type of registration? Lets continue and see. cs:51AD 2EA28008 mov cs:[0880],al cs:51B1 B43F mov ah,3F cs:51B3 2E8B1ED805 mov bx,cs:[05D8] cs:51B8 B92A00 mov cx,002A cs:51BB BABD00 mov dx,00BD cs:51BE CD21 int 21 cs:51C0 3D2A00 cmp ax,002A cs:51C3 7403 je 51C8 cs:51C5 E98200 jmp 524A It saves the byte it just checked to cs:880h. Then it does what it did before with Int 21h, it reads 2Ah bytes from the file to ds:00BDh. If it could read 2Ah bytes, it continues on, otherwise it quits. Now would be a good time to get out of the debugger and make the key file. 9Bh + 2Ah bytes (add the two cx vaules from the file read Int 21h's) is equal to 197 bytes, so now would be a good time to get out, make a file of size 197 bytes, With the first lot of data it compared (that string of bytes), then either a E0h, E1h, E2h or E3h, which it looked for. I will use a E0h. You've got your registration key half done. After making it, you should be able to pass all of the tests it performs to the point where we left off. If you had problems, have a look at the key that I provided called XLOGIC.REG to get some hints. Now you hit this: cs:51C8 BEBD00 mov si,00BD cs:51CB 8BFE mov di,si cs:51CD B92A00 mov cx,002A cs:51D0 2E8A1E8008 mov bl,cs:[0880] cs:51D5 AC lodsb cs:51D6 32C3 xor al,bl cs:51D8 AA stosb cs:51D9 80EB22 sub bl,22 cs:51DC E2F7 loop 51D5 Now before i tell you, try and work out what this does. Here is what it is doing: 1. si = 0BDh ;the location to start from 2. di = si ;set the second location to start from 3. cx = 2Ah ;how many times to loop 4. bl = cs:880h ;get that byte that it checked for earlier 5. lodsb ;load a byte from ES:SI into al, increment si by 1 6. xor al,bl ;xor al by bl 7. stosb ;store al to DS:DI, increment di by 1 8. sub bl,22 ;decrement bl by 22h 9. loop 5 ;loop cx times. Now, step through this, watching what this does. What does it do? It decripts the data after the 0E0h, in the keyfile, using the above process. If you can't understand this, just keep watching it and debugging it, because if you can't understand this, you won't be able to write a keygen. Now it has tried to decrypt your name, and what we're about to look at. Check this code out: cs:51DE BEBD00 mov si,00BD cs:51E1 8BFE mov di,si cs:51E3 B92800 mov cx,0028 cs:51E6 2E8A1E8008 mov bl,cs:[0880] cs:51EB 33D2 xor dx,dx cs:51ED 33C0 xor ax,ax cs:51EF AC lodsb cs:51F0 03D0 add dx,ax cs:51F2 E2FB loop 51EF cs:51F4 2E3B14 cmp dx,cs:[si] cs:51F7 7551 jne 524A Whats it doing? You should understand the first 7 lines, actually, you should understand the whole thing if you have a good grasp of Assembly. It adds all the bytes together of what "Should" be you name, into dx. Then it compares dx to the number stored at cs:si. This is what is called a CRC check. This is only a simple one, and all it does is check if any of the bytes in the string have changed. If it is the same, it is ok, and continues, otherwise it quits. Now it sets cs:2220 to 01h, to tell the program it is registered. cs:51FC 2EC606202201 mov cs:byte ptr [2220] Then it checks the 0E0h byte. This is where we find out what it does. cs:5202 2E803E8008E0 cmp cs:byte ptr [0880] cs:5208 7424 je 522E So we let it jump: cs:522E BA9B22 mov dx,229B cs:5231 E81D00 call 5251 cs:5234 C3 ret And it prints on the screen "REGISTERED VERSION". So what do the other "0E?h" values do? Go back and try the others to find out for yourself. IMPORTANT. If you don't understand all of the above, go over and over it until you do. 2. Writing The KeyGen. Now I am going to get lazy. I will tell you what the steps are, give you my commented source file, and leave you go from there. Here is what it is doing: 1. Open the Rego File. 2. Read the Header. 3. Check it. 4. Read the Rego Name and CRC. 5. Decrypt them. 6. Calculate the CRC. 7. Check the CRC. 8. Display the Rego type. 9. Continue on with the program. Here is what you have to do: 1. Read the Rego Name. 2. Calculate the CRC. 3. Encript the Rego name and CRC. 3. Store the Rego type. 4. Write the whole block (including the header) to the Rego file. Now for the assembly file: ------------------------------------------------------------------------------- .386p seg_a segment byte public use16 assume cs:seg_a, ds:seg_a org 100h xtract_keygen Proc Far start: mov dx,offset title_text ;load the startup banner call print_text ;print it on the screen mov dx,offset max_ent_length ;load the text entry offset mov ah,0Ah ;function=get text string int 21h ;get the text cmp byte ptr entry_length,01h ;check if mor than 1 ;character was entered jae short reg_type_sel ;jump if 1 or more mov dx,offset no_entry ;not enough was entered jmp short exit ;jump to exit reg_type_sel: mov dx,offset reg_type_text ;load rego type selection call print_text ;display it xor ax,ax ;clear ax int 16h ;get a char from the keybd int 29h ;display it cmp al,31h ;check if its 1 jl reg_type_sel ;jmp if lower than cmp al,34h ;check if its 4 ja reg_type_sel ;jmp if above continue: add al,0AFh ;add 0AFh to input, to get ;"E" value. mov reg_type,al ;store it in the rego type mov dl,0Ah ;1 These lines store mov dh,al ;2 the rego type mov bx,offset max_ent_length ;3 mov [bx],dx ;4 call make_key ;make the key mov dx,offset done_text ;load done text exit: call print_text ;display the output result retn ;exit to dos/windoze xtract_keygen endp print_text proc near ;put text up on the mov ah,9 ;screen int 21h retn print_text endp make_key proc near mov si,offset name_input ;this should look mov dx,si ;familiar :) mov cx,28h ; mov bl,reg_type ; xor dx,dx ; xor ax,ax ; crc_loop: ; lodsb ; add dx,ax ; loop crc_loop ; mov bx,offset checksum_dat ; mov [bx],dx ;store the crc mov si,offset name_input ;this should also look mov di,si ;familiar :) mov cx,2Ah ; mov bl,reg_type ; encription_loop: ; lodsb ; xor al,bl ; stosb ; sub bl,22h ; loop encription_loop ; mov ah,3Ch ;open the file to write mov dx,offset key_name ; int 21h ; xchg bx,ax ;put filehand in bx mov ah,40h ;write the key to disk mov dx,offset key_data ; mov cx,0C5h ; int 21h ; mov ah,3Eh ;close the file handle int 21h ; retn make_key endp title_text db 'X-Tract 1.51 Key File Generator by XLogic', 0Dh, 0Ah name_prompt db 'Enter your name: $' reg_type_text db 0Dh,0Ah,'Please Choose Registration Type:',0Dh,0Ah db '1. Registered Version',0Dh,0Ah db '2. Beta-Test Version',0Dh,0Ah db '3. Distro-Site Version',0Dh,0Ah db '4. Special Version',0Dh,0Ah db 'Enter the number corresponding to the type: $' no_entry db 0Dh,0Ah,'You must enter a name.$' done_text db 0Dh,0Ah,'Key file X-TRACT.KEY created.$' key_name db 'X-TRACT.KEY',0 reg_type db 0 key_data dd 073696854h,020736920h,072756F79h,067657220h,072747369h,06F697461h,0656B206Eh,06F662079h dd 02D582072h,043415254h,050202E54h,07361656Ch,064202C65h,06F6E206Fh,069642074h,069727473h dd 065747562h,021746920h,063280A0Dh,039312029h,062203439h,06F572079h,02C79646Fh,065754220h dd 020736F6Eh,065726941h,041202C73h,04E454752h,0414E4954h,06150202Eh,0206F6C62h,06576694Ch dd 06F532073h,06877656Dh,020657265h,054206E49h,054206568h,02E656D69h db 0Dh max_ent_length db 26h entry_length db 0 name_input db 40 dup ('$') checksum_dat db 2 dup (0) seg_a ends end start ------------------------------------------------------------------------------- Ok, there it is in all its glory. I hope you've learned something from this, and if you did, let me know. If you didn't, good for you. Tell me how to improve this tutorial. I can be contacted in #PC97 or #cracking on EFNET. Cya Round. XLogic.