Cracking for dummies - by fravia+
Lesson 2: 
"The difficult years" - Target: Netmed
(08 December 
1997 - version 0.01, will change)

Cracking and reverse engineering for those that 
have NEVER done something like this before
Reviews:
"Fravia's lessons demonstrate that cracking can be great fun!"
"For people that would like doing useful cracking in a matter of hours"
"Fravia+'s 'Cracking for dummies' is the perfect choice 
for those who want to use their programs in order to do what they want, 
not what the programmers wanted they to do with them"
              
Synopsis:
Expert +cracker and +ORC's student fravia+ builds on the success of his 
cracking essays, updating his discussions in a humorous fashion. 
His style helps to overcome the technical and non-intuitive 
barriers presented by cracking. The lessons show readers everything 
from how to 'dead list' a target to more advanced cracking tasks 
like 'feeling' concealed and encrypted protection schemes.
Price:
Nothing, nada, nichts... it's here and free for everyone, of course :-)
OK, enough kidding... I have decided to write an easy and GUIDED tutorial to 
software reverse engineering, aimed at all those among my 
readers that 
are interested yet AFRAID of the many 'technicalities' 
that 
are given for acquired inside the 'real' essays on the 
student pages (those essays of the +HCU 
Academy that 
are dedicated to a 'more mature' cracking audience). In fact
 I believe that 
our duty is not only to explain our science to those already 
able to follow it, but also to allow anybody who cares to join us.
These essays does not have ANY value for  
average or advanced crackers and are aimed 
EXCLUSIVELY at those 
among our readers that have NOT YET BEGONNEN any 
cracking or reverse engineering at all.
This said, you'll not be able to understand this lesson if you do
not 'work' a little. Some of the explanations and of the 
concepts that you have to learn may NOT be easy 
to assimilate, no matter how 'basically' explained.
If this happens, 
just read on, once you have got some more 'perspective' many 
of the 'barriers' that you encounter will suddenly 
disappear.   
Don't forget to read and assimilate lesson 1 before 
starting this.
GATHERING TARGET AND TOOLS FOR THE SECOND LESSON
You are about to begin a REVERSE ENGINEERING SESSION.
You need to PRINT this text, you need a PC-computer with 
windows95 installed, you need a 'target' and you need 
some tools in order to follow my lessons (tools are 
forever, like diamonds).
For this  second lesson you'll need, specifically, all tools described in 
lesson 1 (the "tekfact" lesson: wdasm, psedit and pkunzip) 
and two new programs
1) Base Calculator: an integer calculator 
with not only the usual operations 
such as addition and subtraction, but also the most common logical operations.  
In addition, Base Calculator can display 8 bit, 16 bit and 32 bit numbers, 
both signed and unsigned in decimal, hexadecimal, binary or octal. 
You can fetch it right off my site, here: 
bcalcns1.zip (148.156 bytes).
This program by John Zaitseff has been programmed in pascal (Delphi2) and 
is one of the best tools you'll use when you 
reverse engineer. It offers bin, hex, dec and octal calculations with XORing, 
ANDing, NOTing and 
whatever capabilities you need... you'll see and understand...  
For now just download it, unzip it and keep it ready for use.
2)	Netmedic. (Version 1.2). This is our target for this lesson: 
You'll be able to fetch it easily 
performing a ftp search.
Search 
for the strings 'nm.exe', 'netmedic' and 
'vitalsign' in this order.
The self-extracting trial shareware 
version 1.2 that we will use here as target has a length of 1.019.455 bytes
Alternatively you may fetch this target from vitalsign's own site at 
http://www.vitalsigns.com. They will release 
a new version very soon, of course, so harry up.
Netmedic is a PHANTASTIC tool for stalking activities, self-defense on the Web and net 
surfing, as you will soon discover. To navigate the deep sees of the web with this 
tool can be great fun, like being in 
the gauge and machine room of a huge ship every time you approach a site.
Its 
protection scheme, altough extremely easy to defeat, does indeed present some very 
interesting pecuilarities.
I checked (just in case) and found that this target 
has already been cracked by (at 
least) three different cracker groups.
You could easily fetch  all over 
the web a ready made 
de-protection, for 
instance its Phrozen Crew's patch...
But you will not do it, because 
you will never need any more these ready-made "patches for lamers".
You are already a cracker 
(in nuce) and therefore you are going to feel the code of your target, understand it
 and crack it all by yourself (and  in the mean time you will learn a lot, and you'll know 
what you have done and why :-)
OK, let's start: fetch netmedic and install it on your harddisk. 
Believe me: you'll love this 
target for the sheer MIGHT that it gives (offensive and defensive) to all internauts  
lost among the sees (and the currents) of the Web.
In fact you'll like netmedic so 
much that you'll probably want to 
register its next new version (which should deserve in my opinion a much more 
complicated protection scheme :-)
STARTING THE SESSION: string fishing
We could have tackled this protection scheme inside the code of our 
target in many other ways, like searching for the relative protection functions;  
pinpointing the protection scheme through a debugger (the easiest if most boring 
approach); getting the 
pixel dimensions of the protection window elements with a screen ruler, individuating 
the protection through a resource editor or even using a 
software 'stepwatch' (great fun for graphical demos deprotection :-)
But we will for this lesson -once more- use the SIMPLEST way: the approach you 
already began to 
learn with lesson one: string fishing.
Disassemble netmedic.exe
Run wdasm32 (by now you should have found on the web, or bought, version 8.9 of wdasm (see 
my first lesson). If you are still using the demo version, what follows applies nevertheless, 
yet you'll work on your target's code "on screen", using wdasm's own search capabilities, 
and not inside your texteditor, since the demo version of wdasm does not allow the editing
 and saving of the disassembled text file. Yet by the end of this lesson you should be enough 
'semi-advanced' in our reversing art to be able to work on the essays inside 
+HCU's project 0, where you'll find detailed instructions about 
transforming the demo version of wdasm in a full working version adding or modifying all 
disabled functions inside it. But wait, don't go there right now: 
you better finish this lesson first :-)
The disassembly of a windows95 program can easily result in a huge 
text file.
netmed.exe is a 1.016.832 bytes file, and wdasm89 -which I'm using as 
disassembler 
instead of the more powerful (but newbyes scaring) IDA 3.7. for these lessons- 
will give you a 11.927.177 bytes *.alf file: a dead listing that of 12 millions 
bytes, quite a monster. 
Of course you wont be able to handle well such a file inside Micro$oft Word, which is a 
very sloppy wordprocessor by whatever standards you might choose to use. 
I may suggest my personal 
choice working under Windoze: Ultraedit32.
 
You'll have the possibility to customize its toolbar with your own 'reversing' macros and 
it will be a lot quicker than Word. Moreover it will not crash and you'll be able 
to cut and paste code without 'loosing' your mouse grip on the window (a very peculiar 
and annoying 
characteristic of Micro$oft's abomination :-(
Choose a quiet evening and perform your string search, (using for instance 
"license" "evaluation" 
"expir"), see if something "bites" and once you think 
you have found enough, 
pull your nets out of the code and look at the many little poor zapping fishes you have 
caught:
:00406A1B 6817E20000 push 0000E217 ID=57879: "Your advanced feature trial license expires in 1 day." 
:00406A3A 6818E20000 push 0000E218 ID=57880: "Your advanced feature trial license expires in %d days."                                 |
:00406A87 6819E20000 push 0000E219 ID=57881: "Your advanced feature trial license has expired."                                         
:0043E901 6812E20000 push 0000E212 ID=57874: "Your evaluation period for Net.Medic has ended. 
:0043F21F 6835E20000 push 0000E235 ID=57909: "Your advanced feature trial license expires in %d day(s)
:0043F234 6840094A00 push 004A0940 Data Obj ->"Your license expires in %d days."
Whoa!  Even if something did slip 
through we have pulled a full net of strings out of our target's code! We will not hunger 
this evening!
Notice that we already know WHERE are located the protection code snippets: in fact 
we'll have a 
protection snippet around 06A and another one from 3E9 to 3F2!
Let's prepare and sip our cocktail and continue:
DISSECTIONING OUR FIRST FISH
Let's pull out the guts of the first one:00406A1B 6817E20000 push 0000E217 ID=57879: "Your advanced feature...expires in 1 day."
 
Before passing the protection code that dwells around this location under our 
serene 'reversing' blick (we will do it in a minute), we better understand 
first of all what's the 
meaning of the code that precedes those 6 strings above. Let's look at the instruction 
at location :00406A1B: 6817E20000
68 is push and 17E20000 is 0000E217 
(which corresponds, hexadecimally to the decimal value ID=57879).
 
Why the pushing around?
First: all the strings you see are being PUSHED on the stack because a subsequent call 
to a display function will need to know what to display on the screen. All the 
parameters for any subroutine function must be pushed (the call must be prepared) before 
executing the call, and the only (minor) question when you reverse is the ORDER of 
this pushing. In C language it is rightmost parameter first, 
in Pascal language the other way round.
Here we have a target written in C... 
well, sort of, they have used overbloated Micro$oft's "Visual" C++... 
would the authors have programmed with "real" C, 
this target would have been a lot 
smaller, yet some sort of degenerated C it is anyway,  
and therefore the LAST parameter is pushed first on the stack... how do I know that 
our target has been written and compiled with Micro$oft's VisualC++? 
Well, the code is typical, and that would be more than enough, but if you want to 
check on your own, just have a look at the list of IMPORTED FUNCTIONS (at the 
beginning of your dead listing) and you'll find the following: Import Module 009: 
MSVCRT40.dll... that's the (bad) Micro$oft's run-time library dll, as you'll see in 
a moment... back to our pushing parameters around:
The following 
code snippet (from our very target) shows you for instance the typical and very simple 
parameter passing for the ubiquitous messagebox function::00457586 6A00                    push 00000000             ;0, the rightmost parameter
:00457588 68541E4A00              push 004A1E54             ;Data Obj ->"Error"
:0045758D 68481E4A00              push 004A1E48             ;Data Obj ->"Print Error"
:00457592 6A00                    push 00000000             ;NULL, the leftmost parameter
:00457594 FF15A4864A00            Call dword ptr [004A86A4] ;USER32.MessageBoxA, Ord:0188h
Since the function MessageBox has 4 parameters, 
int MessageBox(hwndParent, lpszText, lpszTitle, fuStyle)
 you can see inside the target's code four pushes just before the call, so 
easy and simple is that.
The above code means therefore: 
MessageBoxA(NULL, Print Error, Error, 0)... in other words: 
"please draw a DialogBox without parent window (hwndParent=NULL) with the word 
 "Error" as title and the words "Print Error" as message text and with 
a nice little OK button!
 See, fuStyle is 0, and this 
correspond to MB_OK, and therefore this message box will contain only one 
push button with the tag OK written onto it... 
In fact you could modify this last parameter determining the "button", 
through your hexeditor, and  for instance substitute 
0x20 to the zero for the rightmost parameter. If you then re-run the program 
(and then cause a print error), 
 the modified line :00457586 6A20 would give you MB_ICONQUESTION instead of MB_OK, 
and a silly question-mark icon 
would in this case appear in the message box. Pretty cheap reversing 
thrills, in this specific case, 
yet I'm sure you are getting the point: 
substituting parameters inside alien code it's very easy and 
may be great fun!
Yet the 'MessageBox' 
explanation above is fully valid only for ONE of the above fishes: the last string at 
3F234, which is 
directly located inside our target's data::0043F234 6840094A00 push 004A0940 Data Obj ->"Your license expires in %d days."
So it pushes a string located inside the target, at A0940! 
Now -for this string- we will use psedit (or another hexeditor, see lesson1, the "tekfact" lesson) 
and search it "physically" inside the BYTES 
of our target, (I repeat: put now aside our disassembled wdasmed dead listing, 
and look at the bytes of netmed.exe).
Once we 
search for this string we find it at 9ED40:9ED40	596F7572206C6963656E736520657870 Your license exp
9ED50   6972657320696E20256420646179732E ires in %d days.
O mann_o_mann! 
Hey! It is not at A0940!ou use your brand new base calculator, that 
you should have downloaded and installed on your harddisk and notice a staggering 
difference of 1C00 bytes! What's going on? Where does this difference come from?
Man! I thought you just pushed  
the stupid data location for the call, getting thattaway the string you pushed for,  
automagically, appear! Hey fravia+, what's going on?
Quiet! I have the pleasure 
to introduce to you the subdivisions of all 
windozes' programs (in fact of ALL programs but the most tight ones): have a 
look at the TOP of your netmed's dead listing! The very first table you'll find there 
is the following 
one:
Number of Objects = 0007 (dec), Imagebase = 00400000h
   Object01: .text    RVA: 00001000 Offset: 00000400 Size: 00087400 Flags: 60000020
   Object02: .rdata   RVA: 00089000 Offset: 00087800 Size: 00014C00 Flags: 40000040
   Object03: .data    RVA: 0009E000 Offset: 0009C400 Size: 00006200 Flags: C0000040
   Object04: .idata   RVA: 000A7000 Offset: 000A2600 Size: 00002E00 Flags: C0000040
   Object05: .tls     RVA: 000AA000 Offset: 000A5400 Size: 00000200 Flags: C0000040
   Object06: .rsrc    RVA: 000AB000 Offset: 000A5600 Size: 00046A00 Flags: 40000040
   Object07: .reloc   RVA: 000F2000 Offset: 000EC000 Size: 0000C400 Flags: 42000040
So, netmed.exe has 7 objects. Don't worry about their names and exact meanings for yet, just 
remember that .text and .data are the two important (and standard) ones. .text is CODE 
and .data is DATA.
Now look: the Imagebase is at 400000 and the DATA (Object03), is at 
RVA 9E000 with offset 9C400.
And as you can easily check (using for instance 
your brand new basecalculator 
tool) once you take away the 
dummy 400000 of the Imagebase, the simple subtraction 0x9E000-0x9C400 gives us a 
difference of 1C00... Bingo! This little mistery is cleared.
Yet where are the other little zapping strings we have fished out?
STRINGTABLE VAGARIES
ALL the other protection strings inside 
our target's code (our zapping fishes) are in unicode (all the ascii characters 
have an interpolated null) and dwell at 
locations that (apparently) have nothing to do with the direct data 
locations pushed above... for instance, 
0xE217 (which is ID=57879) does NOT directly correspond to a code location... hey bud, what's that? Keep cool, just read on
:00406A1B 6817E20000    push 0000E217      ;Your advanced... license expires in 1 day."
What's "E217"? Some sort of european food component?
No. it's a stringtable pointer... see: 0xE217 is decimal 57879. Yet if we have look at 
the hexes of our target with an hexeditor... our string begins at 0xE8DFC... what's going on here?
E8DFA		                350059006F00           5.Y.o.
E8E00		7500720020006100640076006100  u.r. .a.d.v.a.n.
E8E10		6E00630065006400200066006500  c.e.d. .f.e.a.t.
...
Well: this is a pointer to the STRINGTABLE!
I'l show you a part of the stringtable of our target, which you could easily inspect 
using a resource monitor tool like BRW from Borland... you will learn how to use this 
very important 
reversing tool later studying the +HCU's essays, for the moment just have a look at this STRINGTABLE snippet):  
STRINGTABLE 
{
 57872, "Delay"
 57873, "Traffic"
 57874, "Your evaluation period for Net.Medic has ended. You can continue using 
 57875, "www.vitalsigns.com/buy/register.html"
 57876, "www.vitalsigns.com/buy/index.html"
 57877, "www.vitalsigns.com/tech/relnotes.html"
 57878, "www.vitalsigns.com/tech/index.html"
 57879, "Your advanced feature trial license expires in 1 day."
 57880, "Your advanced feature trial license expires in %d days."
 57881, "Your advanced feature trial license has expired."
 57882, "The feature you have requested is available only in the retail 
 57883, "Net.Medic from VitalSigns Software uses analysis techniques which 
 57884, "Some of the information above has been provided by Net.Medic from\r\nVitalSigns 
 57885, "Date and Time of Occurrence: "
 57886, "Date and Time of First Occurrence: "
 57887, "Date and Time of Last Occurrence: "
}
If we look at the data part of the target code we find above our string running from E8DFC 
(That's the "Y" of 
Your) to E8E66 (that's the full point after "day."). Look once more at the data dump 
above... at E8DFA, immediately before the "Y", 
we have a "3500": this is 0x0035, and represents the number of characters (it's decimal 
53) of 
our string 12345678901234567890123456789012345678901234567890123
 Your advanced feature trial license expires in 1 day.
So the real "block" is E8dfA-E8e65. And somewhere inside the code a TABLE translates 
the string number 57879 (0xE217) into a pointer to our location E8defA... where?
Well as you'll see, the MFC40 function "NoName" 185 is an equivalent of a 
LoadString function, and it works like this::00406A1B 6817E20000    push 0000E217      ;Your advanced... license expires in 1 day."
:00406A20 8D4DA8        lea ecx, dword ptr [ebp-58] ;prepare call
:00406A23 E8BC0C0800    Call 004876E4      ;MFC40:NoName0185, Ord:0E48h; call_this
This means: call MFC40:NoName0185 with a pre-determined cx and the stringtable ID pushed.
OK, we have seen enough, if you want to see what the cuckoo MFC40/185 does you know 
already what you have to do: just disassemble MFC40.DLL and look at the dead listing!
A string table consists of one or more separate resources, each containing exactly 16 
strings. The maximum length of each string is 255 bytes. One or more strings in a 
block can be null or empty. The first byte in the string specifies the number of 
characters in the string. (For null or empty strings, the first byte contains 
the value zero.)
 
Windows uses a 16-bit identifier to locate a string in a string-table resource.
 
Bits 4 through 15 specify the block in which the string appears;
 
bits 0 through 3 specify the location of that string relative to the beginning of the block.
 
Time to get back to our little fishes and crack them, before they get stale.
Sniffing the code
Let's have a look at the code where our first string 
"Your advanced... license expires in 1 day"
 is pushed for the call: as we have already noticed, part of the protection scheme 
MUST dwell around 00406Axx; here you have the relative code snippet, that I have commented 
for you. Don't worry too much right now, get this snippet on your screen (or on 
paper) as well and just try to follow:
* Referenced by a Jump at Address:069BF(C)
:069EC E8CF7D0100    call 0041E7C0      ;get PROT parameter good/bad guy  !!!!!!
:069F1 83C404        add esp, 4         ;correct stack after call
:069F4 898542FFFFFF  mov dword ptr [ebp+FFFFFF42], eax  ;save PROT parameter
:069FA 83F801        cmp eax, 1         ;is it one?
:069FD 757F          jne 00406A7E       ;go check if PROT is three, or what else
:069FF E83C800100    call 0041EA40      ;else PROT = one, call this function
:06A04 8BF8          mov edi, eax       ;and save in edi how many days this guys has left
:06A06 8D4DA8        lea ecx, dword ptr [ebp-58] ;and do whatever the following call
:06A09 E8CA0C0800    Call 004876D8      ;MFC40:NoName0183, Ord:01E6h, ;MFC40/183 does
:06A0E C645FC03      mov [ebp-04], 03   ;and flag with three [ebp-04]
:06A12 85F6          test esi, esi      ;and check esi
:06A14 7455          je 00406A6B        ;go flag [ebp-04] with 2, else
:06A16 83FF01        cmp edi, 1         ;does he have only one day left, the poor chap?
:06A19 751F          jne 00406A3A       ;no, then go calculate how many days left, else
:06A1B 6817E20000    push 0000E217      ;Your... license expires in 1 day"
:06A20 8D4DA8        lea ecx, dword ptr [ebp-58] ;prepare call
:06A23 E8BC0C0800    Call 004876E4      ;MFC40:NoName0185, Ord:0E48h; call MFC40/185
:06A28 85C0          test eax, eax      ;did it work?
:06A2A 7430          je 00406A5C        ;no:continue without ax/cx and without call213
:06A2C 8D45A8        lea eax, dword ptr [ebp-58]  ;yes get ax
:06A2F 8D4DF0        lea ecx, dword ptr [ebp-10]  ;yes get cx
:06A32 50            push eax           ;and use ax for the following call213
:06A33 E8480D0800    Call 00487780      ;MFC40:NoName0213, Ord:02F8h ;call MFC40/
:06A38 EB22          jmp 00406A5C       ;then continue
:let's tell you how many days you have left (from 6A19)
:00406A3A 6818E20000    push 0000E218      ;Your... license expires in %d days"
:00406A3F 8D4DA8        lea ecx, dword ptr [ebp-58]
:00406A42 E89D0C0800    Call 004876E4  ;MFC40.MFC40:NoName0185, Ord:0E48h
...
...
:check if parameter PROT is three (from 69FD):
:00406A7E 83BD42FFFFFF03    cmp dword ptr [ebp+FFFFFF42], 3  ;guy's parameter it's three
:00406A85 751C              jne 00406AA3                     ;if not three check what else it is
:00406A87 6819E20000        push 0000E219     ;and push "Your advanced license has expired"
:00406A8C 8D4DF0            lea ecx, dword ptr [ebp-10]      ;beggar off bad guy
....
Well, an impressive code snippet with not only one but THREE zapping strings!
We can already understand some easy elements of this protection. The scheme checks right at the 
beginning a protection PARAMETER, calling function 1E7C0 (that we will examine in a minute).
ON return we save the return value in [ebp+FFFFFF42] (which is [ebp-BE] probably). And chooses 
different strings depending from these values.
We know now that:
call 1E7C0 and get "kinda_guy" return value"
  if kinda _guy=1 then 
                    call 1EA40 and save in edi how many days this guy has left
                    call MFC40/143 and check esi return value 
                                                  and flag [EBP-4] with 2 or 3 accordingly
                             if the guy has 1 day tell him
                             else tell him how many days he has left
  if kinda_guy=3 then
                    tell the guy that his license his expired.
