Program : DiskFactory/32 v2.10
Cracked by : drlan [ME97]
Date : 10/17/97
URL : www.shareware.com
Protection : Very simple name and validation code
Audience : Newbies
Tools needed : SoftIce 3.x, Hex editor
While much of this has been covered elsewhere, I'm going to include it
again here to make this a comprehensive "newbie" tutorial. This has
been blatantly plagarized from various sources. So, giving credit where
credit is due:
Thanks go to ED!SON, Razzia, Romeo and the rest of the cracking greats
who published earlier essays for newbies covering much of this
introductory info.
For starters, you'll need to assemble your cracking toolkit. You'll
find most of these resources on the web, or by asking senior crackers.
These represent the tools we use most frequently, subject to some
personal preference. The version listed is current as of this writing.
Debugger : NuMega SoftIce 3.21 for Windows 95 (best by far!)
: or Borland Turbo Debugger, Microsoft CodeView, Watcom, etc.
Disassembler : W32Dasm 8.9
: or IDA 3.64, Sourcer 7.0, etc.
Hex Editor : PS Edit 4.40 (small, fast, DOS)
: or Hiew 5.66, Hex Workshop 2.53, Ultra Edit 4.40c, etc.
Resource editor: Borland Resource Workshop 4.5
Assembler : Borland Turbo Assembler (TASM/TLINK)
: or Microsoft MASM
Registry watch : Shetef WinExpose/Registry 1.0
: or RegMon
File I/O watch : Shetef WinExpose/IO 2.0
: or FileMon
File Viewer : Inso Quick View Plus 4.0
There are lots of other tools and everyone has their personal favorites.
But, this represents what I would consider a minimum set of tools for a
serious cracking student.
Get W32Dasm installed. You'll use it to dis-assemble programs, to have
a look a the source code. This approach is called "dead listing." The
live and the dead listing approach have their merits and you'll probably
use them both. It's analagous to reading a road map (dead listing) vs.
just driving around and checking things out (live cracking). Sometimes
you may need to combine both methods.
Get SoftIce installed. You'll use it to crack live. It allows you to
step through a program that is running and allows you to view/change
memory locations, registers, flags, etc. You can set breakpoints on
execution, memory ranges, interrupts, etc. SoftIce will become your best
friend. After you install SoftIce, you need to edit the WINICE.DAT file
to make sure that certain "symbol exports" are enabled. You do this by
removing the semicolon (;) from the front of the line. Here is a copy
of my WINICE.DAT.
; General Variables
NMI=ON
SIWVIDRANGE=ON
LOWERCASE=OFF ; Disable lowercase assembly
MOUSE=ON ; Enable mouse
NOLEDS=OFF ; Disable led switching
NOPAGE=OFF
PENTIUM=ON ; Pentium op-codes
THREADP=ON ; Follow thread process
VERBOSE=ON
ECHOKEYS=OFF
PHYSMB=32 ; Exact memory size
SYM=512 ; Memory allocated to symbols
HST=128 ; Memory allocated to history
TRA=128 ; Memory allocated to back trace buffer
MACROS=32
; Startup Sequence
INIT="lines 60;ww;wl;wr;wd 24;wc 24;code on;x;"
; Funtion Keys
F1="h;"
F2="^wr;"
F3="^src;"
F4="^rs;"
F5="^x;"
F6="^ec;"
F7="^here;"
F8="^t;" ; Step into functions (Trace)
F9="^bpx;" ; Set breakpoint
F10="^p;" ; Step over functions (Procedure)
F11="^G @SS:ESP;" ; Step out of function
F12="^p ret;" ; RETurn from caller
SF3="^format;"
CF8="^XT;"
CF9="TRACE OFF;"
CF10="^XP;"
CF11="SHOW B;"
CF12="TRACE B;"
AF1="^wr;"
AF2="^wd;"
AF3="^wc;"
AF4="^ww;"
AF5="CLS;"
AF8="^XT R;"
AF11="^dd dataaddr->0;"
AF12="^dd dataaddr->4;"
CF1="altscr off; lines 60; wc 32; wd 8;"
CF2="^wr;^wd;^wc;"
; WINICE.DAT
; (SIW95\WINICE.DAT)
; for use with SoftICE Version 3.0 (Windows 95)
; 14 Aug 1996
; *************************************************************************
; If your have MORE than 32MB of physical memory installed, change
; the PHYSMB line to the correct # of Megabytes.
; If you have LESS than 32MB you can save a bit of memory by
; specifying the correct # of Megabytes
; Example: PHYSMB=32
; *************************************************************************
; ***** Examples of sym files that can be included if you have the SDK *****
; Change the path to the appropriate drive and directory
;LOAD=c:\win95\system\user.exe
;LOAD=c:\win95\system\gdi.exe
;LOAD=c:\win95\system\krnl386.exe
;LOAD=c:\win95\system\mmsystem.dll
;LOAD=c:\win95\system\win386.exe
; ***** Examples of export symbols that can be included *****
; Change the path to the appropriate drive and directory
;EXP=c:\win95\system\vga.drv
;EXP=c:\win95\system\vga.3gr
;EXP=c:\win95\system\sound.drv
;EXP=c:\win95\system\mouse.drv
;EXP=c:\win95\system\netware.drv
;EXP=c:\win95\system\system.drv
;EXP=c:\win95\system\keyboard.drv
;EXP=c:\win95\system\toolhelp.dll
;EXP=c:\win95\system\shell.dll
;EXP=c:\win95\system\commdlg.dll
;EXP=c:\win95\system\olesvr.dll
;EXP=c:\win95\system\olecli.dll
;EXP=c:\win95\system\mmsystem.dll
;EXP=c:\win95\system\winoldap.mod
;EXP=c:\win95\progman.exe
;EXP=c:\win95\drwatson.exe
; ***** Examples of export symbols that can be included for Windows 95 *****
; Change the path to the appropriate drive and directory
EXP=c:\win95\system\kernel32.dll
EXP=c:\win95\system\user32.dll
EXP=c:\win95\system\gdi32.dll
EXP=c:\win95\system\advapi32.dll
;EXP=c:\win95\system\comdlg32.dll
;EXP=c:\win95\system\shell32.dll
;EXP=c:\win95\system\shell232.dll
;EXP=c:\win95\system\comctl32.dll
;EXP=c:\win95\system\crtdll.dll
;EXP=c:\win95\system\version.dll
;EXP=c:\win95\system\netlib32.dll
;EXP=c:\win95\system\msshrui.dll
;EXP=c:\win95\system\msnet32.dll
;EXP=c:\win95\system\mspwl32.dll
;EXP=c:\win95\system\mpr.dll
The important export symbol lines to enable are:
EXP=c:\win95\system\kernel32.dll
EXP=c:\win95\system\user32.dll
EXP=c:\win95\system\gdi32.dll
EXP=c:\win95\system\advapi32.dll
Here's a very brief summary of SoftIce commands. You can find detailed
help files on the web, or via help within the program. I suggest you
download the users' guide and command reference.
? ; print a number, or the value of a register, in hex and decimal
D ; display (data/ASCII or hexadecimal values)
BL ; list all current breakpoints
BC ; clear breakpoints (BC 0 - clears breakpoint 0, BC * - clears all)
BD ; disable breakpoints
BE ; enable breakpoints
BPX ; breakpoint on execution
BPM ; breakpoint on memory (read/write)
BPR ; breakpoint on memory range
BPMB ; breakpoint on memory byte
BPINT ; breakpoint on interrupt (e.g., BPINT 21, BPINT 3)
BPIO ; breakpoint on io (useful for dongle cracking)
F4 ; view user screen
F5 ; enter/exit SoftICE screen (same as Ctrl-D)
F8 ; step into a function (same as T - trace)
F10 ; step over a function (executes the line of code)
F11 ; step out of a function (throws you back at the caller)
F12 ; return to caller (same as P RET - process to next RETurn)
Here are some various breakpoints useful in our trade.
For the "enter your name and reg code" type dialogs
GetDlgItemText ; 16 bit
GetDlgItemTextA ; 32 bit
GetWindowText ; 16 bit
GetWindowTextA ; 32 bit
GetDlgItemInt
When you get a message that the serial number is wrong
MessageBeep
SendMessage ; 16 bit
SendMessageA ; 32 bit
For "nag screens"
MessageBox ; 16 bit
MessageBoxA ; 32 bit
DialogBox
DialogBoxParam ; 16 bit
DialogBoxParamA ; 32 bit
For string comparisons
lstrlen
lstrcmp
For registry settings
RegSetValueEx
RegSetValueExA
RegQueryValue
RegQueryValueEx
RegQueryValueExA
GetPrivateProfileString
GetPrivateProfileStringA
GetProfileString
GetProfileStringA
GetStartupInfo
For date limits
GetLocalTime
GetSystemTime
For nags that pop up after some amount of time
SetTimer
KillTimer
When GetWindowText, GetDigItemText and GetDlgItemInt fail, try
Hmemcpy
- or -
BMSG window-handle [L] [begin-msg [end-msg ]] [IF expression]
[DO "command1;command2;..."]
window-handle
HWND value returned from CreateWindow or CreateWindowEX.
begin-msg
Single Windows message or lower message number in a range of Windows
messages. If you do not specify a range with an end- msg, only the
begin-msg will cause a break.
Note: For both begin-msg and end-msg, the message numbers can be
specified either in hexadecimal or by using the actual ASCII names
of the messages, for example, WM_QUIT.
end-msg
Higher message number in a range of Windows messages.
L
Logs messages to the SoftICE Command window.
c=
Breakpoint trigger count.
IF expression
Conditional expression: the expression must evaluate to TRUE (non-zero)
for the breakpoint to trigger.
DO command
Breakpoint action: A series of SoftICE commands can execute when the
breakpoint triggers.
I've found the BMSG approach very useful when nothing else seemed to
work. To use this approach, first you need to find the "window-handle"
of your target. So, with the registration screen up, toggle over to
SoftICE (Ctrl-D) and first do a TASK. This will show you what programs
are running. Look for the name of your target. Then do an HWND
target_name (where target_name is the name of your program). These
windows are hierarchical and usually your the one you're looking for is
the first one in the list. Also watch for things like "EDIT." These are
good to break on, too. Once you've found the window-handle, you can set
your "windows message" breakpoint. I don't normally use a "begin-msg"
and an "end-msg." I just use one of the commands that I know will pop.
Here are some of my favorites:
bmsg xxx wm_command ; where xxx is the window-handle
bmsg xxx wm_gettext ; returned by HWND program_name
bmsg xxx wm_lbuttonup
bmsg xxx wm_lbuttondown
There are lots and lots of other nifty features and functions of
SoftICE. Again, I encourage you to find and download the users' guide
and the command reference (and check them out).
"Ok, I have everything installed and I can toggle in and out of SoftICE
using Ctrl-D... Teach me to crack." This lesson will be very basic,
but I will introduce some intermediate "cracking techniques," like how
to "fix" a program to turn it into its own "key generator." So, grab
some popcorn and a mug full of your favorite frosty beverage and prepare
to crack!
Our target is DiskFactory/32 v2.10. You should be able to find it in
one of the shareware archives like www.windows95.com, www.shareware.com,
etc.
Install the program and run it a few times to get a feel for its
behavior and to see how it's protected (e.g., nag screens, registration,
date limit, etc). You'll find that this one pops up a nag screen asking
you to register when you run it and upon exit. Go ahead and click on
the Register button. Enter your name and some bogus validation code.
Unless you are the luckiest person on earth and guessed the correct
validation code, the program will complain that you entered an invalid
code.
Ok, so now our job is to break into the program when it reads in the
values we typed. Then we want to trace through the code until it
compares our code with the "correct" code. Sometimes this is simple and
the comparison is only a few lines away from where it reads the data.
Other times, you may have to wade through a bunch of code to get to the
right spot. Our target is one of the easy ones...
Remember from above, we listed a few of the more common breakpoints that
will help us in this type of situation. This is a 32-bit program, so we
might try any of these SoftIce breakpoints.
bpx GetWindowTextA
bpx GetDlgItemTextA
bpx GetDlgItemInt
I'll save you some trouble... Let's use bpx GetDlgItemTextA. First run
the program. Then select register. Type in your name and type
something in the validation code field, but don't click on OK yet. Now
toggle over to SoftICE using Ctrl-D. Type bpx GetDlgItemTextA. Type BL
to see that your breakpoint is indeed set. Then press Ctrl-D (or F5) to
toggle back to your program. Click on OK and SoftICE will pop. You
should be looking at a SoftICE screen and should actually be in the
USER32.DLL. You can tell this by looking at the bottom of the SoftICE
screen. This will show you which program is currently active. You'll
often see KERNEL32, USER32, GDI32, and your program. This is because
typically the program makes calls to the Windows 32 API set instead of
implementing all the code itself. You'll also see other DLL names here,
like the Visual BASIC and Visual C++ runtime libraries, other program
DLLs, etc. The reason you are currently in the USER32.DLL is because the
program made an API call (GetDlgItemTextA) which happens to be
implemented in USER32.DLL.
You want to get out of the USER32.DLL and back into your program. The
best way to do that from here is to press F11. This will "step out of
the current function" and throw you back at the calling code. Go ahead
and press F11. If everything is going according to plan, you should now
be back in the target. Again, you can tell be looking at the bottom of
the SoftICE screen. It should now say DSKFAC32 (with some other text).
This is good, but so far we've only read in the name we entered. Go
ahead and press F5 (or type Ctrl-D) to leave SoftICE and continue
running the program. It will break again immediately. This time it has
read in the validation code you entered. Again, press F11 to get out of
the USER32.DLL and back into the target. You will land in a section of
code that looks something like this (again, this is the second call to
GetDlgItemTextA). This excerpt is from a "dead listing" created using
W32Dasm 8.9.
* Reference To: USER32.GetDlgItemTextA, Ord:00EDh
|
:0040DF8B FF1534F74200 Call dword ptr [0042F734]
* Possible StringData Ref from Data Obj ->"-"
|
:0040DF91 68E8744200 push 004274E8 ; second F11 brings you here
:0040DF96 6880AC4200 push 0042AC80
:0040DF9B E8A0050100 call 0041E540
:0040DFA0 83C408 add esp, 00000008
:0040DFA3 8945FC mov dword ptr [ebp-04], eax
:0040DFA6 837DFC00 cmp dword ptr [ebp-04], 00000000
:0040DFAA 0F85E7000000 jne 0040E097
:0040DFB0 6A00 push 00000000
:0040DFB2 6A00 push 00000000
:0040DFB4 682D010000 push 0000012D
:0040DFB9 8B4508 mov eax, dword ptr [ebp+08]
:0040DFBC 50 push eax
* Reference To: USER32.GetDlgItemInt, Ord:00ECh ; convert the
| ; "string" we
:0040DFBD FF1504F74200 Call dword ptr [0042F704] ; entered to an
:0040DFC3 A370AC4200 mov dword ptr [0042AC70], eax ; integer value
:0040DFC8 A150734200 mov eax, dword ptr [00427350]
:0040DFCD 50 push eax
:0040DFCE 6838AC4200 push 0042AC38 ; calculate the
:0040DFD3 E87B060000 call 0040E653 ; ver 1.x serial
:0040DFD8 83C408 add esp, 00000008
:0040DFDB 0FB7C0 movzx eax, ax
:0040DFDE 3B0570AC4200 cmp eax, dword ptr [0042AC70] ; does it match?
:0040DFE4 0F8521000000 jne 0040E00B ; no, jump bad guy
:0040DFEA 6A04 push 00000004
:0040DFEC 6870AC4200 push 0042AC70
:0040DFF1 6A04 push 00000004
:0040DFF3 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"Validation Code"
|
:0040DFF5 68EC744200 push 004274EC
:0040DFFA A148734200 mov eax, dword ptr [00427348]
:0040DFFF 50 push eax
* Reference To: ADVAPI32.RegSetValueExA, Ord:00ECh
|
:0040E000 FF1570F44200 Call dword ptr [0042F470]
:0040E006 E987000000 jmp 0040E092
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040DFE4(C)
|
:0040E00B 6838AC4200 push 0042AC38
* Reference To: KERNEL32.lstrlenA, Ord:02A3h ; count string length
|
:0040E010 FF15A0F54200 Call dword ptr [0042F5A0]
:0040E016 50 push eax
:0040E017 6838AC4200 push 0042AC38 ; calculate the
:0040E01C E8D6090000 call 0040E9F7 ; upgrade serial
:0040E021 83C408 add esp, 00000008
:0040E024 3B0570AC4200 cmp eax, dword ptr [0042AC70] ; does it match?
:0040E02A 0F8521000000 jne 0040E051 ; no, jump bad guy
:0040E030 6A04 push 00000004
:0040E032 6870AC4200 push 0042AC70
:0040E037 6A04 push 00000004
:0040E039 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"Validation Code"
|
:0040E03B 68FC744200 push 004274FC
:0040E040 A14C734200 mov eax, dword ptr [0042734C]
:0040E045 50 push eax
* Reference To: ADVAPI32.RegSetValueExA, Ord:00ECh
|
:0040E046 FF1570F44200 Call dword ptr [0042F470]
:0040E04C E941000000 jmp 0040E092
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040E02A(C)
|
:0040E051 6838AC4200 push 0042AC38
* Reference To: KERNEL32.lstrlenA, Ord:02A3h ; count string length
|
:0040E056 FF15A0F54200 Call dword ptr [0042F5A0]
:0040E05C 50 push eax
:0040E05D 6838AC4200 push 0042AC38 ; calculate current
:0040E062 E8AF040000 call 0040E516 ; ver serial number
:0040E067 83C408 add esp, 00000008
:0040E06A 3B0570AC4200 cmp eax, dword ptr [0042AC70] ; does it match?
:0040E070 0F851C000000 jne 0040E092 ; no, jump bad guy
:0040E076 6A04 push 00000004
:0040E078 6870AC4200 push 0042AC70
:0040E07D 6A04 push 00000004
:0040E07F 6A00 push 00000000
* Possible StringData Ref from Data Obj ->"Validation Code"
|
:0040E081 680C754200 push 0042750C
:0040E086 A14C734200 mov eax, dword ptr [0042734C]
:0040E08B 50 push eax
* Reference To: ADVAPI32.RegSetValueExA, Ord:00ECh
|
:0040E08C FF1570F44200 Call dword ptr [0042F470]
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040E006(U), :0040E04C(U), :0040E070(C)
|
:0040E092 E9F6000000 jmp 0040E18D
So, what's happening in all this mess? Well, the second GetDlgItemTextA
reads in the validation code we entered (as a string). Then the call to
GetDlgItemInt converts the string to an integer value and then stores
the value in variable (actually it stores it at a memory location
[0042AC70]). This memory location probably refers to some variable that
was coded in a higher level language (like C++). Press F10 (step) until
you get to this section.
* Reference To: USER32.GetDlgItemInt, Ord:00ECh ; convert the
| ; "string" we
:0040DFBD FF1504F74200 Call dword ptr [0042F704] ; entered to an
:0040DFC3 A370AC4200 mov dword ptr [0042AC70], eax ; integer value
After you press F10 on the CALL line, then type ? EAX. This will print
the value contained in the EAX register. You should notice that this is
the value you entered in the validation code box. Now continue pressing
F10 a few more times until you come to:
:0040DFCE 6838AC4200 push 0042AC38 ; calculate the
:0040DFD3 E87B060000 call 0040E653 ; ver 1.x serial
:0040DFD8 83C408 add esp, 00000008
:0040DFDB 0FB7C0 movzx eax, ax
:0040DFDE 3B0570AC4200 cmp eax, dword ptr [0042AC70] ; does it match?
:0040DFE4 0F8521000000 jne 0040E00B ; no, jump bad guy
This CALL calculates the value for a version 1.x serial number. Then it
compares that with the code you entered. If it doesn't match it jumps
on and calculates an "upgrade" serial number. Again it compares this
with the value you entered and makes a conditional jump depending on
whether or not they match. And finally it calculates a serial number
for the current version and compares it with the code you entered. If
these don't match, we jump to the nagging "you entered an invalid
code..." dialog. So, if you type ? EAX right after executing the CALL
0040E516 (line cs:0040E062) you will see the correct serial number
(validation code). CS stands for code segment. This may be different
on your machine, but on mine my CS for this program was 0137. Don't go
back to the program and enter the correct serial number (YET). Now that
we know where in the program the correct serial number calculated, we
can set a neat breakpoint in SoftICE and create all the serials we want.
First clear all your existing breakpoints by typing BC *. Now let's set
our new (neat) breakpoint. Make sure you're still sitting on or around
the above code section and set the following breakpoint:
bpx cs:0040E067 do "? eax"
This will break on the line right after the CALL which calculates the
current version serial number and when it breaks it will print the
correct value (which is contained in the EAX register). After you get
the breakpoint set, toggle back over to the registration and enter the
name you wish to find the serial for. Then enter a bogus serial (even
just one character) and click on OK. SoftICE will pop and will print
the correct serial number for you at the bottom of the screen. It's the
decimal (middle) value you're looking for. For example, using drlan as
the name, my registration code was 22971975. Write down your serial,
then press F5 or Ctrl-D to continue running the program. Since you
entered an "invalid" serial number it will bitch and give you a chance
to enter another one. Go ahead and generate as many as you'd like.
Ok, normally once we've found a serial number we don't crack any
further. But, I want to teach you a few tricks here, so I'll bend the
rules a little. Let's think about how we could actually crack the
executable. Now, to understand this you're going to need some knowledge
of Assembler programming (which I suggest you develop to become a
proficient cracker). Look at the section that calculates the current
version validation code and then compares it to the one we entered.
Here it is again:
:0040E05C 50 push eax
:0040E05D 6838AC4200 push 0042AC38 ; calculate current
:0040E062 E8AF040000 call 0040E516 ; ver serial number
:0040E067 83C408 add esp, 00000008
:0040E06A 3B0570AC4200 cmp eax, dword ptr [0042AC70] ; does it match?
:0040E070 0F851C000000 jne 0040E092 ; no, jump bad guy
:0040E076 6A04 push 00000004
:0040E078 6870AC4200 push 0042AC70
:0040E07D 6A04 push 00000004
:0040E07F 6A00 push 00000000
As with anything, there are a number of ways to approach this. But
consider this: we have 12 bytes of code that we could change to make it
do something more to our liking. The lines that compare our code to the
correct code and then makes the conditional jump. If the codes match,
it will not make the jump. So, we really don't need to make the
comparison. And we certainly do not want to make the jump. Simply
reversing the jump (changing jne into je, or blatantly using NOP) is one
approach we might consider. However, this will simply write the wrong
code to the registry and we still won't be registered. It will write
the code, then go back and read it again and check it. So, simply
eliminating the jne won't help us. Let's put on our thinking/cracking
caps...
Let's use some of those 12 bytes and "put the right code where it
belongs." What we're going to do is let the program calculate the
correct code for us (built in key generator). Then rather than
comparing the correct code with the code we entered, we'll just move the
correct code into the location where our code is stored and we'll skip
that nasty jne. Actually we'll only need 5 bytes for this, so we'll let
it make the comparison, then we'll replace the jne 0040E092 with our own
instructions.
Change:
:0040E070 0F851C000000 jne 0040E092
Into:
:0040E070 A370AC4200 mov [0042AC70], eax
:0040E075 90 nop
This MOVes the correct code (contained in register EAX) into the memory
location for the code we entered. Now they match! Notice we had to add
one NOP (No OPeration) to pad to 6 bytes. We have to replace the same
number of bytes and the jne 0040E092 was 6 bytes.
You can do this live in SoftICE by pressing F10 until you are on the
line you want to change (cs:0040E070). Then type A (to assemble in our
new instructions). In the SoftICE command window, type:
A
mov [0042ac70], eax
nop
Press ESC
Press F5 or Ctrl-D to continue running the program.
Viola, it's registered! Do a Help, About and you'll see your name and
the correct serial number. Is this fun, or what?
Since we faked it into using the correct serial number, it will write
this information to the registry and stay there, so it will stay
registered and there really isn't any need to create a crack/patch. If
you want to play around and "unregister" it, just go into the registry
and delete the following entry:
[HKEY_LOCAL_MACHINE\SOFTWARE\Accurate Technologies\DiskFactory32\2.0]
Validation Code
Now it will pop up the registration nag again and allow you to
experiment.
If you really want to crack/patch the executable, just fire up your
favorite hex editor. You need to use a search string from the code a
few lines above where we're going to crack (to find a unique match).
So, here is the search and replace information.
E8AF04000083C4083B0570AC42000F851C000000 ; search
xxxxxxxxxxxxxxxxxxxxxxxxxxxxA370AC420090 ; replace
The 'x' pattern is only a place holder. Don't change any of those
values. They're just in there to make the search string unique for easy
location. Just change the last 6 bytes.
That's it for this lesson. Hope this was fun and instructional.
Disclaimer: THIS ESSAY IS FOR EDUCATIONAL PURPOSES ONLY. ANY USE,
MIS-USE OR ILLEGAL ACTIVITY IS THE SOLE RESPONSIBILITY OF THE READER.
GreetZ: Everyone in [ME97/C4N], PC97, UCF, fravia, gthorne, +ORC, Razzia!
drlan