-
How to Make a Key Generator Using W32Dasm
Author: Andrew Aksel Heinlein [Mouse]
http://www.mouseindustries.com
[email protected] Download this tutorial here.
In this tutorial you will could learn: - Real-time debugging
methods with W32Dasm...
z Soft-Ice isn't always the answer. z How to initiate a debug
session with most executables. z Basic assembler theories, such as
how the stack works and how assembler calls imported DLL functions
(API). z Seek out certain values which might be helpful. z How to
toggle a breakpoint in a live process. z How to read and view
memory/registers in a live process. z How to patch a register and
memory in a live process. z How to copy assembler code from W32Dasm
in to your own program and make it work.
- Basic theories on Win32 programming...z How knowing what
certain Window's API can help you in your quest. z How pointers
actually work. z How Win32 Inline Assembler works and how you could
utilize it in your own work. z Basic ways on retrieving information
from target windows z How to use Microsoft's Spy++ or a resource
editor such as eXeScope.
From this tutorial you will take: -Free stuff...
z The code layout, in C++, to a basic key generator for the
famous Particle Fire Screen Saver. z My e-mail address to be used
in many spam lists (you bastards.)
Intro I have talked to a lot of people about key generators and
a lot of them say: "People who make key generators are insane, I
don't think I could ever do that." Not so! It is a lot easier than
it seems. You don't need to be a Soft-Ice mastermind, hell, you
don't even need to know much assembler. I will show you the steps
someone may take to make a key generator. This method I am about to
describe has proven successful many times for myself.
Let's Begin...
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/
-
How to Make a Key Generator Using W32Dasm
Author: Andrew Aksel Heinlein [Mouse]
http://www.mouseindustries.com
[email protected]
What you will need:z W32Dasm (even the shareware version will
suffice) You can find a copy at www.programmerstools.org in the
decompilers section. z Optional: A compiler that supports inline
assembler (for example: Microsoft Visual C++) z Particle Fire
Screen Saver version 1.1a (File size: 102,912 bytes) (found at:
http://www.longbowdigitalarts.com/particlefire.html) z A window spy
(Microsoft Spy++) or a resource editor (eXeScope). This is not
needed, but it helps us find Dialog Item ID Numbers. z A computer,
monitor and keyboard.
Step One
Once you have installed Particle Fire, open your screensaver
settings in Window's Display Properties. Select the Particle Fire
screensaver. Hit the Settings... button. The Particle Fire settings
dialog should appear. At the bottom of this dialog there is an edit
box which is labeled Serial #: There should be a 0 within this box.
Obviously this is where the serial number will eventually go. The
first thing I would do is open Microsoft Spy++ or eXeScope and try
to find the dialog item ID Number. (Look up GetDlgItem() on MSDN to
understand what a dialog item ID is.)
Finding the dialog item ID in Microsoft Spy++
Finding the dialog item ID with eXeScope
OK, now we know that the ID of the dialog item is 0x000003F0 (or
1008 in decimal).
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_01.htm
-
Now since we are all Window's gurus here, we know that in order
to read a value or text from a window we have to use one of the
following API calls:
z GetWindowText() z GetDlgItemText() z GetDlgItem() z
GetDlgItemInt()
I am going to assume (since there is a ZERO already in the box)
that he used SetDlgItemInt(). So I will also assume that he is
going to use GetDlgItemInt() to get the value. Don't feel like
assuming? No problem, I'll do it the long way to cover all the
bases. First, let's open up the Particle Fire screen saver in
W32Dasm. Once it finishes disassembling, there is a menu item named
Functions and a submenu called Imports. Click it. (For us impatient
ones who hate the mouse, use ALT+F+I) These are all the API
functions that this program imports from system DLLs. Now what we
are looking for are GetWindowText(), GetDlgItemText(), GetDlgItem()
or GetDlgItemInt() We should know that these functions are exported
by the User32.DLL (if you don't know this, just scroll down until
you find the export by name.) Let's try to find GetWindowText()
first. Can't find it? Me either... so this means he is not using
it. Now, with knowing he isn't using GetWindowText(), we can
scratch GetDlgItem() off our list of target functions. (You can
only use GetWindowText() with the returned HWND of GetDlgItem() to
get a window's text or value.) Confused? Just go to microsoft.com
and search GetDlgItem() and read up on it. Ok, so let's move on to
GetDlgItemText(). Can you find it on the list of imports? Nope! Ok,
that leaves one final call... GetDlgItemInt(). Find this call in
the list. It should be listed as USER32.GetDlgItemInt. See the
picture below.
Once you have found it in the list, double-click on it. The
first reference W32Dasm should take us to will look like this:
:00402428 8D442410 lea eax, dword ptr [esp+10] :0040242C 6A00 push
00000000 :0040242E 8B74242C mov esi, dword ptr [esp+2C] :00402432
50 push eax :00402433 68EA030000 push 000003EA * Reference To:
USER32.GetDlgItemInt, Ord:00F4h | :00402438 8B3D2CD44700 mov edi,
dword ptr [0047D42C] :0040243E 56 push esi :0040243F FFD7 call
edi
Author's Suggested Reading See exactly how GetDlgItemInt() works
by going to microsoft.com and looking it up or clicking here.
Author's poor attempt at a basic definition of the Stack
Assembler relies heavily on something called a "Stack." You
"push" 32 bit pointers/values on to the stack to save the values in
order to pass them to other functions. It's basically like a
growing array or vector of values. It uses the theory of "First on,
Last Off" Think of it like a stack of pancakes. You lay down one
(push), "push" another one on top of the last. to get them off, you
"pop" them off from the top down. (This is a very basic description
on the stack... I would suggest reading up on it to get a more
precise definition.) (No, really, I mean that.) Ok, with knowing
(basically) how the stack works, we can tell from the code above
that it is "pushing" 4 values onto the stack before the call to
GetDlgItemInt(). What are these 4 values? Let's look at how the API
is defined:
UINT GetDlgItemInt(HWND hDlg, int nIDDlgItem, BOOL*
lpTranslated, BOOL bSigned); Ok, great.. we see it requires 4
parameters:
z hDlg - Handle to the dialog box that contains the control of
interest.
z nIDDlgItem - Specifies the identifier of the control whose
text is to be translated.
z lpTranslated - Pointer to a variable that receives a success
or failure value (TRUE indicates success, FALSE indicates failure).
If this parameter is NULL, the function returns no information
about success or failure.
z bSigned - Specifies whether the function should examine the
text for a minus sign at the beginning and return a signed integer
value if it finds one (TRUE specifies this should be done, FALSE
that it should not).
Now, with knowing all this basic information, let's look at the
above code from a different view: :00402428 8D442410 lea eax, dword
ptr [esp+10] ; 1) "Move" the pointer to the BOOL value to EAX
:0040242C 6A00 push 00000000 ; 2) PUSH 0 onto the stack (parameter
4) :0040242E 8B74242C mov esi, dword ptr [esp+2C] ; 3) MOVE the
parent dialog window to ESI :00402432 50 push eax ; 4) PUSH the
pointer to the BOOL onto the stack (parameter 3)
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_01.htm
- :00402433 68EA030000 push 000003EA ; 5) PUSH the dialog ID to
set the value to onto the stack (parameter 2) * Reference To:
USER32.GetDlgItemInt, Ord:00F4h | :00402438 8B3D2CD44700 mov edi,
dword ptr [0047D42C] ; 6) MOVE the call to GetDlgItemInt() to EDI
:0040243E 56 push esi ; 7) PUSH the parent dialog HWND onto the
stack (parameter 1) :0040243F FFD7 call edi ; 8) CALL
GetDlgItemInt() See how that works? Pretty simple. Starts by
pushing the last parameter on first and the first parameter on
last. With knowing this, we know that this function will not help
us. Why? Because we are looking for the ID of 0x000003F! As you can
see here, it is pushing 0x000003EA on to the stack. This isn't the
ID we are looking for! But that was a good review on what to expect
next, right ? Let's continue on by going back to our Import list
and double clicking on the same item again. Keep double clicking
until you come to this address 0x00001948. It should look like
this: :00402538 8D442410 lea eax, dword ptr [esp+10] :0040253C 6A00
push 00000000 ; PUSH parameter 4 :0040253E 8B74242C mov esi, dword
ptr [esp+2C] :00402542 50 push eax ; PUSH parameter 3 :00402543
68F0030000 push 000003F0 ;
-
How to Make a Key Generator Using W32Dasm
Author: Andrew Aksel Heinlein [Mouse]
http://www.mouseindustries.com
[email protected]
Welcome back.At this point, we now know that the serial number
is stored at address 00412114. So, let's scroll all the way back to
the top of W32Dasm and select the first line. What we are going to
do is search for this value using the Search feature located in the
"Search>>Find Text" (or ALT+S+F) In the Find What edit box
type in 00412114 (See picture below) and hit search.
At address 0x00000954 - The first reference shows Particle Fire
grabbing the value from the registry and setting it for future use,
this is unimportant.At address 0x00000B93 - The next reference
shows Particle Fire setting the value to the registry to save it at
shut down. This is also unimportant.At address 0x00001474 - The
third reference shows Particle Fire setting the serial number to
the dialog item 0x000003F0. This is probably the "Init Dialog"
function. Also unimportant.At address 0x00001965 - The fourth
reference is the one we went though in part 1 with
GetDlgItemInt().At address 0x0000197E - The fifth reference is
setting the serial number's value to zero. This is unimportant.At
address 0x00001B26 - The sixth and FINAL reference is what we want!
Let's take a look... :00402726 A114214100 mov eax, dword ptr
[00412114] ; MOVE in current serial number :0040272B 50 push eax ;
PUSH it onto the stack :0040272C E8CFE8FFFF call 00401000 ; CALL a
mysterious function What could this be? Well, let's assume it is a
call to the serial number verification code. Ok, let's remember
this and move on to something else. We will come back to this
later. OK, now for the really fun part. Let's debug the
process.
z We know where Particle Fire grabs the serial number from the
edit box. z We know where it stores the number to. z We think we
know where it checks the serial number.
Go to the DEBUG menu and select Load Process (ALT+B+L) (If a
Load Disassemble Dialog comes up with a command line edit box, just
hit the "Load" button to skip this.)W32Dasm will now rearrange
itself and enter into DEBUG mode and set the code display to the
program entry point as shown below. W32Dasm has now paused the
process. Nothing will happen until you are ready to go.
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_02.htm
-
Now, let's run the process. To do this hit F9 (or ALT+B+R).Ok,
now that we can see the configuration dialog of Particle Fire, we
can now enter in some bogus serial number. For this example I will
enter in 201527 (I suggest you do the same, it will be easier to
follow the rest of this example)After you have entered the bogus
serial number, go back to W32Dasm. We must set a breakpoint in
order for W32Dasm to stop on the line of code we want to examine.
So let's set one near the GetDlgItemInt(). To do this, find the
call (remember going to the imports list and finding
USER32.GetDlgItemInt()?) Ok, once we have found the call, lets set
a breakpoint a couple lines below it. (remember the redundant call
to GetDlgItemInt()?, let's catch the 2nd call) To do this, select
the line and hit F2 (or ALT+B+B). The line should be hi-lighted in
yellow now. You have successfully set a breakpoint. (See picture
below)
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_02.htm
-
break. If it doesn't, just click on the serial number edit
box... if it still hasn't broke, then start over. The reason why it
breaks immediately is because the author has it checking the key
when the edit box "changes." So when you bring the configuration
dialog to the front, the edit box gains focus and triggers it to
use GetDlgItemInt() so it can verify it. Most of the time you have
to close the dialog before it will trigger this event.
Now we are inside Particle Fires process. The Particle Fire's
configuration window should be frozen. Go back to W32Dasm. We are
now going to "Step Thru" the code and examine it.Now we must hit F8
to "Step Thru" to the next line. We do this a total of 4 times. The
4th time a new dialog should appear. It's W32Dasm description of
the call to GetDlgItemInt() API call. Hit the "Get API Result" at
the bottom of the dialog.
There is our bogus serial number in Arg00! (00031337 == 201527)
Hit the Close button on the API description box.Hit F8 two more
times. We should now be one line past this one: :00402565
A314214100 mov dword ptr [00412114], eax If you are there, your
bogus serial number is now stored in memory!How do we know for a
fact that it is? Well, let's check. We know the address is
00412114. So, in the Register Dialog (See picture below) Type
"412114" into the "User Addr 2" box. Once we have done that, click
on the "UA2" button in the middle display. Wallah! There it is in
the middle of the list box!
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_02.htm
-
Close the Particle Fire configuration dialog box and close up
W32Dasm.
Step Two Summary Ok, take another deep breath. What we should
now
know is:
z How to load and start to debug a process. z How to toggle a
breakpoint. z How to resume a "broken" process. z How to step thru
lines of code. z How to view the contents of an address in
memory.
If you don't understand how to do these things, just start over
and retry... it's really easy!
Continue on to step three...
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_02.htm
-
How to Make a Key Generator Using W32Dasm
Author: Andrew Aksel Heinlein [Mouse]
http://www.mouseindustries.com
[email protected]
Once again, welcome back.Feel confident? This tutorial will now
get a little less personal since by now you know how to debug a
process with W32Dasm and since you know where how to get to the
address' we need to get to. OK, now we are going to run into a
problem. We have to actually start the screensaver to debug the
"KeyGen" code. But if we do this, the screen saver will cover all
the other windows and we wont be able to see W32Dasm. Well, I guess
we will just have to figure out a way to make it so this window
doesn't cover all other windows. This is where we learn how to
patch a live process' memory and registers. Now, to trigger the
screensaver to kick on, we have to set the command line to be "/s"
This will tell particle fire that we want it to start in
screensaver mode.
I can think of 2 simple ways to make Particle Fire not get in
the way of our work area. If we look up the import
"USER32.CreateWindowEx" and set a breakpoint before it, we will see
that the dwExStyle is 8 when CreateWindowEx() is called. 8 is
defined as WS_EX_TOPMOST. Also, we see that the width and height is
our desktop's width and height. Let's try and change dwExStyle
parameter to zero instead of 8 so the window stays in back of our
work area and not "on top" of all others. The CreateWindowEx() code
looks like so: :00405E3E 51 push ecx ; push lpParam :00405E3F 50
push eax ; push hInstance :00405E40 51 push ecx ; push hMenu
:00405E41 FF7508 push [ebp+08] ; push hWndParent :00405E44 FF75F8
push [ebp-08] ; push nHeight :00405E47 57 push edi ; push nWidth
:00405E48 51 push ecx ; push y :00405E49 51 push ecx ; push x
:00405E4A FF75FC push [ebp-04] ; push dwStyle :00405E4D 53 push ebx
; push lpWindowName :00405E4E 68D4154100 push 004115D4 ; push
lpClassName :00405E53 56 push esi ; push dwExStyle
-
Now continue to step thru the code until the API Description box
pops up. You should now see Arg01 as 00000000! (Look at picture
below) Hit "Get Api Result" and now your background should be a
black window. The screen saver was created as usual, except without
it being the top most window! You have successfully patched a
register.
The other way i was thinking of doing this is to set the width
and height to be 1. I won't explain how to do this, I'm sure you
can figure it
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_03.htm
-
out now :)
Step Three Summary Are you confused? Don't be! Just keep
starting from the beginning, eventually you will get it, I
promise.
You should now be able to:
z Start and debug a process with a specific command line
z Basically know how the "Register View" works.
z Basically know how the "Modify Data" dialog works.
z Know how to modify a register value.
Continue on to step four...
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_03.htm
-
How to Make a Key Generator Using W32Dasm
Author: Andrew Aksel Heinlein [Mouse]
http://www.mouseindustries.com
[email protected]
Welcome to the fourth and final step!You should now have a big
black desktop with W32Dasm in debug mode and paused right after the
CreateWindowEx() function. Remember us using the search tool to
find the value 00412114 (where the serial number is stored in
memory)? Let's do that again and find the last occurrence of
00412114. Once you have found the last occurrence, set a breakpoint
on that line. Now, hit F9 to let the process run. Particle Fire
should now immediately break. Step thru ONE line. Look at the value
of EAX in the register view. Look familiar? It's our bogus serial
number :) Ok, can you guess where the next CALL will take us? If
you guessed "To the key verification code" you were right.This is
the magical call: :0040272C E8CFE8FFFF call 00401000 IMPORTANT:Once
you stepped thru to that line, HIT F7 TO *STEP INTO* THE CODE. Do
not use F8! You will step over it! ok, if everything is going the
way it's supposed to, you should now be in a block of code that
looks like this: :00401000 8B442404 mov eax, dword ptr [esp+04] ;
MOVE our bogus serial number to EAX :00401004 56 push esi ; we need
to use ESI :00401005 3D00CA9A3B cmp eax, 3B9ACA00 ; compare our
bogus serial number to 3B9ACA00 (dec:1000000000) :0040100A 763D jbe
00401049 ; Jump out if below or equal (no good if serial
2000000000) :00401013 8BC8 mov ecx, eax ; MOVE serial to ECX
:00401015 8BF0 mov esi, eax ; MOVE serial to ESI :00401017 C1E114
shl ecx, 14 ; SHIFT LEFT () ECX by 0x0C (dec: 12) :00401033 33F1
xor esi, ecx ; EXCLUSIVE OR (XOR, ^) ESI by ECX :00401035
B994260000 mov ecx, 00002694 ; MOVE 00002694 (dec: 9876) to ECX
:0040103A 33C6 xor eax, esi ; EXCLUSIVE OR (XOR, ^) EAX by ESI
:0040103C F7F1 div ecx ; DIVIDE ECX (store remainder in EDX)
:0040103E 85D2 test edx, edx ; is EDX zero? :00401040 7507 jne
00401049 ; If EDX is not zero, this key is NO GOOD! * Possible
Reference to String Resource ID=00001: "Particle Fire!" ; not a
reference to the string resource "Particle Fire!" | :00401042
B801000000 mov eax, 00000001 ; If we made it here, we have a
legitimate key! (returning TRUE):00401047 5E pop esi ; done with
ESI :00401048 C3 ret ; get outta here * Referenced by a
(U)nconditional or (C)onditional Jump at Addresses: ; If we make it
here, its a BAD KEY |:0040100A(C), :00401011(C), :00401040(C) |
:00401049 33C0 xor eax, eax ; set EAX to zero (returning FALSE)
:0040104B 5E pop esi ; done with ESI :0040104C C3 ret ; get outta
here Ok, there is the key verification code. The beginning of this
function should make some sense to you. The key must be greater or
equal to 1000000000 and less than 2000000000. If you don't
understand the rest of this, don't worry about it, you don't really
need to :) Here is some pseudo code for this function: if( (key =
2000000000) ){ return FALSE; // the key is no good! }else{ Do Some
Crazy Ass Math } Ok, obviously, we wont make it far with our bogus
key since its less than 1000000000. But, we know what the code is
to verify the key! All we have to do now is open our compiler and
cut and paste the assembler into our source code!
Let's copy the assembler in W32Dasm to the clipboard. In order
to do this, click to the left of the first line you want to copy. A
red dot should appear (). You want to be able to select multiple
lines, so once you have selected one line, hold the SHIFT key down
and click a couple lines below the first
marker. You should now see a series of red markers. Click the
"Copy" button. You will now have all the selected lines on the
clipboard. (Look at picture
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_04.htm
-
below.)
Here is some C++ source code to run in a console and generate
every key that Particle Fire could ever use. #include void main(){
for(unsigned int i = 1000000001; i < 2000000000; i++){ __asm{
mov eax, i push esi cmp eax, 0x3B9ACA00 jbe l_get_out cmp eax,
0x77359400 jnb l_get_out mov ecx, eax mov esi, eax shl ecx, 0x14
mov edx, eax shl esi, 0x10 and ecx, 0xFFF00000 shr edx, 0x10 or
esi, edx sub edx, edx xor esi, ecx mov ecx, eax shr ecx, 0x0C xor
esi, ecx mov ecx, 0x00002694 xor eax, esi div ecx test edx, edx jne
l_get_out } // if we got here, it is a good key! printf("Found a
key: %u\n", i); l_get_out: __asm{ pop esi } } } And here is the
actual function completely converted to C++:
BOOL VerifyParticleFireKey(unsigned int Key){ UINT a = Key, b =
Key, c = Key, d = Key; if( (Key = 2000000000) ){ return FALSE; } a
= 0x0C; b ^= a;
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_04.htm
-
a = 0x00002694; d ^= b; d %= a; return (d == 0); }
Congratulations! You now have a key generator for Particle Fire! If
you are reading this, and you still have no idea how you did this,
or you couldn't do this, just start over. Honestly, if I were
showing you this in real life, it would have taken me about 7
minutes to go through everything and you would be sitting there
saying "oh! I see what's going on." and would probably feel pretty
confident about doing it yourself. Don't give up, it is much harder
trying to learn from a tutorial than in real life. A lot of these
steps are not needed in making a key generator for Particle Fire,
but I really wanted to show you some neat things you can do with
W32Dasm. The only problem with relying on W32Dasm is the fact that
sometimes executables are compressed and the data within the
executable is unreadable. But, there are ways around this. You
could use a program called ProcDump (found at programmerstool.org).
A lot of programs can be restored to original working condition
with this program. If a program like ProcDump fails to work, then
the other route is learning NuMega's Soft-Ice. Soft-Ice does the
same thing as W32Dasm's debugger, except it debugs the process
which is loaded in to memory. Soft-Ice is a hard program to use,
and I would suggest only using it if all else fails. What I have
shown you today with W32Dasm is just the tip of the ice burg. There
are plenty more things you can do with this program (i.e.:
debugging DLLs, temporary patches to target code, etc. the
possibilities are endless) If people seem to benefit from this
tutorial, I will target other methods in new tutorials. If you have
any questions about anything in here, send me an e-mail and I will
try to help you out. (Please don't e-mail me with key generator or
patch requests, you can find those online.) Good luck!-Mouse (May
10th, 2003)
9/25/2012http://www.mouseindustries.com/tuts/w32dasm_tut1/part_04.htm
How to Make a Key Generator Using W32DasmIntroWhat you will
need:Step OneStep TwoStep ThreeStep Four