I would say that our work is already (almost) finished.
Let's examine the code at the call that triggers the whole "kinda_guy" value, 
we will surely learn more.
Where we will crack:
The following code snippet is the routine that rturns the "kinda_guy" parameter.
We already know that a value of 1 means a "time limited trial" and that a value of 
3 means that "your allowed time limit has expired". Well, an immediate legitime quastion for 
any researcher mind would be: "What about parameters "0", "2" and "4", "5", etcetera?
 In the code below of our kinda_guy routine, you'll see many calls to OTHER routines (of 
course) some of them are calls to MSVCRT40.DLL, like the following sscanf:
:first_sscanf(ax,%x,cx):
:0041E8A6 8B3D44854A00       mov edi, dword ptr [004A8544];MSVCRT40.sscanf, Ord:0442h
:0041E8AC C645C000           mov [ebp-40], 00             ;zeroing memory location [ebp-40]
:0041E8B0 51                 push ecx                     ;pass parameter cx for sscanf
:0041E8B1 68A4F54900         push 0049F5A4   ;->"%x"      ;pass parameter
:0041E8B6 52                 push edx                     ;pass parameter dx for sscanf
:0041E8B7 FFD7               call edi                     ;sscanf(dx,%x,cx)
Clearly you may legitimately ask what the cuckoo is going on here. Well, I told you that 
this target has been written with Microsoft Visual C++, and therefore read (and head) the 
following:
MSVCRT40 is "Microsoft C Runtime Library Version 4.10.6038" 
for  "Microsoft Visual C++", as you can see through any hexeditor inside the very code of 
this *.DLL.
What the cuckoo is a "runtime library"?
A run time library is a set of hundreds of predifined 
functions and macros, designed for use in C programs.
Run time libraries make programming (and cracking) easier, 
providing tne following:
- an interface to operating system functions (such as opening 
  and closing files)
