Page 1 of 5 12345 LastLast
Results 1 to 15 of 67

Thread: How to write a keygen ripping the original asm code

  1. #1
    achi
    Guest

    keygening ?

    i'd like to know , if there anyone have a source for win32asm keygen with comments 4 newbies.
    i think that best way to learn is get some good example.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  2. #2
    FoolFox
    Guest
    Hello,

    Here's one skeleton for, I've removed the serial generation as
    it was part of the rea course. I've just post the asm, other
    files are those generted by RadASM, don't think I added something
    in those.....the basic template is a dialogbox.
    Anyway, let me know if you need further details:

    I'm using the Masm8 Hutch's package for win32 and Ketilo
    RadASM as IDE.

    Code:
    ;===========================================================================
    ;                    KeyGen by etherlord 
    ;                 Compiled with RadASM/MASM32
    ;===========================================================================
    .386
    .model flat, stdcall  ;32 bit memory model
    option casemap :none  ;case sensitive
    
    include REAKEYG1.inc
    
    .code
    
    start:
    
    	invoke GetModuleHandle,NULL
    	mov		hInstance,eax
    
        invoke InitCommonControls
    	invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
    	invoke ExitProcess,0
    
    ;########################################################################
    
    DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    
    	mov		eax,uMsg
    	.if eax==WM_INITDIALOG
    
    	.elseif eax==WM_COMMAND			; user press the generate button
    		mov	eax,wParam
    		.IF ax==IDC_BTN1 
                ; getting the handle of the Crackme window with FindWindow
                invoke FindWindow, addr lpClassName, addr lpWindowName
                	.if eax!=NULL 			
    			; we have found a handle
                		mov hwndParent,eax
                		; now we have to get the handle of the subwindow with FindWindowsEx
                		invoke FindWindowEx,hwndParent,hwndChildAfter, addr ClWindn, NULL
                		; if we get a handle, time to retrieve the info
                		.if eax!=NULL
    	            		mov hwindfirst,eax
    	            		; we are now seeking the second textbox
        	        		invoke FindWindowEx,hwndParent,hwind, addr ClWindn, NULL
    						.if eax!=NULL
    							mov hwind,eax						
    		            		invoke SendMessage,hwind,WM_GETTEXT,wParam,addr TexBuf
    	    	        		.if eax!=NULL
        	    	    			;we got some chars in the buffer, placing them back
            	    				; to our windows, 
            	    				invoke SetDlgItemTextA,hWin,IDC_EDT1,addr TexBuf
            	    				; Now, we have to build the correct serial from it
            	    				pushad
            	    				; code removed from here... just serial generation
    						; then we print out the result
    								invoke SetDlgItemTextA,hWin,IDC_EDT2,addr HrdCodStr
            	    				popad
                				.endif
    	            		.endif
                		.endif
                		;invoke MessageBox,NULL,addr MsgBoxText, addr MsgBoxCaption, MB_OK
    	            .endif
            .endif    
    	.elseif eax==WM_CLOSE
    		invoke EndDialog,hWin,0
    	.else
    		mov		eax,FALSE
    		ret
    	.endif
    	mov		eax,TRUE
    	ret
    
    DlgProc endp
    
    end start
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  3. #3
    Red wine, not vodka! ZaiRoN's Avatar
    Join Date
    Oct 2001
    Location
    Italy
    Posts
    922
    Blog Entries
    17
    Hi achi,
    I agree with you about the fact that the best way to learn is to start from some good example but we also need a bit of theory. To learn how to keygen a program, you have only to understand how the name/serial routine works. After that, when you know how the routine works, if you want to write a keygenerator you have to know how to write a simple program, in assembly or c or in the language you like.
    The source posted by FoolFox is correct but if you want to learn how to write a program, take a look at Iczelion's site: http://win32asm.cjb.net/
    The tutorial section contains interesting tutorials on how to write win32 applications.

    Tell us if to write a win32 application is really what you want to learn, we could leave this thread for all those whom want to learn how to write a simple application (or a keygenerator template ;-))

    ZaiRoN

  4. #4
    FoolFox
    Guest
    Hello,

    Yeah, Zairon is right, maybe I was a little bit straightforward on
    this one

    just in case, here's some details on the keygen I'had made
    a while ago for a friend, it's just some notes on why the
    sample is done this way :

    Code:
    So, step by step :
    
    - Find the handle of the application.
    - Find the handle of the textbox where the name lie.
    - Retrieve the content of the username textbox.
    - Compute the correct serial.
    - Either show the user the correct serial or inject it directly in the
      application.
    
    
    To find the handle of the application, I use WinSpector, there is 
    many tools of that kind floating around, any that'll show you the handle, 
    class, and such info will do the job. What we need to find the handle 
    of the application is the window name and the class name. Once found we 
    are ready to start our keygen.
    
    To find the handle of the application windows, we'll use the FindWindow
    API. The FindWindow API need the following params:
    
    
    	Syntax
    
    	HWND FindWindow(
              LPCTSTR lpClassName,
    	  LPCTSTR lpWindowName
    	  );
    
    	Parameters
    
    	lpClassName
    	-----------
    	[in] Pointer to a null-terminated string that specifies the 
    	class name or a class atom created by a previous call to the 
    	RegisterClass or RegisterClassEx function. The atom must be 
    	in the low-order word of lpClassName; the high-order word 
    	must be zero. 
    
    	If lpClassName points to a string, it specifies the window 
    	class name. The class name can be any name registered with 
    	RegisterClass or RegisterClassEx, or any of the predefined 
    	control-class names. 
    
    	If lpClassName is NULL, it finds any window whose title matches 
    	the lpWindowName parameter. 
    
    	lpWindowName
    	------------
    	[in] Pointer to a null-terminated string that specifies the 
    	window name (the window's title). If this parameter is NULL, 
    	all window names match. 
    
    	Return Value
    	------------
    	If the function succeeds, the return value is a handle to the 
    	window that has the specified class name and window name.
    
    	If the function fails, the return value is NULL. To get extended 
    	error information, call GetLastError. 
    
    
    
    So, to get the handle, we'll use the function the following way :
    
    
    	includelib user32.lib
    
    	FindWindow	PROTO	lpClassName:HWND,lpWindowName:HWND
    
    	.data
    	lpClassName	db "<ClassName>",0
    	lpWindowName	db "<WindowName>",0
    	hwndParent	dd ?
    
    	.code
    	......
    	.IF ax==IDC_BTN1 
    	   ; getting the handle of the window with FindWindow
               invoke FindWindow, addr lpClassName, addr lpWindowName
               .if eax!=NULL 
    		; if we get a result, store the result handle
               	mov hwndParent,eax
    
    
    We have now the window handle stored in hwndParent. From there, we must
    find the child window, the one wich handle the textbox. In case we have
    several textbox, we may need to enumerate them until we got the good one.
    Those objects are declared in ressources, kind of static object, once 
    you got a value about them this value should not change.
    
    To find the handle of the child window, we can use the FindWindowsEx 
    function.
    
    
    	Syntax
    
    	HWND FindWindowEx(          
      	  HWND hwndParent,
        	  HWND hwndChildAfter,
        	  LPCTSTR lpszClass,
        	  LPCTSTR lpszWindow
    	  );
    
    	Parameters
    
    	hwndParent
    	----------
    	[in] Handle to the parent window whose child windows are 
    	to be searched. If hwndParent is NULL, the function uses 
    	the desktop window as the parent window. The function searches 
    	among windows that are child windows of the desktop. 
    
    	hwndChildAfter
    	--------------
    	[in] Handle to a child window. The search begins with the 
    	next child window in the Z order. The child window must be 
    	a direct child window of hwndParent, not just a descendant 
    	window. If hwndChildAfter is NULL, the search begins with 
    	the first child window of hwndParent. 
    
    	Note that if both hwndParent and hwndChildAfter are NULL, the 
    	function searches all top-level and message-only windows. 
    
    	lpszClass
    	---------
    	[in] Pointer to a null-terminated string that specifies the 
    	class name or a class atom created by a previous call to the 
    	RegisterClass or RegisterClassEx function. The atom must be 
    	placed in the low-order word of lpszClass; the high-order word 
    	must be zero.
    
    	If lpszClass is a string, it specifies the window class name. 
    	The class name can be any name registered with RegisterClass 
    	or RegisterClassEx, or any of the predefined control-class names, 
    	or it can be MAKEINTATOM(0x800). In this latter case, 0x8000 is 
    	the atom for a menu class. For more information, see the Remarks 
    	section of this topic.
    
    	lpszWindow
    	----------
    	[in] Pointer to a null-terminated string that specifies the 
    	window name (the window's title). If this parameter is NULL, all 
    	window names match. 
    
    	Return Value
    	------------
    	If the function succeeds, the return value is a handle to the 
    	window that has the specified class and window names.
    
    	If the function fails, the return value is NULL. To get extended 
    	error information, call GetLastError. 
    
    
    If we consider a standard username/serial combo, the first subwindow is
    usually the username textbox, the one we want to catch. If we wanted to
    also grab a second textbox (company, or anything...), then we would have
    to call the function a second time. This function is called the followin
    way (we are assuming here that we got the hwndParent from previous call):
    
    
    	includelib user32.lib
    
    	FindWindowEx	PROTO	hwndParent:DWORD, hwndChildAfter:DWORD, 
    				lpszClass:HWND, lpszWindow:HWND
    
    	.data
    	ClWindn		db "<TextBoxName>",0
    	hwndChildAfter	dd ?
    	hwindfirst	dd ?
    
    	.code
    	......
           	; now we have to get the handle of the subwindow with FindWindowsEx
    	invoke FindWindowEx,hwndParent,hwndChildAfter, addr ClWindn, NULL
    	   .if eax!=NULL
    	      ; if we get a result, store the handle
    	      mov hwindfirst,eax
    
    
    Ok, we have now the handle we need to retrieve the info we want. But, how
    could we do that ? If we where in the application, a simple WM_GETEXT would
    have done the job. But we are seeking the info from an external application.
    So we need to use Windows MESSAGES to send the command to the right 
    application.
    
    
    	Syntax
    
    	LRESULT SendMessage(          
    	   HWND hWnd,
    	   UINT Msg,
    	   WPARAM wParam,
    	   LPARAM lParam
    	   );
    
    	Parameters
    
    	hWnd
    	----
    	[in] Handle to the window whose window procedure will 
    	receive the message. If this parameter is HWND_BROADCAST, 
    	the message is sent to all top-level windows in the system, 
    	including disabled or invisible unowned windows, overlapped 
    	windows, and pop-up windows; but the message is not sent 
    	to child windows.
    
    	Msg
    	---
    	[in] Specifies the message to be sent.
    
    	wParam
    	------
    	[in] Specifies additional message-specific information.
    
    	lParam
    	------
    	[in] Specifies additional message-specific information.
    
    	Return Value
    	------------
    	The return value specifies the result of the message 
    	processing; it depends on the message sent.
    
    
    To send the WM_GETTEXT command and retrieve the result, we'll use the
    following snippet :
    
    
    	includelib user32.lib
    
    	.data
    	TexBuf	db "00000000000000000",0
    
    	.code
    	......
    	; here we are getting the handle of the textbox
    	.if eax!=NULL
    	   ; we save the handle of the textbox
     	   mov hwind,eax			
    	   ; we send the WM_GETTEXT message to the textbox	
    	   ; wParam is a parameter passed to/from DlgProc		
    	   invoke SendMessage,hwind,WM_GETTEXT,wParam,addr TexBuf
    	   .if eax!=NULL
    		; here we deal with the result found
    
    
    And we have now the username stored in TexBuf, ready for any kind of
    processing. From them, insert your algo computation and show the result
    to the user. We are just showing a textbox here, but we could have as
    well send a WM_SETTEXT command to the second textbox to fill the serial
    in place of the user. Just a thing to remember, before messing with
    register in your function, it's a good thing to save the registers. You
    can choose to save only those you play with, I find it easier to user the
    PUSHAD/POPAD function (push all 32 bits register in the stack) :
    
    
    	   .if eax!=NULL
    		; here we deal with the result found
    		pushad
    		....
    		your func here
    		....
    		popad
    But the main point, is the one shown by Zairon, that you need
    first to understand the algo used in the prog you want to
    keygen.

    Hope this help to clear it a little bit.

    Regards
    FoolFox
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  5. #5
    Red wine, not vodka! ZaiRoN's Avatar
    Join Date
    Oct 2001
    Location
    Italy
    Posts
    922
    Blog Entries
    17
    Hi All,
    thx for the explanation FoolFox :-)

    To join theory and practice I will add a simple crackme to this thread. This is a simple crackme and, to keygen it, you only need to rip the original code. I decided to attach this type of crackme because I wanted to join this thread with the thread in the newbies forum named "Copying keymaker ASM from Win32Dasm" (read it, you will find a little hint :-)).
    In this way the project is complete and it gives you the possibility to:
    - learn to write a win32asm keygen
    - learn to rip code from a program

    I thought it could be an interesting idea, what do you think?
    Let the discussion begin :-)

    Good luck,
    ZaiRoN
    Attached Files Attached Files

  6. #6
    Fahr
    Guest
    Originally posted by FoolFox
    Hello,

    Here's one skeleton for, I've removed the serial generation as
    it was part of the rea course. I've just post the asm, other
    files are those generted by RadASM, don't think I added something
    in those.....the basic template is a dialogbox.
    Anyway, let me know if you need further details:

    I'm using the Masm8 Hutch's package for win32 and Ketilo
    RadASM as IDE.

    Code:
    <--snip-->
    Hmm, interesting; can you let RadASM generate the code for loading the form and handling it automatically? Or do you still have to do it by hand? (If so, I'd rather stick with raw MASM).

    - Fahr
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  7. #7
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,479
    Blog Entries
    1
    hello ZaiRoN & others..

    this thread seems to me too iLLegalz!

    2 little tech questions I inject here:
    I have dlded masm8 & about 2 month fight with it..

    Q1: So Masm can't MMX? or can(where to read how?)?
    //
    Q2: Can't force Masm to Immediate memory R/W..
    e.g.
    if I wrote:
    mov eax, dword ptr[00402000]..

    this will anyway:
    mov eax, 00402000..

    So not supported?

    *********
    DEPIH is Greyt!

  8. #8
    Red wine, not vodka! ZaiRoN's Avatar
    Join Date
    Oct 2001
    Location
    Italy
    Posts
    922
    Blog Entries
    17
    Hi evaluator!

    >Q1: So Masm can't MMX? or can(where to read how?)?
    You can but you have to use .MMX directive.

    >Q2: Can't force Masm to Immediate memory R/W..
    I am not totally sure but I don't think you can work directly with virtual address... Delphi can?

    For specific masm questions you can take a look at these two boards:
    http://www.masmforum.com/
    http://board.win32asmcommunity.net/


    ZaiRoN

  9. #9
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,479
    Blog Entries
    1
    ye, Delpih can
    mayb, better you switch from masm!?:)

    "I am to old" for inject in other forums:(
    Please, can you describe how put this .MMX
    directive or make for me header..
    (but no big prob, do DB..)

  10. #10
    FoolFox
    Guest
    Hello,

    Originally posted by Fahr
    Hmm, interesting; can you let RadASM generate the code for loading the form and handling it automatically? Or do you still have to do it by hand? (If so, I'd rather stick with raw MASM).

    - Fahr
    Yeah, RadASM come with basic templates, such as dialoggbox,
    window squeletton, and the code work as is.

    Of course, depending on what you want to achieve, you may
    have to add some extra functionnality, handling message, and
    so on. If you add a button on the ressource, you'll have to
    deal accordingly in your source...

    But for little projects, RadASM let you quickly do some windows
    stuff...

    @evaluator:

    you can write the .mmx directive just before the .code directive.


    Regards
    FoolFox
    Last edited by FoolFox; June 6th, 2003 at 07:21.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  11. #11
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,479
    Blog Entries
    1
    thanx you very match!
    this works, also .XMM works

    I searched in HLP files about MMX but nothing found.
    judge me..

    "RTFM or NOT RTFM <- thiS waS a queStion!" (W.FoolFox)

  12. #12
    Fahr
    Guest
    Originally posted by ZaiRoN
    Hi All,
    thx for the explanation FoolFox :-)

    To join theory and practice I will add a simple crackme to this thread. This is a simple crackme and, to keygen it, you only need to rip the original code. I decided to attach this type of crackme because I wanted to join this thread with the thread in the newbies forum named "Copying keymaker ASM from Win32Dasm" (read it, you will find a little hint :-)).
    In this way the project is complete and it gives you the possibility to:
    - learn to write a win32asm keygen
    - learn to rip code from a program

    I thought it could be an interesting idea, what do you think?
    Let the discussion begin :-)

    Good luck,
    ZaiRoN
    Ok, I did your keygen and it came out nice
    Except for one little detail
    For some reason, the wsprintfa doesn't produce a nice 8 digit number, instead it produces the correct serial (first 8 digits) and then keeps repeating the last 5 digits of the serial for numerous times. Anyone care to enlighten me as to what is wrong?

    Here is my code and exe:
    http://dump.lycantrope.com:5000/keymaker.asm
    http://dump.lycantrope.com:5000/keymaker.exe

    I know the name is still hardcoded, but this is only a tryout for getting the code. Once it works ok, I'll make it into a nice dialog.

    - Fahr
    Last edited by Fahr; June 8th, 2003 at 08:50.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  13. #13
    Try changing this line:

    @Buffer db 0

    To this:

    @Buffer db 20 dup (0h)

    That way you have 20 bytes to store the serial, instead of just one

  14. #14
    Registered User
    Join Date
    Dec 2002
    Location
    PL
    Posts
    45
    First, you are defining buffer which is only 1 byte big:
    @Buffer db 0
    255 bytes will be more than enough:
    @Buffer db 255

    Second, this variable will be used for MessageBox which needs string terminated with 0 so you need to initialize this var with zero's:
    @Buffer db 255 dup(0)

    Now, it will work

  15. #15
    Fahr
    Guest
    Well, that worked :P

    Guess I need some lessons on reservations still.

    Tho, why 20?
    I promise that I have read the FAQ and tried to use the Search to answer my question.

Similar Threads

  1. can anyone tell me why code such as this avoids access violation on write..
    By BanMe in forum Advanced Reversing and Programming
    Replies: 6
    Last Post: January 13th, 2011, 22:27
  2. DVD ripping problem.
    By Woodmann in forum Off Topic
    Replies: 19
    Last Post: July 28th, 2009, 20:30
  3. Me code write good: The l33t skillz of the virus writer
    By Kayaker in forum Malware Analysis and Unpacking Forum
    Replies: 71
    Last Post: July 28th, 2007, 07:55
  4. How to write spaghetti code
    By corus-corvax in forum Advanced Reversing and Programming
    Replies: 13
    Last Post: August 26th, 2005, 01:11
  5. Here is the keygen code for Moving Picture
    By goatass in forum Mini Project Area
    Replies: 4
    Last Post: November 17th, 2000, 10:32

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •