Level : newbie
Writing a basic keygen in MASM for Phlux keygenme 1.
Tools used: MASM32 and OllyDBG for debugging if necessary.attachment
Good day to you all who are reading this first, we'll discuss the basic opcodes such as MOV, ADD or other opcodes that are used in the algo I'll explain.
After my last tutorial about the 'Can you CrackMe', I said I'd rate myself 0/10 in keygens, heh, well that's not 0/10 anymore otherwise I couldn't write this tutorial. But because I'm not an expert too, if somebody has ideas to add something or found some serious mistakes contact me.
Okay, I'm hoping you read this thorougly so you can learn something :-)
We'll not go into further details about the full ASM source, or are we? Okay for the ones who really want that too, I'll include a total source at the bottom of this tutorial.Look at the following algorithm:
generate proc ; indicates a procedure is started
PUSH EBX ; saves the EBX value to the stack because we are going to use EBX, and EBX is a register that needs to be saved (often).
PUSH OFFSET szUser
MOV EDX, EAX
XOR ECX, ECX
XOR EBX, EBX
movzx eax, byte ptr [szUser+ECX]
xor eax, 31337h
add eax, 0DEADBEEFh
imul eax, 666h
sub eax, 1BADBAB3h
shl eax, 3h
xor eax, 0D34DD00Dh
add ebx, eax
invoke wsprintf, ADDR BUFFER, ADDR PREFIX, ebx ; look at API of wsprintf some lines below
; basically, it turns the hex value into an
; ASCII value, because we use the %X prefix.
;int wsprintf( ; this is the API wsprintf as you might understand :-)
; LPTSTR lpOut, ; LPCTSTR lpFmt, ; ... ; other optional arguments ; ); POP EBX
I've commented the ASM opcodes of the algorithm, look at them :-). First of all, I also want to say this, EAX and EDX are used for dividing, EAX is the quotient result and EDX is the remainder (you learnt this on school I hope, except for the registers :P). Next, EBX, EBP, ESI, EDI are registers that often need to be saved. If something is in it before you start using them, always use PUSH, and after you are finished use POP to retrieve it again from the stack, but beware: if you use another POP instruction in the thing you are busy on, then that POP gets the value of the PUSH, so you could also POP your PUSHED (the saved register) first and then later on PUSH and POP it again. This can be confusing, therefore I'll comment a little example below:Look at this piece of code with PUSHES and POPS.
generate proc ; indicates a procedure is started PUSH EBX ; saves the EBX value to the stack
PUSH ESI ; saves the EDI value to the stack
; some code now
XOR ESI,ESI ; clears it, we use the last ESI (XOR destination,source) as 0,
; because that takes less bytes, it's just a fact that it's used
; as 0, nothing more, nothing less
; XOR sets the output bit if the source bit is different from the
; destination bit. So that's why it becomes 0.
XOR EBX,EBX ; clears EBX too, so we can start using it :)
ADD ESI,539h ; this adds the decimal value 1337 to ESI, 1337d is 539h, 539h = 539 HEX :-)
MOV EBX,9865h ; this adds the decimal value 2689 to EBX, it's 9865h and 2689d. You can use
; windows calculator for this, use the SCIENTIFIC view :)
POP EBX ; gets the last value in the stack and saves it to EBX, see?
; that's a mistake that could be taken
; therefore, ignore this opcode
POP ESI ; gets the last value (that was ESI, therefore this is right) and saves it into ESI
POP EBX ; gets the value after the last POP, so that's EBX, see? first in / first out system
Okay, so this are some basics :-), MOV puts a value somewhere, ADD adds a value, XOR is explained in the comments above. I strongly recommend that you get 'win32asmtutorial.zip'. It is a HLP file in HTML style, you could also print it to read them somewhere in ease :-), I did put it on my MP3 player because I can view text-files on it :-) saves me some ink.
So, this commands like MOV (is put), DIV (is /, divide), MUL (is *, multiply), there do exist other opcodes of course, that you will often meet in algorithms, therefore I recommend the 'win32asmtutorial.zip' to find out what these things do exactly, if you still don't understand them after reading the Win32 ASM Tutorial, contact me or some experienced cracker at BiW Forum. If you want 'win32asmtutorial.zip' and you REALLY can't find it (would surprise me) you may contact me.
Now I'll include the full ASM, and I'll comment some things too, because that'll make things easier to understand maybe, I'll only comment things that have to do with displaying the serial or getting the username and the algo, I assume you know the other stuff, if not, then please have a break and read the Win32 ASM Tutorial (the 'win32asmtutorial.zip' of course). Or you could just continue and read that tutorial later :-)Source for the Key Generator (keygen.asm for example):
.model flat, stdcall
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
.data hEdit1 dd 0
hEdit2 dd 0
hInstance dd 0
hIcon dd 0
dlgname db "keygen",0
Format db "%0.8X%0.8X",0
Caption db "About",0
MsgAbout db "Key Generator by TDC",13,10,10
db "..: Cracked by : nick? :.. ",13,10
db "..: Also known as : ur alias? :.. ",13,10
db "..: Protection : Custom :.. ",13,10
db "..: Contact info : mail? :.. ",13,10
db "..: Release date : date? :.. ",13,10
db "..: Date format : dd-mm-yyyy :.. ",13,10
db " ",13,10
db "Greetings to : BiW Reversing members",13,10
db "Special thanks to : usernames here",13,10,0
UserName db "username displayed when start", 0
UserKey db "serial displayed when start", 0
szMsgMinLetter db "Please enter more than 3 characters...",0
BUFFER db 32 dup(0)
PREFIX db "%X", 0 ; important, sets the PREFIX for later use in wsprintf API, %X indicates we are going to use wsprintf for conversion of HEX to ASCII
szUser db 90 dup (?)
szSerial db 90 dup (?)
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam,hInstance,ADDR dlgname,NULL,ADDR WndProc,NULL
WndProc proc hWin :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD
.if uMsg == WM_INITDIALOG
invoke SendMessage,hWin,WM_SETICON,0,eax invoke GetDlgItem,hWin,107
mov hEdit1, eax
mov hEdit2, eax
invoke SetDlgItemText,hWin,107,offset UserName
invoke SetDlgItemText,hWin,108,offset UserKey
.elseif uMsg == WM_COMMAND
.if wParam == 109 ; if Generate button is pressed, remember parameter 109 was set in rsrc.rc
invoke GetDlgItemText,hWin,107,offset szUser,90
cmp eax,3 ; checks if username = 3 characters, you can change this to whatever you want the user to require at least
jl error ; if less ( JL = Jump less ) then goto error and display please enter.... blabla..
call generate ; call the actual generating process with the algo
invoke SetWindowText,hEdit2, offset BUFFER ; sets the new serial generated in the hEdit2 box, (the second box)
error: invoke SetDlgItemText,hWin,108, offset szMsgMinLetter ; puts the szMsgMinLetter value in the read-only box, check the box in rsrc.rc (the one with 108 as parameter)
.elseif wParam == 110
invoke MessageBox, hWin,addr MsgAbout, addr Caption,MB_ICONINFORMATION or MB_OK
.elseif wParam == 111
.elseif uMsg == WM_CLOSE
.endif exit: xor eax, eax
generate proc PUSH EBX ; save EBX
PUSH OFFSET szUser ; the push for the call :-)
CALL lstrlen ; checks username length (often used), then it's stored in EAX
MOV EDX, EAX ; in this example we move the EAX value to EDX, EAX was the length.
XOR ECX, ECX ; clear ECX
XOR EBX, EBX ; clear EBX
@@: ; indicates a point in the program, to jump to :-)
movzx eax, byte ptr [szUser+ECX] ; gets next character from szUser
xor eax, 31337h ; XORs that with 31337h
add eax, 0DEADBEEFh ; ADDs DEADBEEFh (we included a 0 before DEADBEEF, that's always necessary when a value begins with a A, B, C, D, E or F, when beginning with a number it's not necessary to put a 0 in front of it.
imul eax, 666h ; we use IMUL because our eax is a signed byte, (more about signed and unsigned bytes in the Win32 ASM Tutorial that I'm pointing much to in this tutorial)
sub eax, 1BADBAB3h ; substracts eax with BADBAB3h
shl eax, 3 ; SHLs the bytes 3, shifts it left by 3
xor eax, 0D34DD00Dh ; XORs that with D34DD00Dh
add ebx, eax ; adds EAX to EBX, ebx is the value that will be the total serial at the end of this loop
INC ECX ; increases the value to pick the next character from szUser in the next jump to @@
CMP ECX,EDX ; checks if we are at the end of the username, if so the jump next is ignored
JNZ @B ; means jump one back, so thats jumping to @@, JMP @F means jump forward
invoke wsprintf, ADDR BUFFER, ADDR PREFIX, ebx ; convert it to an ASCII string for displaying, the PREFIX is set above under the '.data' section.
POP EBX ; get original EBX value back
ret ; return from call (remember the call generate when Generate is pressed?)
#include "masm32includeresource.h" keygen DIALOGEX 0, 0, 196, 93
STYLE DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU
CAPTION "Brought to you by ?nick-in-rsrc.rc?, 2005"
FONT 8, "Tahoma" BEGIN
CTEXT "Key Generator by ?nick-in-rsrc.rc?",101,6,7,184,11,SS_CENTERIMAGE ,WS_EX_STATICEDGE
CONTROL "",103,"Static",SS_BLACKFRAME | SS_SUNKEN,6,22,184,2
EDITTEXT 108,36,49,147,13,ES_AUTOHSCROLL | ES_READONLY
END OF SOURCE
Hopefully, you have learned something of the comments, it's not that hard to understand, the parameter for the Generate button is set in the 'rsrc.rc' file, and it's set to 109 in this case. I've done as much as I could to help you understanding it all better, and again I strongly recommend you to take a look at the 'win32asmtutorial.zip', because it gives much information about calculation opcodes and about how memory works in 32-bits.
If you want to compile this all (of course you want :P), then also make a little batch program that automatically makes an .EXE file, it's not hard to do. Heres the MS-DOS batch program I made for the job:
Batch program (let's call it make.bat):
@echo offif exist rsrc.res del rsrc.res
REM change the keygen.* to whatever you want to name your keygen.asm, .obj and .exe files.
if exist keygen.exe del keygen.exe
if exist keygen.obj del keygen.obj
if exist rsrc.res del rsrc.res
if exist rsrc.obj del rsrc.obj
masm32binml /c /coff keygen.asm
masm32bincvtres /machine:ix86 rsrc.res
masm32binLink /SUBSYSTEM:WINDOWS keygen.obj rsrc.obj
if exist keygen.obj del keygen.obj
if exist rsrc.obj del rsrc.obj
END OF SOURCE
Oh yes, one thing I want to say about the algorithm, hehe, it's the algorithm for 'Phlux keygenme 1'. I added 'Phlux keygenme 1' to BiW Reversing under crackmes.
After all this stuff I hope you will understand it and try to make some stuff on your own, just try a random newbie keygenme or just do whatever you think you should to get better :-). You are now ready for it if the stuff works.
You can always contact me about anything :-)