- fast functions to perform common programming task (such as
  string manipulation, "sparing the programmer the time and 
  effort needed to write such functions".
Run time libraries are specially important in high level programming 
because all "high level" programmers rely on libraries for basic functions not 
provided by their languages: input and output, storage allocation, process 
control.
These C functions try to maintain a maximum system compatibility
between DOS, Xenix and Unix, and have mostly the same names in 
the C runtime libraries for Unix operating systems.
OK, let's have a look "inside" our MSVCRT40.DLL (you'll find a couple 
of them, at least, inside your own harddisk, disassemble one of them 
with wdasm (or IDA) and look, for instance, at the very simple 
_toupper function:
in c you would have:
int toupeer(c);		converts c to uppercase if appropriate
int _toupper(c);	converts c to uppercase
and therefore you would for instance use this kind of programming code:
if (islover(ch))
	printf("_toupper =%#04x", _toupper(ch));
Well, let's look at its implementation INSIDE our disassembled MSVCRT40.DLL:
Exported fn(): _toupper - Ord:036Fh
:10215450 8B442404                mov eax, dword ptr [esp+04]
:10215454 83E820                  sub eax, 00000020
:10215457 C3                      ret
This means: get passed parameter inside eax
            subtract 20h
            return home with subtracted parameter... 
and since fravia is (ASCII)     f  r  a  v  i  a
                               66 72 61 76 69 61
if I call _toupper six times, one for each letter, this will return me
                               46 52 41 56 49 41
which, as you have guessed is:
                                F  R  A  V  I  A
So easy is that (in assembly :-)
In fact it is so easy that one wonders why you should use twelwe bytes
to perform the same uppercasing (with a lot more CPU-cycles and a call 
to a DLL outside your main exe code):
 53                      push ebx                   ;throw lowercase char_value
 FF15C8854A00            Call dword ptr [004A85C8]  ;MSVCRT40.toupper, Ord:0461h
 83C404                  add esp, 00000004          ;correct stack
 8BD8                    mov ebx, eax               ;save uppercased returned char
instead of just using directly inside your program the three bytes: 
 83E820                  sub eax, 00000020          ;uppercase char in ax
...misteryes of high level languages, I presume. Multiply this for MUCH more 
complexes routines and MANY more bytes and you will quickly understand WHY the 
programs that you are using nowadays
-	are slow
-	crash
-	are huge
-	need powerful CPUs and a lot of memory
-	compel you to upgrade PC every two years
Let's look at our target's code now, it's time to CRACK!: 
Let's have a look at the routine returning the "kinda_guy" parameter:
this code snippet is CALLED from three different points (:004069EC, :0041ED0D, and :0043F1F1)
it has also to do with a Menu whose ident is [ID=807Fh], as you will easily see just perusing 
the routine, which starts at 41E7C0. Here follows ONLY the most interesting part of it for us, 
but if you examine ALL its code, you'll see that we have already had another important 
C++ functions: a strncpy and a sscanf(dx,%x,cx) and that now we come to the second 
sscanf function: sscanf(ax,%x,cx).
....(started at 1E7C0)
:0041E8BC 8D4DEC             lea ecx, dword ptr [ebp-14]  ;prepare cx for call
:0041E8BF 8D45B8             lea eax, dword ptr [ebp-48]  ;prepare ax for call
:0041E8C2 51                 push ecx		          ;pass parameter cx for sscanf
:0041E8C3 68A4F54900         push 0049F5A4   ;->"%x"      ;pass parameter
:0041E8C8 50                 push eax		          ;pass parameter
:0041E8C9 FFD7               call edi		          ;sscanf(ax,%x,cx)
:0041E8CB 83C40C             add esp, 0000000C            ;correct stack
:0041E8CE 8B45F0             mov eax, dword ptr [ebp-10]  ;get value
:0041E8D1 3501101000         xor eax, 00101001            ;xor it with 0010 1001
:0041E8D6 3B45EC             cmp eax, dword ptr [ebp-14]  ;is it like cx, once xored?
:0041E8D9 7521               jne 0041E8FC 		  ;No? Beggar off: EVIL JUMP
:0041E8DB C745FCFFFFFFFF     mov [ebp-04], FFFFFFFF	  ;dummy parameter
:0041E8E2 E831010000         call 0041EA18                ;dummy end call
:0041E8E7 B804000000         mov eax, 4                   ;GOOD "registered" FLAG ax=4
* MAIN EXIT: Jump at Addresses	:0041E916(U), :0041E936(U), :0041E968(U), 
				:0041E974(U), :0041E98A(U), :0041EA09(U)
:0041E8EC 8B4DF4                  mov ecx, dword ptr [ebp-0C]   ;poppall and exit
:0041E8EF 5F                      pop edi
:0041E8F0 64890D00000000          mov dword ptr fs:[00000000], ecx
:0041E8F7 5E                      pop esi
:0041E8F8 8BE5                    mov esp, ebp
:0041E8FA 5D                      pop ebp
:0041E8FB C3                      ret  				;RETURN after check
* Referenced by a Jump at Address:0041E8D9(C) EVIL JUMP 
:0041E8FC 833DA0F5490000          cmp dword ptr [0049F5A0], 0   ;d'we have a zero there?
:0041E903 7413                    je 0041E918			;if so go ahead and xor other things
:0041E905 C745FCFFFFFFFF          mov [ebp-04], FFFFFFFF 	;else  dummy parameter
:0041E90C E807010000              call 0041EA18			;      dummy end call
:0041E911 B801000000              mov eax, 00000001  		;trial FLAG ax=1
:0041E916 EBD4                    jmp 0041E8EC  		;RET WITH trial FLAG 1
* Referenced by a Jump at Address:0041E903(C) EVIL JUMP
:0041E918 8B45F0               mov eax, dword ptr [ebp-10]   ;clean and ready for xor once more
:0041E91B 3510101100           xor eax, 00111010             ;this time xor with 0011 1010
:0041E920 3B45EC               cmp eax, dword ptr [ebp-14]   ;is it, xored, like cx?
:0041E923 7513                 jne 0041E938                  ;No? Go ahead and xor 1101 1101
:0041E925 C745FCFFFFFFFF       mov [ebp-04], FFFFFFFF        ;else   dummy parameter
:0041E92C E8E7000000           call 0041EA18                 ;       dummy end call
:0041E931 B805000000           mov eax, 00000005             ;Not yet advanced funct flag 5
:0041E936 EBB4                 jmp 0041E8EC                  ;ret with bad flag ax=5
* Referenced by a Jump at Address:0041E923(C) EVIL JUMP
|
:0041E938 8B45F0               mov eax, dword ptr [ebp-10]   ;ready for xor once more
:0041E93B 3501110111           xor eax, 11011101             ;this time xor with 1101 1101
:0041E940 3B45EC               cmp eax, dword ptr [ebp-14]   ;is it, xored, like cx?
:0041E943 7534                 jne 0041E979                  ;if yes check time else ret with 
:0041E945 6A00                 push 00000000                 ;trial ax=1 and time unchecked
:0041E947 FF1548864A00         Call dword ptr [004A8648]     ;MSVCRT40.time, Ord:045Dh
:0041E94D 83C404               add esp, 00000004
:0041E950 2B45F0               sub eax, dword ptr [ebp-10]   ;number of second elapsed, subtracted
:0041E953 C745FCFFFFFFFF       mov [ebp-04], FFFFFFFF        ;       dummy parameter
:0041E95A 3BC6                 cmp eax, esi                  ;check if user has time or not
:0041E95C 760C                 jbe 0041E96A	             ;below, return with trial flag one
:0041E95E E8B5000000           call 0041EA18                 ;       dummy call
:0041E963 B803000000           mov eax, 3                    ;else return with flag ax=3:
:0041E968 EB82                 jmp 0041E8EC                  ;flag ax=3= no more time!
* Referenced by a Jump at Address:0041E95C(C)
|
:0041E96A E8A9000000              call 0041EA18    ;     dummy call
:0041E96F B801000000              mov eax, 1       ;trial FLAG 1: time not to be...
:0041E974 E973FFFFFF              jmp 0041E8EC     ;...checked or something: return 1 
* Referenced by a Jump at Address:0041E943(C)
|
:0041E979 C745FCFFFFFFFF          mov [ebp-04], FFFFFFFF    ;dummy parameter
:0041E980 E893000000              call 0041EA18             ;dummy call
:0041E985 B801000000              mov eax, 1                ;trial flag 1
:0041E98A E95DFFFFFF              jmp 0041E8EC              ;return with trial flag 1
OK, we can now experiment a little...
since the return flag of this function is important, you may want to see 
what happens when you return: 0, 2, 4 (just try it :-) and 5. (parameter fiddling).
The big question is of course: what is the sscanf above?
The sscanf function reads data from buffer into the locations given by each argument.
Every argument must be a pointer to a variable with a type that corresponds to a type 
specifier in format.
The sscanf function returns the NUMBER of fields that were successfully converted 
and assigned. The return value does not include the fields that were read but 
not assigned.
The return value is EOF for an attempt to read at end of string
A return value of ZERO means that no fields were assigned
among other things sscanf calls _isctype and isspace!
isspace is a test for white space chars (0x9, 0xD, 0x20)
_isctype is a test for integer values in an ASCII environment
(alphanumeric, letters or ASCII)
So we have here the part of the target code that checks if the name and 
the serial number you have entered are or, are not, valid.
Actually, to be simple, sscanf goes into a string and interprets it according 
to the format specifications... let's seay you want for instance to  
convert a STRING OF DIGITS INTO AN INTEGER (typical of password protections :-)
In that case you would write in C:sscanf (char_array_digitz, "%d",&intstorez);
this statement will convert the string of digits held inside the array of type char 
into type int, and store it into the variable intstorez
Well, if you want to learn 
more you'll find many resources about C language (and sscanf) online... just read on!
You'll notice that we have THREE xoring operations inside the code above: it work like this:
          8B45F0             mov eax, dword ptr [ebp-10]  ;get value
:0041E8D1 3501101000         xor eax, 00101001            ;1) here xor it with 0x00101001
:0041E91B 3510101100         xor eax, 00111010            ;2) here xor it with 0x00111010
:0041E93B 3501110111         xor eax, 11011101            ;3) here xor it with 0x11011101
          3B45EC             cmp eax, dword ptr [ebp-14]  ;[ebp-14] like xored [ebp-10]?
XOR is a "logical" operation, like and, not and all the other 
that you'll learn if you continue on your cracking path.
You take the bits of your 
two operands and check, each bit of the resultant dword is set to 1 ONLY if the corrisponding 
bits of the two operands contain opposite values.
So, first of all the three right operands of our three XORs are HEXADECIMAL values, in a
"binary-similar" format: 0x00101001, 0x00111010, 0x11011101.
(Watch it when you will search for these instructions inside the listing, there 
are two occurrences inside our target, and the second one is the correct one, as you'll 
notice if you acquire the GOOD practice of ALWAYS checking the code "around" your search 
strings)!
At your base calculator! Use hexadecimaml values and xore them, and see how 
they see out in binary (and how the xoring affects the bits!)
In my case we have always Ox34829AB7 inside [ebp-10]
which, xored with 0x01101000 unfortunately does not give
0x25838bb6 (the value that I always had inside [ebp-14]... therefore we are 
unfortunately NOT REGISTERED!
This Ox34829AB7 that we have inside [ebp-10]
xored with 0x10101100 (at the second check) does not give either
0x25838bb6 any more (it would have done it at the beginning, by the first run of our target) 
therefore we don't get flag 5 and that means that we have CHOSEN THE SPECIAL advanced features 
option!
Finally, our Ox34829AB7, that we have inside [ebp-10]
xored with the third xoring choice: 0x01110111 does indeed
give us 0x25838bb6 therefore we have snapped the advanced features and 
we are running the trial time flag.
What do we learn from this, besides using our base calculator?
1) That the only thing that matter is to get flag 4, therefore we just need to xor with 
0x01110111 at the FIRST occurrence to have it every time!
2) That even xoring with 0x01110111 at the SECOND OCCURRENCE would be good, since we would 
have 'just started' flag 5 every time.
3) That the only thing we really don't need is xoring 0x01110111 at the third xoring 
occurrence, since that's the "normal" trial period checking.
4) That this protection is incredibly lame and that the programmer should NEVER have 
included a 'registering' flag inside the target.
In order to crack the above target you may of course now 
choose HUNDRED different solutions, and you may apply the crack wherever you want 
inside the get the flag subroutine.
Now that you have seen the protection scheme naked, try to work a little on this using 
the DEBUGGER that you have downloaded for the previous "tekfact" lesson (iwindebug).
Set some location breakpoints just before the xores above, and follow in the register 
window (and in the memory windows) what's going on. You'll have a taste of the 'live' 
approach to cracking, that we will use in the next lessons. Dead listing and live approach 
together can reverse ANY code you will encounter on your way, even if it has been written on 
Mars (or at Micro$oft :-)
I showed you enough, I'm not going to give you ANY ready made solution to crack this 
target, you 
don't need it any more. In fact I will never give ready made cracks again, you are (gonna be) 
real crackers: you don't need people chewing code for you and spitting out ready made solutions 
any more! Reread this lesson, experiment a little and crack this target on 
your own, it's very easy (now).
Well, I reckon that's enough for this second lesson.
(c) fravia+ December 1997. All rights reserved. 
WATCH IT, THIS LESSON IS STILL UNDER CONSTRUCTION!   
 
You are deep inside fravia's page of reverse engineering,  
choose your way out:
           
homepage
links 
anonymity 
+ORC
students' essays
academy database
tools
cocktails
antismut CGI-scripts
search_forms
mail_fravia
Is reverse engineering legal?