9217 lines
292 KiB
Plaintext
9217 lines
292 KiB
Plaintext
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
--------------------------------------------------------------
|
||
|
||
(Htocrk10.txt) Lesson 1: an approach
|
||
|
||
(Htocrk20.txt) Lesson 2: tools and tricks of the trade
|
||
|
||
(Htocrk31.txt) Lesson 3.1: hands on, paper protections (1)
|
||
|
||
(Htocrk32.txt) Lesson 3.2: hands on, paper protections (2)
|
||
|
||
(Htocrk51.txt) Lesson 5.1: disk & CD-Rom access (basics)
|
||
|
||
(Htocrk61.txt) Lesson 6.1: funny tricks
|
||
|
||
(Htocrk81.txt) Lesson 8.1: how to crack Windows, an approach
|
||
|
||
(Htocrk82.txt) Lesson 8.2: how to crack Windows, a deeper approach
|
||
|
||
(Htocrk91.txt) Lesson 9.1: how to crack Windows, hands on
|
||
|
||
(Htocrka1.txt) Lesson A.1: advanced cracking: internet cracking (Unix)
|
||
|
||
(Htocrkc1.txt) Lesson C.1: how to crack, cracking as an art
|
||
|
||
(Htocrkc2.txt) Lesson C.2: how to crack, cracking as an art HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 1: an approach
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[Pooldemo.exe]
|
||
|
||
--------------------------------------
|
||
|
||
The best way to learn cracking (i.e. understanding, broadly
|
||
|
||
individuating, locating exactly and eliminating or suspending or
|
||
|
||
deferring one or more protection schemes inside a software
|
||
|
||
application you do not possess the source code of) is to begin
|
||
|
||
your tampering experiments using OLDER applications which have
|
||
|
||
OLDER protection schemes.
|
||
|
||
In this way you 'll quickly grasp the base techniques of the
|
||
|
||
trade. Do not forget that the evolution of the protection schemes
|
||
|
||
has not been a one way road... strictly speaking it's not even
|
||
|
||
an evolution: you'll eventually find some very clever new tricks,
|
||
|
||
but most of the time you 'll unearth only various trite
|
||
|
||
repetitions of past (and well known) tricks. This is no wonder:
|
||
|
||
the REAL knowledge of the "commercial" programmers themselves
|
||
|
||
(the "protectionists") is often very limited indeed: they are
|
||
|
||
inclined to use the old methods (albeit somehow changed,
|
||
|
||
sometimes even improved) instead of conceiving new methods. This
|
||
|
||
typical "commercial" degeneration happens every time people act
|
||
|
||
for money instead of doing things for the sake of it or for
|
||
|
||
pleasure. This "commercial" trend is blindly encouraged by the
|
||
|
||
stupid, money-oriented society we are coerced to live in.
|
||
|
||
So I'll begin the "hands on" part (-> starting from lesson
|
||
|
||
3), using as examples, some "old" applications and some "old"
|
||
|
||
tricks. We'll be able to come later over to the newest protection
|
||
|
||
schemes in order to understand them, and you 'll learn how to
|
||
|
||
defeat this kind of junk too. I'll also explain WHERE you can
|
||
|
||
find a lot of programs to crack for next to no money at all, and
|
||
|
||
HOW 'grossomodo', you should proceed in your work.
|
||
|
||
This tutorial is for people who are getting started with
|
||
|
||
cracking. Maybe you are just contemplating doing some cracking,
|
||
|
||
maybe you have tried it with mixed success. If you are here to
|
||
|
||
get aimed in the right direction, to get off to a good start with
|
||
|
||
the cracking tricks and procedures, then you have come for the
|
||
|
||
right reason. I can't promise you'll get what you want, but I'll
|
||
|
||
do my best. On the other hand, if you have already turned out
|
||
|
||
some working cracking code in assembler and already cracked many
|
||
|
||
different protection schemes, then this tutorial is likely to be
|
||
|
||
on the elementary side for you. (If you want to review a few
|
||
|
||
basics and have no where else pressing to go, then by all means
|
||
|
||
stay).
|
||
|
||
In order to crack successfully you need four basic things:
|
||
|
||
* A passing knowledge of assembler language (the more you
|
||
|
||
know, the better and quicker you crack)
|
||
|
||
* Some intuition
|
||
|
||
* Some help from more experienced cracker
|
||
|
||
* A non mercantile mind (more about this later)
|
||
|
||
The applications you'll use to learn with can be divided into:
|
||
|
||
1 - Password crippled applications (the easiest to crack)
|
||
|
||
2 - applications crippled on how many times, or how many
|
||
|
||
days, you use them (fairly easy to crack)
|
||
|
||
3 - applications crippled on which date you use them before
|
||
|
||
(easy to crack)
|
||
|
||
4 - applications that have some functions present but
|
||
|
||
disabled (sometimes easy, sometimes difficult)
|
||
|
||
5 - applications crippled on Disk access (protections schemes
|
||
|
||
that are now defined as "obsolete") and applications
|
||
|
||
crippled on
|
||
|
||
CD-ROM presence (more or less the same methods, but -
|
||
|
||
somehow- not defined as "obsolete") (very easy to crack)
|
||
|
||
6 - CRYPTOGRAFED ADDS ON (i.e. one of the previous protection
|
||
|
||
schemes, but with some scrambled or self modifying code
|
||
|
||
(XORring and SHRLing codes) (fairly easy to crack)
|
||
|
||
7 - None of the above (sometimes difficult to crack)
|
||
|
||
WHERE TO GET THE STUFF
|
||
|
||
The recent widespread appearance of "Demo"-CDROM on magazine
|
||
|
||
covers is a treasure for all crackers! A short time after their
|
||
|
||
release you 'll get all the copies that remain unsold for next
|
||
|
||
to free. The demos on CD-ROMs will permit you to gather quickly
|
||
|
||
a lot of applications -old and new- that have somehow been
|
||
|
||
crippled (at times with interesting schemes). Truly a wonderful
|
||
|
||
world of cracking possibilities! Gee! For next to no money you
|
||
|
||
can secure on one CDROM the whole of LOTUS applications (or
|
||
|
||
Microsoft or Wordperfect, or you name them) on "trial for 30
|
||
|
||
days" or "try it 20 times" editions. You'll really enjoy to crack
|
||
|
||
them, to use them for ever and ever and/or graciously donate them
|
||
|
||
on the Web to the poor lamers that have no money and no brain.
|
||
|
||
GAMES are definitely not to be frowned upon! They are
|
||
|
||
very interesting from a cracker prospective coz they are often
|
||
|
||
"overprotected". With this I mean that they possess protection
|
||
|
||
schemes of a relatively HIGH level hidden inside files that are
|
||
|
||
relatively small. Now, see, it is much more easy, and simple, to
|
||
|
||
track down and eliminate protection schemes inside a single
|
||
|
||
35.000 bytes long executable file than to locate them inside a
|
||
|
||
collection of many lengthy DLLs and overlaids that could have
|
||
|
||
swollen as long as 2.000.000 bytes each. The lazy bunch of
|
||
|
||
"modern" programmers relies systematically for protection schemes
|
||
|
||
on this "hide the sting in the wide desert" logic. As a matter
|
||
|
||
of fact they are no longer able to program in assembler: they
|
||
|
||
bank more and more on overbloated "fatty" atrocities like Visual
|
||
|
||
Basic, Delphy or Visual C++. (Don't worry... I'll nevertheless
|
||
|
||
teach you how to crack -and quickly- those huge applications
|
||
|
||
too).
|
||
|
||
There is another reason for employing games instead of
|
||
|
||
applications as study material: often EXACTLY THE SAME protection
|
||
|
||
schemes that you find in a simple (and short) shareware game will
|
||
|
||
be used -without much improving- a little later in order to
|
||
|
||
"protect" some huge and extremely expensive graphic application.
|
||
|
||
For this reason in my tutorial we'll often crack games
|
||
|
||
protection schemes, even if we'll later apply what we learn
|
||
|
||
mainly in order to crack the protection schemes of commercial
|
||
|
||
applications, or to crack the access protection routines to
|
||
|
||
remote servers, or BBS, or even ATM (cash dispensers).
|
||
|
||
Here follows an example cracking session, that will show you
|
||
|
||
-I hope- the dos and donts of our art: let's crack together as
|
||
|
||
introductory example a time crippled application. We'll learn
|
||
|
||
later (-> LESSON 4) that all applications that are crippled on
|
||
|
||
time (i.e. "how many times" you use them or "how long" you use
|
||
|
||
them) rely on analogous protection schemes (albeit with a huge
|
||
|
||
palette of small variations):
|
||
|
||
1- they may have a counter which "clicks" every so often: FIND
|
||
|
||
IT AND DISABLE IT!
|
||
|
||
2- they may fetch the time_clock interrupts in your machine:
|
||
|
||
INTERCEPT THEM YOURSELF!
|
||
|
||
3- they may compare a random_seed with a variable: NOOP IT!
|
||
|
||
4- they may check randomly the date of your other, unrelated,
|
||
|
||
files on the hard disk: find this verification routine and
|
||
|
||
INVERT the JUMPS!
|
||
|
||
I wanted to start with a modern example of this "counter clicks"
|
||
|
||
protection type, just to give you a feeling for cracking, and I
|
||
|
||
have chosen a widely published demo: you should be able to find
|
||
|
||
it pretty easily. In order to show you some of the problems you
|
||
|
||
may encounter we'll crack this example "wrongly" (you'll learn
|
||
|
||
how to crack effectively in the "HANDS ON" lessons).
|
||
|
||
EXAMPLE: ARCADE POOL, Demonstration version, PC Conversion
|
||
|
||
by East Point Software Ltd, (c) Team 17 Software Ltd 1994. This
|
||
|
||
demo has been published by many magazines on their CDRom covers
|
||
|
||
throughout 1995.
|
||
|
||
What follows will be useful even if you do not have our
|
||
|
||
example; nevertheless you should get a copy of this widespread
|
||
|
||
demo in order to better grasp some of the following points.
|
||
|
||
This nice demo of a billiard game is time-crippled. It is
|
||
|
||
crippled on how long you use it: i.e., you can only play 2
|
||
|
||
minutes, afterwards a "nag" reminder of where and how you can buy
|
||
|
||
the real version snaps: protectionist squalor at its best.
|
||
|
||
So, how do you proceed? Where does the beginning begin?
|
||
|
||
Here is what you could (but not necessarily should) do:
|
||
|
||
Get [Soft-ice] and load it in your config.sys. See the TOOLS
|
||
|
||
OF THE TRADE lesson (-> LESSON 2) about this debugger. Version
|
||
|
||
2.6 of [Soft-Ice] has been cracked by MARQUIS DE SOIREE and can
|
||
|
||
be found on the Web for free.
|
||
|
||
- vecs s (save all the vectors before loading the babe)
|
||
|
||
- start [pooldemo.exe]
|
||
|
||
- vecs c (vector compare, save a printing of all hooked
|
||
|
||
vectors)
|
||
|
||
- enter and leave Soft-ice a few times to understand what's
|
||
|
||
going on and where in [pooldemo.exe] are we roaming around
|
||
|
||
(you should always check MORE THAN ONCE your findings when
|
||
|
||
you snoop around: nothing moves and confuses pointers in a
|
||
|
||
more frenzied way than good old "inactive" DOS).
|
||
|
||
- have a good look at the map of memory usage ("map")
|
||
|
||
- now "snap_save" the main memory regions where
|
||
|
||
[pooldemo.exe] dwells... snapping saves "photographs" of
|
||
|
||
memory areas.
|
||
|
||
- do not do anything, let just the seconds go by.
|
||
|
||
- "snap_compare" every two or three seconds without moving
|
||
|
||
anything at all on the game board (no mouse_clicking,
|
||
|
||
NOTHING), so that the only changes are (hopefully) the
|
||
|
||
changes caused by the time counters.
|
||
|
||
- snap_compare twice in a second.
|
||
|
||
- snap_compare at second 00:59 and at second 1:01.
|
||
|
||
- snap_compare just before and just after the time limit and
|
||
|
||
the snapping of the nag screen.
|
||
|
||
- Now collect carefully your printed "snaps" data: write
|
||
|
||
clearly on the various sheets the occurrences of the snaps.
|
||
|
||
- now comes the graceful "zen-cracking" moment: Sit down with
|
||
|
||
a dry Martini and Wodka (obviously only russian Wodka will
|
||
|
||
do) and contemplate the printing of the various mutant
|
||
|
||
locations. Feel, perceive, empathize! Look closely at the
|
||
|
||
locations that have changed in the snap compares. Analyze,
|
||
|
||
interpretate, evaluate.
|
||
|
||
- Mmm! Hey! Something fishy is changing there, and there, and
|
||
|
||
there! (you are lucky, few do actually change in this case:
|
||
|
||
only two dozen)
|
||
|
||
- breakpoint on execute at the location that you believe act
|
||
|
||
as a "continuous" counter, i.e. the location that triggers
|
||
|
||
the "a second went by" event when it zeroes.
|
||
|
||
- Now set the occurrence counter of BPX in order to break at
|
||
|
||
the moment where the location "refills" and restarts from
|
||
|
||
the beginning (the equivalent of "one second" went by,
|
||
|
||
let's start anew). Use the occurrence counter in order not
|
||
|
||
to single-step through the program your life long!
|
||
|
||
- IN THIS CASE you 'll quickly locate the refill at location
|
||
|
||
3DD0. Here follows the "refill" line:
|
||
|
||
xxxx:3DCC C706F1013C00 MOV WORD PTR [01F1], 003C
|
||
|
||
The "3C" byte at xxxx:3DD0 represents a counter_byte... i.e. the
|
||
|
||
program "charges" 3C in this location and then DECs it step by
|
||
|
||
step to 3B, 3A, 39, 38 etc... till 0. When it reaches 0: bingo!
|
||
|
||
Sucker user has lost one second more of his precious two minutes.
|
||
|
||
Now, you would get a first wizard level if you searched
|
||
|
||
further on for the exact point where you get the "nag screen" in
|
||
|
||
order to eliminate the whole witless protection, but you may
|
||
|
||
think you got it already and you remember anyway that the first
|
||
|
||
principle in cracking is the following: "once you can eliminate
|
||
|
||
the effects of a protection, do not look further!"
|
||
|
||
Most of the time this is true: you do not always need to
|
||
|
||
eliminate a "whole" protection scheme (unless you are just
|
||
|
||
studying it for the joy of it). It's normally easier (and
|
||
|
||
quicker) to eliminate the "effects" of a given protection scheme.
|
||
|
||
Unfortunately this is not true in this case.
|
||
|
||
Here you believe that you have already found the way: you
|
||
|
||
got the counter that charges the reverse clock that triggers the
|
||
|
||
particular protection scheme of [pooldemo.exe]. Now you may think
|
||
|
||
that if you could modify the refill_value... say changing "3C"
|
||
|
||
to "EE" (Yeah, the maximum would be FF... but it's always good
|
||
|
||
practice to avoid such extreme values when cracking) you should
|
||
|
||
get four times more playtime for your game... more than enough
|
||
|
||
in order to make the protection scheme useless.
|
||
|
||
So you change location xxxx:3DD0 from "3C" to "EE". To work
|
||
|
||
on bytes you should use a good Hexeditor like PSEDIT (Parity
|
||
|
||
solutions, [Psedit.exe], brilliant shareware: see the "tool of
|
||
|
||
the trade" section) but you could also work with simpler
|
||
|
||
debuggers like [debug] or [symdeb] (-> see lesson 2). If you do,
|
||
|
||
remember to work on a "dead" copy of your crippled [*.exe] file,
|
||
|
||
i.e.:
|
||
|
||
ren POOLDEMO.EXE POOLDEMO.DED
|
||
|
||
symdeb POOLDEMO.DED
|
||
|
||
-s (cs+0000):0 Lffff C7 06 F1 01 C3 <- this string
|
||
|
||
corresponds to the
|
||
|
||
refill line).
|
||
|
||
cs:3E85 <- symdeb gives you two locations as answer
|
||
|
||
cs:3EEA
|
||
|
||
-e cs:3E85+4 EE <- refill changed from C3 to EE
|
||
|
||
-w
|
||
|
||
ren POOLDEMO.DED POOLDEMO.EXE
|
||
|
||
Now you run your tampered pooldemo. You think you cracked it, you
|
||
|
||
glee with satisfaction... but loo! Nothing at all has changed,
|
||
|
||
everything's as lame as before, you still have only 2 minutes
|
||
|
||
playtime. How disappointing: how comez it didn't work?
|
||
|
||
Well, for a start you have not been attentive enough! The
|
||
|
||
search in debug gave you TWO locations, you moron, and not just
|
||
|
||
the one you just tampered with. Check and you 'll see that the
|
||
|
||
second location (cs:3EEA) is a MIRROR/CONTROL location (more on
|
||
|
||
this later). Some times there exist "double" locations... coz at
|
||
|
||
times it's quicker to use a double routine than to use a
|
||
|
||
branching if or switch structure... some times the second
|
||
|
||
locations do mirror the first ones and correct them on the fly
|
||
|
||
if need be.
|
||
|
||
So you need to modify this too... you act as said above but
|
||
|
||
this time you enter in debug a
|
||
|
||
-e cs:3EEA+4 EE
|
||
|
||
before writing back the dead file and then renaming it to exe and
|
||
|
||
then running it... and loo! Hoow sloow! THERE YOU ARE! Your
|
||
|
||
crippled POOLDEMO.EXE is now (sort of) unprotected: You think
|
||
|
||
that you can now play the stupid game up to 12 minutes real time,
|
||
|
||
even if the protection scheme (and the counter) "believes" that
|
||
|
||
it is playing only two minutes.
|
||
|
||
So you begin to play, and the seconds look veeery sloow, and
|
||
|
||
everything seems OK, but -alas- NO! At screen second 28 you get
|
||
|
||
the irritating "two minutes are over" nag screen! Obviously you
|
||
|
||
were dead wrong: the program "knows" the time directly from the
|
||
|
||
timer... you only modified the stupid counter ON THE SCREEN.
|
||
|
||
So it's back to cracking, and now you are angry, and forget
|
||
|
||
the quiet ways of the zen-analyze and begin the heavy cracking
|
||
|
||
you should reserve -if ever- for really complicated schemes. You
|
||
|
||
now start to check the hooked vectors (you did your routinely
|
||
|
||
VECS_save before loading pooldemo in [Soft-ice] and your
|
||
|
||
VECS_compare afterwards) and you see some findings that you
|
||
|
||
believe interesting:
|
||
|
||
vecs c
|
||
|
||
08 1EFD:84C6 0CD1:17AC <- the clock
|
||
|
||
09 1EFD:85EC 136A:069C <- the keyboard
|
||
|
||
22 0BCE:02B1 0BCE:017E <- the terminate
|
||
|
||
That's more like it -you think. Smack at the beginning: the
|
||
|
||
first hooked vector does it! It's good old interrupt_08: the
|
||
|
||
timer_clicker!
|
||
|
||
Some basics for those of you that do not know anything:
|
||
|
||
INT_08 controls indirectly the INT_1C timer interrupt. The 8253
|
||
|
||
clock chip generates an IRQ_0 hardware interrupt at a rate of
|
||
|
||
18.2 interrupts per second. This gives control to the ISR
|
||
|
||
(Interrupt Service Routine) that the INT_08 points to... and this
|
||
|
||
should be at 0CD1:17AC, but has been hooked here, by pooldemo,
|
||
|
||
to 1EFD:84C6.
|
||
|
||
One of the actions taken by the INT_08 ISR within the BIOS
|
||
|
||
is to issue a software interrupt call to INT_1C, just in case any
|
||
|
||
software modules within the system have established an intercept.
|
||
|
||
If no intercepts have been established, the default contents of
|
||
|
||
the INT_1C vector point to an iret instruction within the BIOS,
|
||
|
||
so that a null action results.
|
||
|
||
Normally a protectionist would intercept INT_1C, coz at
|
||
|
||
every ISR from INT_08 the CPU would fetch the contents of the
|
||
|
||
corresponding interrupt vector and make an interrupt style call
|
||
|
||
to the code at that address (which should contain the iret at
|
||
|
||
address F000:9876 but can contain any trick they could think of).
|
||
|
||
So -you think- the protectionist hooked here INT_08 directly
|
||
|
||
(a pretty infrequently used protection scheme by the way): What
|
||
|
||
now?
|
||
|
||
A rather drastic measure would be, in such circumstances,
|
||
|
||
to
|
||
|
||
disable the IRQ_0 level timer interrupt, which is controlled by
|
||
|
||
bit 0 of the mask register, at address I/O 0021h. When bit 0
|
||
|
||
within the mask register is set to 1, no further interrupts will
|
||
|
||
be recognized for this IRQ level. This unfortunately won't work
|
||
|
||
here, but it's an interesting technique per se, so you better
|
||
|
||
learn it anyway, just in case you should need it elsewhere:
|
||
|
||
--- Trick to disable the timer ("IRQ_0 masking" by +ORC) ---
|
||
|
||
* prompt $t and hit ENTER a few times, see how the dos_clock
|
||
|
||
is merrily ticking along?
|
||
|
||
* enter DEBUG.COM
|
||
|
||
* Assemble using the command 'a'
|
||
|
||
- a
|
||
|
||
in al,21
|
||
|
||
or al,1
|
||
|
||
out 21,al
|
||
|
||
ret
|
||
|
||
RETURN
|
||
|
||
RETURN <- twice to exit immediate assembler
|
||
|
||
- g 100 <- to run the tiny program.
|
||
|
||
- q <- to quit debug.
|
||
|
||
prompt $t is still on: hit ENTER a few times:
|
||
|
||
whoa! The clock has stopped advancing!
|
||
|
||
Compliments: you loaded the current mask register's contents
|
||
|
||
into AL, you set the mask bit in the bit 0 position (which
|
||
|
||
corresponds to IRQ_0) at then updated the value back to the mask
|
||
|
||
register.
|
||
|
||
When you are ready to activate IRQ_0 events again, reenter DEBUG,
|
||
|
||
run the following and then reset the clock you stopped with DOS
|
||
|
||
TIME command:
|
||
|
||
- a
|
||
|
||
in al,21
|
||
|
||
and al,fe
|
||
|
||
out 21,al
|
||
|
||
ret
|
||
|
||
RETURN twice
|
||
|
||
- g 100
|
||
|
||
- q
|
||
|
||
A word of caution: with the timer click disabled some processes
|
||
|
||
will not operate correctly: once you access the diskette drive,
|
||
|
||
the motor will continue to run indefinitely afterwards, etcetera.
|
||
|
||
-------------------------------------------------------
|
||
|
||
Unfortunately the above technique cannot work with our
|
||
|
||
[pooldemo.exe], where you now are looking closely to the INT_08
|
||
|
||
hook you found, believing that it hides the protection scheme:
|
||
|
||
herein you find immediately the EoI (End_of_interrupt: MOV
|
||
|
||
AL,20h... OUT 20h,AL). Both controllers have a second port
|
||
|
||
address at 20h (or 0a0h), from which the instructions are given.
|
||
|
||
The most important is the EoI command (20h). This instruction
|
||
|
||
indicates the end of the interrupt handler and frees up the
|
||
|
||
corresponding controller for the next interrupt. If somebody
|
||
|
||
writes a new custom interrupt handler (as many protectionists
|
||
|
||
do), it's up to him to see to it that at the end of the handler
|
||
|
||
the EoI command (20h) is written to either port 20h or port 0a0h.
|
||
|
||
After the EoI follow the usual pushes, then some CALLS then
|
||
|
||
a call that issues some OUT 40,AL that look like timer refreshing
|
||
|
||
(OUT transfers data to an output port and ports 40-42 correspond
|
||
|
||
to the Timer/counter). Some do_maintenance follows, then a double
|
||
|
||
CALL, one more conditional CALL and then a "mysterious" call FAR
|
||
|
||
CS:[AA91] on which depends a byte PTR[970C] that decides another
|
||
|
||
final CALL... then the routine pops all registers and irets away.
|
||
|
||
Ah! You say, and begin disassembling, reverse engineering
|
||
|
||
and looking inside each suspect call (the quicker method in
|
||
|
||
these cases is to breakpoint calls on entrance and see if you
|
||
|
||
find the one that's only called at the awakening of the time
|
||
|
||
limit protection).
|
||
|
||
You work, and work, and work... and eventually find nothing
|
||
|
||
at all, coz the protection of this program is NOT HERE!
|
||
|
||
Back to the zen-analyze of the snap printings... we forsake
|
||
|
||
it too soon, as you will see.
|
||
|
||
If you watch with more attention the compare locations for
|
||
|
||
the range DS:0 DS:FFFF you 'll notice that one of them changes
|
||
|
||
relatively slowly from 0 to 1 to 2 to 3 and so on... the
|
||
|
||
precedent location changes very quickly, and runs the complete
|
||
|
||
cycle 0...FF. That's a counter, at locations DS:0009 and DS:000A!
|
||
|
||
How long will it tick along? Well, we saw above that the "charge"
|
||
|
||
every second is 3C, so it will be x3C*x78=x1C20, coz x78 is 120
|
||
|
||
seconds, i.e. the two minutes time limit.
|
||
|
||
Now search this 1C20 value around inside the code
|
||
|
||
(protections are most of the time at the beginning of the
|
||
|
||
CS:offset section), and you 'll find quickly what follows:
|
||
|
||
The protection in [pooldemo.exe] is at code_locations
|
||
|
||
CS:0A8A 813E20A7201C CMP WORD PTR [A720], 1C20
|
||
|
||
compare location A720 with limit 1C20
|
||
|
||
CS:0A90 7C07 JL okay_play_a_little_more
|
||
|
||
CS:0A92 E834FD CALL beggar_off_time_is_up
|
||
|
||
BINGO!: FOUND!
|
||
|
||
Now let's quickly crack it:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING POOLDEMO.EXE (by +ORC, January 1996)
|
||
|
||
ren pooldemo.exe pooldemo.ded
|
||
|
||
symdeb pooldemo.ded
|
||
|
||
- s cs:0 Lffff 81 3E 20 A7 20 1C
|
||
|
||
xxxx:yyyy <- this is the answer of the debugger
|
||
|
||
- e xxxx:yyyy+5 4C <- this time limit is much better
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren pooldemo.ded pooldemo.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
We have done here a "weak" crack: we limited ourselves to
|
||
|
||
accept a (better) time limit, changing it from 1C20 to 4C20 (4
|
||
|
||
minutes instead of two). We could obviously have done a more
|
||
|
||
radical crack if we had changed the JL (jump lower) instruction
|
||
|
||
in a JMP (jump anyway) instruction. In this case it would have
|
||
|
||
worked, but for reasons that will be explained in lesson 4, you
|
||
|
||
should choose a rather delicate approach in cracking when you
|
||
|
||
deal with time-limit protection schemes.
|
||
|
||
As you have seen, in this artificial cracking session we
|
||
|
||
found the protection scheme after a little snooping around. But,
|
||
|
||
as you will see in the hands on part, there are always MANY ways
|
||
|
||
to crack a single protection scheme. You could -for instance-
|
||
|
||
have found this protection the other way round: set a trace on
|
||
|
||
memory range for the program, restricting the trace to the first
|
||
|
||
part of it (say CS:0 to CS:1000, if you do not fetch anything you
|
||
|
||
can always try the other blocks). Breakpoint at the nag screen,
|
||
|
||
have a look at the last 300-400 backtraced instructions, if you
|
||
|
||
did not move anything, everything will follow a repetitive
|
||
|
||
pattern, until the protection snaps on:
|
||
|
||
...
|
||
|
||
JL 0A99
|
||
|
||
CMP BYTE PTR [A72A],01
|
||
|
||
...
|
||
|
||
JL 0A99
|
||
|
||
CMP BYTE PTR [A72A],01
|
||
|
||
...
|
||
|
||
for ages and ages and then...
|
||
|
||
...
|
||
|
||
JL 0A99
|
||
|
||
E834FD CALL 0759 <- BINGO! (CALL beggar_off_time_is_up)
|
||
|
||
... there it is, found the other way round. (But this apparently
|
||
|
||
better method is unfortunately very unstable: it depends on your
|
||
|
||
timing of the breaking in and on the distance between protection
|
||
|
||
and nag screen, therefore the somehow more complicated, but more
|
||
|
||
sure previous one should be favoured).
|
||
|
||
The reason why "minimal" approaches in cracking are often
|
||
|
||
more successful than heavy vector_cracking, is that the programs
|
||
|
||
are hardly ever "overprotected", and therefore the protections
|
||
|
||
are seldom difficult to find (and those that are really worth
|
||
|
||
cracking for study reasons).
|
||
|
||
Sometime you don't even need to crack anything at all! Some
|
||
|
||
applications are fully functional -per se-, but have been
|
||
|
||
crippled in a hurry in order to release them as demos. The
|
||
|
||
commercial programmers want only money, do not even try to
|
||
|
||
understand our zen ways, and do not care at all for a well done
|
||
|
||
job. That means, among other things, that the hard disk of the
|
||
|
||
user will be cluttered with files that the main program module
|
||
|
||
never calls. A typical example of this sloppy method is the demo
|
||
|
||
of [Panzer General] from SSI that appeared in the summer '95.
|
||
|
||
This was in reality no less than the complete beta version of the
|
||
|
||
game: you just had to substitute to one of the two "allowed"
|
||
|
||
scenarios one of the 20 or more scenarios of the beta version in
|
||
|
||
order to play them freely... you didn't ever need to crack!
|
||
|
||
The pooldemo crack example above should not discourage you
|
||
|
||
from cracking intuitively. Be careful! Perform a thoroughly
|
||
|
||
zen_analyze before attempting deeper methods: do remember that
|
||
|
||
you want to crack the protection scheme SOMEHOW, and not
|
||
|
||
necessarily following the same line of thought that the
|
||
|
||
programmer eventually WANTED YOU TO CRACK IT with.
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 2: tools and tricks of the trade
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[INDY.EXE]
|
||
|
||
--------------------------------------
|
||
|
||
LOST IN THE DARK CODEWOODS
|
||
|
||
When you break into a program you end up in portions of code
|
||
|
||
that are unfamiliar to you. It is also not uncommon for the
|
||
|
||
breakpoints to occur outside of the confines of the program you
|
||
|
||
want to crack. Getting your bearings is, in these cases, very
|
||
|
||
important.
|
||
|
||
One of the handiest utilities is the memory dump tool -it
|
||
|
||
tells you where all the device drivers and TSR are loaded, in
|
||
|
||
which memory locations the program you are cracking dwells, how
|
||
|
||
much memory is left and what the next program load point is. The
|
||
|
||
tools you use should report on the following:
|
||
|
||
- the contents of interrupt vectors
|
||
|
||
- the state of the BIOS data area, beginning at address 40:0
|
||
|
||
- internal structures within DOS, such as the MCB chain, the
|
||
|
||
SFT (System File Table) chain, the chain of installed
|
||
|
||
device drivers, the PSPs and memory allocations associated
|
||
|
||
with installed TSRs
|
||
|
||
- memory allocation statistic from XMS and EMS drivers
|
||
|
||
When seeking to understand a section of foreign code, you
|
||
|
||
must be especially careful to seek the real intent of the code.
|
||
|
||
Consider using a profiler prior to undertaking an analysis of an
|
||
|
||
unfamiliar program. This will help you by ensuring that you don't
|
||
|
||
waste time studying sections of the program that aren't even
|
||
|
||
involved in the protection scheme you are chasing down.
|
||
|
||
Using a utility that charts a program's calling hierarchy
|
||
|
||
can give you an important perspective on how your babe conducts
|
||
|
||
its internal operations.
|
||
|
||
YOUR DEBUGGER: YOUR FAVOURITE TOOL
|
||
|
||
First and foremost, your debugger must be designed for use
|
||
|
||
with resident modules (or must be itself a resident module).
|
||
|
||
Trying to crack with simplistic [debug.com] is a sure way to get
|
||
|
||
absolutely nowhere. We recommend Softice.exe from Nu-Mega
|
||
|
||
technologies (Version 2.6 [S-Ice.exe] has been cracked by MARQUIS
|
||
|
||
DE SOIREE and its vastly available on the Web). You could also
|
||
|
||
use [Periscope] or [Codeview] or Borland's Turbodebugger... all
|
||
|
||
these programs have been boldly cracked and/or distributed and
|
||
|
||
are now on the Web for free... learn how to use YAHOO and find
|
||
|
||
them. In emergency cases you could fix some quick crack using
|
||
|
||
[debug] or [symdeb], but, as said above, most of the time these
|
||
|
||
older debuggers won't do. I'll nevertheless ALWAYS give the final
|
||
|
||
crack procedure for [debug.com], in order to permit even lusers
|
||
|
||
to crack programs.
|
||
|
||
When you first smell a protection, it can be tempting to
|
||
|
||
immediately begin your crack using invasive types of techniques.
|
||
|
||
While there is certainly nothing wrong with this approach,
|
||
|
||
provided that you are fairly familiar with the protection scheme
|
||
|
||
used, going in too deep too soon can be a problem when you don't
|
||
|
||
have a strong hunch. Most of the time you'll end up missing
|
||
|
||
important details. So first of all sit down and ponder... that's
|
||
|
||
the zen-way, the only one that really works.
|
||
|
||
Single-stepping is expensive, not only because of the time
|
||
|
||
it requires but also because of the amount of detail with which
|
||
|
||
you must contend. Your immediate goal is to home in on the
|
||
|
||
protection scheme through a series of successively refined traps,
|
||
|
||
your broader aim is to get an overview idea of the program's
|
||
|
||
action... the wise use of breakpoints will condense these
|
||
|
||
minutiae into an understandable form.
|
||
|
||
The first step is to try to identify the section of the
|
||
|
||
program where the protection scheme is snapping.
|
||
|
||
Once you are able to isolate a certain section of a program,
|
||
|
||
breakpoints can be used to gather a trace history of the
|
||
|
||
program's execution. If your debugger sports a backtrace buffer,
|
||
|
||
logging window, or similar feature, by all means learn how to use
|
||
|
||
it. The debugger it's your best weapon, you must know all the
|
||
|
||
possibilities it offers and all the capabilities it possesses.
|
||
|
||
Having a debugger's display output echoed to a printer is another
|
||
|
||
possibility.
|
||
|
||
Using breakpoints is beneficial for two basic reasons: speed
|
||
|
||
and reduction of detail. Manual single-stepping is invaluable
|
||
|
||
when you are close to the protection scheme, but too much of it
|
||
|
||
will bore you to death.
|
||
|
||
When selecting breakpoint locations and the types of
|
||
|
||
breakpoint to use, it is important to step back once more, drink
|
||
|
||
a cool Martini-Wodka (use only Moskovskaja: non-russian Wodkas
|
||
|
||
are appalling) and ask yourself: "What is this going to tell me?"
|
||
|
||
and "What else will I need to know once the break occurs?". MOST
|
||
|
||
IMPORTANT OF ALL: "Is my current cracking approach the simplest
|
||
|
||
and most direct?", coz you do not want to waste precious cracking
|
||
|
||
time.
|
||
|
||
When devising a set of breakpoints it is wise to consider
|
||
|
||
how "a trail of bread crumbs" can be left. Not allowing for an
|
||
|
||
execution chronicle from the start can mean having to restart a
|
||
|
||
cracking session.
|
||
|
||
Setting breakpoints on certain software interrupt calls is
|
||
|
||
an excellent way to get an overview of a program's operations.
|
||
|
||
The INT_21 DOS services interrupt is probably the most universal
|
||
|
||
useful of these, with BIOS interrupts such as the INT_13 (BIOS
|
||
|
||
Disk services) and INT_16 (BIOS keyboard services) useful for
|
||
|
||
specific cracking.
|
||
|
||
When working with a debugger, evaluative breakpoints are
|
||
|
||
usually your best shot. To avoid having to deal with a plethora
|
||
|
||
of calls, you would want to have a debugger capable of being told
|
||
|
||
to "break on any INT_21 call except where AH == 2C or AH == 0B".
|
||
|
||
A real understanding of the working of a program is surely
|
||
|
||
important, but don't overdo it! To reverse-engineer even a small
|
||
|
||
program can involve many hours of analysis and documentation
|
||
|
||
work. If you'll not be able to use the zen-cracking techniques
|
||
|
||
described in this tutorial (sadly not everybody can) pace
|
||
|
||
yourself and make sure your chair is comfortable: you'll be
|
||
|
||
sitting for quite a spell.
|
||
|
||
Much of the work involved in reverse-engineering consist of
|
||
|
||
chasing down tentacles. In order to understand the operations of
|
||
|
||
one function, you must understand what happens within each of the
|
||
|
||
functions it calls- its child functions. To understand these
|
||
|
||
child functions you must study their children; and so on down the
|
||
|
||
calling hierarchy tree. Then there is the data. Tracing tentacles
|
||
|
||
based on a program's calling hierarchy is a directed process.
|
||
|
||
Each function you encounter is basically a list of other
|
||
|
||
functions you must reckon with. When it comes to analyzing a
|
||
|
||
function's interrelationship with the program's data structure,
|
||
|
||
no such list is provided. You must have instinct, feeling and
|
||
|
||
luck.
|
||
|
||
Data analysis requires more of a broad-based inquisition.
|
||
|
||
For each memory variable you are interested in, you must survey
|
||
|
||
all functions to determine which ones read and write that
|
||
|
||
variable. The use of memory conditional breakpoints and of a
|
||
|
||
disassembler that builds a cross-reference table can make this
|
||
|
||
task a lot easier. (Use Sourcer! It's a fairly good tool and
|
||
|
||
version 4.08 of [sr.exe] has been long ago cracked and
|
||
|
||
distributed on the Web).
|
||
|
||
ALL SYSTEM CALLS IN ONE LOCATION
|
||
|
||
Remember that if the program you are cracking was written
|
||
|
||
in assembler in the first place (very unlikely knowing the
|
||
|
||
laziness of to_days programmers), system calls are probably made
|
||
|
||
directly from the functions which need them. But when a program
|
||
|
||
is developed in a high-level language, it is more likely that
|
||
|
||
common library functions will be used for many operations
|
||
|
||
involving system calls. When a program makes all of its INT_21
|
||
|
||
calls from the same location, you know that this is certainly the
|
||
|
||
case.
|
||
|
||
Now, what happens sometimes is that the programmers write
|
||
|
||
the whole application in a overbloated language like C++, but are
|
||
|
||
afterwards compelled to "speed up" critical sections of the code
|
||
|
||
writing them in assembler. And loo! A section where you
|
||
|
||
repeatedly find assembler crafted patches is precisely the
|
||
|
||
protection scheme! So you could have a program with all INT_21
|
||
|
||
calls from the same location but for one or two calls which are
|
||
|
||
coming out of the section where the morons have "hidden" their
|
||
|
||
protection strategy. By just "looking" at the dead code of a
|
||
|
||
program, you should be capable to tell wich parts have been
|
||
|
||
"added on" in a later phase. They presents themselves as
|
||
|
||
unevenness and irregularities, especially if you use an utility
|
||
|
||
that represents graphicallly the code of a program. Protections
|
||
|
||
are often added on at the end of the development.
|
||
|
||
Should you determine that the system calls relevant to your
|
||
|
||
cracking are made from common library functions, all is not lost.
|
||
|
||
The specific function from which these library calls were made,
|
||
|
||
the function you are seeking to locate, is executing at some
|
||
|
||
point in between these calls. Break in with your debugger at the
|
||
|
||
end of the first system call, just where it is returning to the
|
||
|
||
point of call. From there, trace through the remainder of the
|
||
|
||
common library routine until it returns to its caller. In short
|
||
|
||
order, you should find yourself in the function you need to see.
|
||
|
||
The trick is to be able to identify it for what it is.
|
||
|
||
ASCIIZ IN CODE
|
||
|
||
In the interest of gaining an overall familiarity with the
|
||
|
||
program you want to crack, it can be enlightening to use a hex
|
||
|
||
dump utility to examine the message strings contained within the
|
||
|
||
program's binary modules. If the program happens to load its
|
||
|
||
message strings from separate files, your search has just been
|
||
|
||
simplified.
|
||
|
||
Your debugger's memory-dumping feature is one tool that can
|
||
|
||
be useful for this type of exploration. You could also construct
|
||
|
||
a filtering program, which would read a binary file and output
|
||
|
||
all sequences of bytes that are comprised of displayable
|
||
|
||
characters and are over a certain minimum length (the best
|
||
|
||
cracker tools are often the ones you write yourself).
|
||
|
||
When a protection scheme is marked by the issuance of a
|
||
|
||
specific message on the screen, you could go into the program and
|
||
|
||
locate the code that emits this message, and then determine what
|
||
|
||
triggers it. A good way to start the location process is to see
|
||
|
||
if a system call is used to display the string. Interrupt INT_21,
|
||
|
||
INT_10 or INT_29 are usually used to display text messages to the
|
||
|
||
console.
|
||
|
||
When the message's display is not a result of one of these
|
||
|
||
system calls, direct video writing is probably being used. If you
|
||
|
||
know the screen location used, and if that part of video memory
|
||
|
||
is not used for anything else at the time (a big if), a memory
|
||
|
||
write breakpoint could be set on the video buffer address
|
||
|
||
corresponding to the first character's position. If this won't
|
||
|
||
work, use the step-over/step-around tracing technique while
|
||
|
||
watching for the message to appear.
|
||
|
||
Now you found it: from a disassembled listing, you locate
|
||
|
||
the address of the message string and then survey the reminder
|
||
|
||
of the file for any instructions that reference this address.
|
||
|
||
[Sourcer] can generate labels for specific memory locations and
|
||
|
||
a cross-reference table showing where these labelled locations
|
||
|
||
are referenced. Otherwise, load the disassembled listing file
|
||
|
||
into your editor and use its search capabilities. Manually
|
||
|
||
searching for such things in a listing will make you old before
|
||
|
||
your time.
|
||
|
||
CODE AND DATA
|
||
|
||
When stepping through code at the assembler level, watch out
|
||
|
||
for interrupt calls that are followed by data. Sometimes you will
|
||
|
||
find an interrupt call, typically within the range INT_34 to
|
||
|
||
INT_3F, where several bytes immediately following the interrupt
|
||
|
||
instruction will be data rather than code.
|
||
|
||
Be especially suspicious of this type of code-and-data
|
||
|
||
mixture when your debugger's disassembly output of the
|
||
|
||
instructions immediately following an interrupt call doesn't make
|
||
|
||
sense. Sometimes you can determine the offset of the next true
|
||
|
||
instruction by inspecting the following code and data. In other
|
||
|
||
cases, you will have to trace through the interrupt call to see
|
||
|
||
how it accesses the data following the interrupt call instruction
|
||
|
||
and how it manipulates the return address on the stack.
|
||
|
||
HOOKED VECTORS
|
||
|
||
Seeing what interrupt intercepts already exist within a
|
||
|
||
system before running the program you want to crack, as well as
|
||
|
||
what interrupt handlers are established by the target program,
|
||
|
||
can provide useful clues. For example, if a protection
|
||
|
||
establishes an INT_09 intercept just before the snapping of a
|
||
|
||
keyboard verification routine, your range of suspects has just
|
||
|
||
been narrowed significantly.
|
||
|
||
To study the interrupt vector activities of an application,
|
||
|
||
a vector dump map utility is useless. It can't be run while
|
||
|
||
running the application you want to crack. One solution is to run
|
||
|
||
the program under a debugger and watch for system calls to INT_21
|
||
|
||
functions 25h (set interrupt vector) and 35h (get interrupt
|
||
|
||
vector), but in the event that the program reads and writes
|
||
|
||
interrupt vectors directly, this method will not give you a
|
||
|
||
complete picture. Normally you'll use a spy, trace or "step"
|
||
|
||
utility.
|
||
|
||
APPLYING A MEMORY WRITE BREAKPOINT TO A SPECIFIC VECTOR OR
|
||
|
||
TO THE ENTIRE TABLE is another way to deal with this.
|
||
|
||
Note that some sort of direct vector writing must be
|
||
|
||
occurring if a vector change is detected between system calls.
|
||
|
||
If a vector change is detected during a system call but it
|
||
|
||
isn't function 25h of INT_21, suspect that an IRQ handler may be
|
||
|
||
effecting the change.
|
||
|
||
LITTLE TRICKS OF THE TRADE:
|
||
|
||
* determining interrupt vector addresses ****************
|
||
|
||
How do you determine the interrupt vector addresses? As
|
||
|
||
example let's find the address of the INT_21 interrupt vector.
|
||
|
||
Since the interrupt vector table starts at address 0000:0000
|
||
|
||
(easy to remember, isn't it?) and there are four bytes per
|
||
|
||
vector, the basic process is to multiply the interrupt number
|
||
|
||
four times and use the result at the offset (on segment zero).
|
||
|
||
21h + 21h = 42h 42h + 42h = 84h
|
||
|
||
The int_21 vector is located at address 0000:0084
|
||
|
||
You could also use a calculator, for instance, the address of
|
||
|
||
INT_63 is 63h*4=18ch -> 0000:018C
|
||
|
||
|
||
|
||
* address conversion ***************************************
|
||
|
||
After a painstaking cracking session, you have finally
|
||
|
||
determined that a byte of memory at address 6049:891C is the
|
||
|
||
trigger. But when you isolate the offending instruction, you find
|
||
|
||
that the address it is generating when the protection occur is
|
||
|
||
different, being 6109:7D1C instead! How can this be?
|
||
|
||
An 80x86 type CPU, when running in real or VM86 mode, uses
|
||
|
||
what is known as segment:offset type addressing. One side effect
|
||
|
||
of this addressing method is that one physical address can be
|
||
|
||
equivalent to many different segment:offset addresses.
|
||
|
||
To find the PHYSICAL ADDRESS for a given segment:offset do
|
||
|
||
the following:
|
||
|
||
- convert the segment portion of the address to a 1-based number
|
||
|
||
by multiplying it by 16 (x10)... it's easy: add 0 at the right
|
||
|
||
end of the number!...
|
||
|
||
6049 -> 60490
|
||
|
||
6109 -> 61090
|
||
|
||
now all you have to do is to add this value to the offset value
|
||
|
||
60490+891C -> 68DAC
|
||
|
||
61090+7D1C -> 68DAC <- Got it?
|
||
|
||
And the other way round? If you have a physical address, say
|
||
|
||
19AC3, and you want to obtain a segment:offset address you must
|
||
|
||
first of all decide in which segment you want the address... if,
|
||
|
||
say, you choose segment 16CC, you proceed as follows:
|
||
|
||
16CC -> 16CC0
|
||
|
||
19AC3-16CC0 = 2E03 (offset)
|
||
|
||
address for 19AC3 in segment 16CC = 16CC:2E03
|
||
|
||
TOOLS OF THE TRADE
|
||
|
||
Before starting this section, for those of you that do not know
|
||
|
||
anything, here is the ARCHIE way you get all the program that do
|
||
|
||
EXIST on the planet: e-mail following
|
||
|
||
1) (address) archie@archie.univ-rennes1.fr
|
||
|
||
I use this french archie, but you can get a worldwide list using
|
||
|
||
the metacommand "servers"
|
||
|
||
2) (text) set search sub <- anywhere in string
|
||
|
||
set maxhits 140 <- (100-1000)
|
||
|
||
set maxhitspm 15 <- not just 1 file all over
|
||
|
||
find stepdos <- search e.g. this file
|
||
|
||
Wait two hours, get your post and ftp the file you wanted (and
|
||
|
||
YES!, you 'll find also EVERYTHING else for free on the Web).
|
||
|
||
You could, instead of using archie, also learn how to use YAHOO.
|
||
|
||
[MEMSCAN.EXE]
|
||
|
||
One of the most fascinating tools that I have ever seen is
|
||
|
||
a (very old) program: MEMSCAN.EXE.
|
||
|
||
This program was originally written in 1988 by Scott A. Mebust,
|
||
|
||
running in CGA. It's a "visual" utility: it enables you to see
|
||
|
||
graphically the 1-meg of PC memory in 8 kbyte chunks. It's a
|
||
|
||
powerful tool in order to locate quickly bit mapped graphics and
|
||
|
||
other 'objects' in memory, like program data tables, stack areas,
|
||
|
||
code areas, available RAM, etc. I used this great idea to create
|
||
|
||
(in C) my own tools: a "dead_programs scanner" and an ameliorate
|
||
|
||
version of Memscan itself. Looking at the VISUAL STRUCTURE of a
|
||
|
||
program it's a great help when you'll crack higher levels.
|
||
|
||
[TRACKMEM.COM]
|
||
|
||
A very good tool by James W.Birdsall, tracks memory usage
|
||
|
||
of programs (EMS, XMS, conventional).
|
||
|
||
[SCANCODE.COM]
|
||
|
||
"THE" scancode lister, by the code_masters from clockwork
|
||
|
||
software. The must utility for crackers that do not learn all
|
||
|
||
scancodes by heart.
|
||
|
||
[MAP.EXE]
|
||
|
||
Actually "MAP2", THE memory mapper from the code_masters at
|
||
|
||
clockwork software. It's a very good tool and an interesting one
|
||
|
||
too, coz you get it with the "Nigel" nag screens. They are not
|
||
|
||
difficult to remove (a "passletter" protection scheme, you'll
|
||
|
||
learn how to find and remove it from [Map.exe] in LESSON 3.2).
|
||
|
||
[FILEDUMP.COM] [HEXDUMP.COM] [TDUMP.EXE] [DUMP.EXE]
|
||
|
||
There are hundred of file dump utilities, coz file dumping
|
||
|
||
is one of the first exercise they learn you at C-school.
|
||
|
||
Hexdump.com is 558 bytes long, Tdump.exe 120.704, pick the one
|
||
|
||
you like better or write your own (even better). Filedump.com,
|
||
|
||
by Daniel M.O'Brien, 1046 bytes long, it's nice.
|
||
|
||
[SPRAY.COM]
|
||
|
||
That's a good crack utility indeed! This 1989 program by
|
||
|
||
Daniel M.O'Brien gives you a "post-mortem" picture of your
|
||
|
||
memory. You redirect it to <myfile> and study it at ease. It's
|
||
|
||
difficult to say how many hours of cracking it did spare me (you
|
||
|
||
should study the program, only 252 bytes long, and will have to
|
||
|
||
modify it a bit, coz it's pretty primitive, in the original
|
||
|
||
version, for instance, the redirection to the printer works only
|
||
|
||
if there is NO SPACE between "spray" and ">").
|
||
|
||
[VEXE.EXE]
|
||
|
||
A good EXE files analyzer, useful for windows programs too
|
||
|
||
(see --> LESSON 7). Some of its functions are present in
|
||
|
||
TDUMP.EXE too. This 1991 program by S.Krupa it's sometimes very
|
||
|
||
useful.
|
||
|
||
[SNOOP UTILITIES --> KGB.EXE INTMON.EXE INTRSPY.EXE etc...]
|
||
|
||
[TRACE UTILITIES --> TRACE.EXE STEPDOS.EXE etc...]
|
||
|
||
A must to study the "calling hierarchy" of an unknown
|
||
|
||
program. KGB.EXE, a 1992 program by Petr Hor<6F>k could easily be
|
||
|
||
the best one, and comes with source code(!). I'll teach you how
|
||
|
||
to crack without any of them (you do not need them if you zen-
|
||
|
||
crack), but they can nevertheless be very useful in some
|
||
|
||
situations. Stepdos.exe, by Mike Parker, is a excellent program:
|
||
|
||
a pleasure to crack in order to use it for slightly different
|
||
|
||
purposes :=)
|
||
|
||
|
||
|
||
[SOURCERING UTILITIES]
|
||
|
||
SR.EXE can be used for sourcering unknown programs. It's a
|
||
|
||
fairly good sourcering tool. Version 4.08 has been cracked (it's
|
||
|
||
a "ORIGINAL NUMBERCODE" protected program) and distributed on the
|
||
|
||
Web, so you should easily find it. This said, you should NEVER
|
||
|
||
use such a brute force approach, unless you are really desperate:
|
||
|
||
I'll teach you how to crack without sourcering (you don't need
|
||
|
||
to sourcer if you zen-crack).
|
||
|
||
|
||
|
||
[HEXEDITORS]
|
||
|
||
Every idiot has written at least one hexeditor, and you can find
|
||
|
||
very bad tools everywhere (the SIMTEL collection, on the Web,
|
||
|
||
lists at least 35 hexeditors). I suggest you write your own and
|
||
|
||
contribute to the flood, or (better) get PSEDIT.EXE, a good 1990
|
||
|
||
program by Gary C. Crider (Parity Solutions, 1903 Pavia Ct.
|
||
|
||
Arlington, TX 76006... sometimes even americans can write good
|
||
|
||
programs). If you do use it (as you should) disapt the nag screen
|
||
|
||
as small exercise in cracking.
|
||
|
||
[DEBUGGER]
|
||
|
||
Your best friend in cracking, your weapon, your hidecloak...
|
||
|
||
I suggest [Softice.exe] from Nu-Mega technologies (Version 2.6
|
||
|
||
has been cracked by MARQUIS DE SOIREE and its vastly available
|
||
|
||
on the Web). You could also use [Periscope] or [Codeview] or
|
||
|
||
Borland's Turbodebugger... all these programs have been boldly
|
||
|
||
cracked and/or distributed and are now on the Web for free...
|
||
|
||
learn how to use ARCHIE and YAHOO in order to find them. Your
|
||
|
||
debugger is the only tool you 'll REALLY need, believe me. So
|
||
|
||
choose your weapon wisely and learn how to use backtrace ranges
|
||
|
||
and (FOREMOST!) breakpoint on user written qualifications
|
||
|
||
routines. You 'll be able to crack almost EVERYTHING using these
|
||
|
||
features in the right way.
|
||
|
||
You should get all the programs mentioned above (all the
|
||
|
||
programs that EXIST for that matter) for free on the Web. Use
|
||
|
||
them, but also modify them recklessly! REMEMBER THAT YOU ARE
|
||
|
||
(GOING TO BE) A CRACKER! The first programs you should crack and
|
||
|
||
modify are therefore your very tools! So steal the code of the
|
||
|
||
best tools you find! Snatch the best routines and change them for
|
||
|
||
the better! That's the whole point in cracking: a mission to
|
||
|
||
IMPROVE the best accomplishments of humanity's genius :=)
|
||
|
||
HOW TO CRACK, ZEN-CRACKING
|
||
|
||
You 'll learn, beginning with next lesson, how to crack
|
||
|
||
systematically the different protection schemes: paper & password
|
||
|
||
protections, time protections, access protections. At the end of
|
||
|
||
the "methodolocical" part, you'll be able to deprotect programs,
|
||
|
||
but you still wont be a cracker. In order to crack higher you
|
||
|
||
must use what I call (lacking a better definition) "zen-
|
||
|
||
cracking". I 'll give you right now an example of this, so that
|
||
|
||
you know what I'm talking about, but -unless you are already
|
||
|
||
capable- you'll have to finish this tutorial part for "normal"
|
||
|
||
cracking before attempting this techniques. Let's zen-crack
|
||
|
||
together a password protection scheme (aka "paper protection",
|
||
|
||
coz you need the original manual of the program in order to
|
||
|
||
answer). This protection is based on the typing, at the nag
|
||
|
||
screen, of the correct sequence of numbers. Our example is a game
|
||
|
||
for the reasons explained in lesson 1, but you 'll find the SAME
|
||
|
||
protection scheme in the access protection procedure of some old
|
||
|
||
Tapestry networks... so do not frown upon games protections.
|
||
|
||
INDIANAPOLIS 500, Papyrus software & Electronic Arts, 1989
|
||
|
||
It's a rather widespread program, you should therefore find it
|
||
|
||
pretty easily. The nag screen asks for data based on the
|
||
|
||
historical performances of race cars... that means that the
|
||
|
||
answers will consist in two to three digits.
|
||
|
||
Now, the normal way to crack such a program (described in
|
||
|
||
-> lesson 3.1) embodyes following steps:
|
||
|
||
- snap save program memory areas before typing your answer
|
||
|
||
- snap compare after typing, say, "666"
|
||
|
||
- search for the sequence 36,36,36 (i.e. 666)
|
||
|
||
- breakpoint on memory range for reading
|
||
|
||
- look at the program part fetching your data
|
||
|
||
- find the snap procedure
|
||
|
||
- disable it.
|
||
|
||
The above crack it's relatively quick and should be most of
|
||
|
||
the time fairly effective, but there is a better way: the "zen
|
||
|
||
way", the only one that can really enable you to crack high
|
||
|
||
protection schemes.
|
||
|
||
- Run the program and break in at the nag screen
|
||
|
||
- Answer consist of 2-3 digits? Search for "AC" (i.e. the
|
||
|
||
instruction LODSB, load digit of answer in AL) in the area 500
|
||
|
||
bytes BEFORE and 500 bytes AFTER your position. You'll get some
|
||
|
||
locations. (In the case of INDY 500 you get 6 such locations).
|
||
|
||
- "feel" the locations (that's the tricky part).
|
||
|
||
- OK, you already made it! Here is the protection strategy:
|
||
|
||
8BBF28A5 MOV DI,[BX+A528]<-- DI points to coded data area
|
||
|
||
:compare_loop
|
||
|
||
AC LODSB <-- load first digit of answer in AL
|
||
|
||
B4FF MOV AH,FF <-- load mask in AH
|
||
|
||
2A25 SUB AH,[DI] <-- sub coded data from mask and get
|
||
|
||
real answer
|
||
|
||
47 INC DI <-- ready to get next coded data
|
||
|
||
3AC4 CMP AL,AH <-- user answer = real answer ?
|
||
|
||
751A JNZ beggar_off_coz_false_answer
|
||
|
||
0AC0 OR AL,AL <-- more numbers?
|
||
|
||
75F2 JNZ compare_loop
|
||
|
||
59 POP CX <-- all OK, go on, nice guy
|
||
|
||
...
|
||
|
||
And if the protection scheme had been more far away? And if you
|
||
|
||
cannot "feel" the right one? And if my grandma had wheels? You'll
|
||
|
||
learn it, believe me.
|
||
|
||
Now let's quickly crack this crap.
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING INDY.EXE (by +ORC, January 1996)
|
||
|
||
ren indy.exe indy.ded
|
||
|
||
symdeb indy.ded
|
||
|
||
- s (cs+0000):0 Lffff B4 FF 2A 25 47 3A C4 75 1A
|
||
|
||
xxxx:yyyy <-- this is the answer of the debugger
|
||
|
||
- s (cs+1000):0 Lffff B4 FF 2A 25 47 3A C4 75 1A
|
||
|
||
(nothing, but you must be sure there isn't a mirror)
|
||
|
||
- e xxxx:yyyy+8 00 <-- "JNZ 1A ahead" changes to "JNZ 0"
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren indy.ded indy.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
Cracked: you just changed the JNZ beggar_off instruction in a JNZ
|
||
|
||
go_ahead_anyway. Nice, isnt'it?
|
||
|
||
WHY WE CRACK
|
||
|
||
Strange as it may seem, the reasons for cracking are very
|
||
|
||
important for the success of our task. We (at least we old
|
||
|
||
crackers) crack AGAINST society, and OPPOSING laws and
|
||
|
||
conventions. We usually DO NOT crack for money or for other
|
||
|
||
"commercial" reasons (just sometimes, and we are expensive: I
|
||
|
||
have plenty of money already and my services are VERY expensive
|
||
|
||
if you need an aimed deprotection). But in general we don't care
|
||
|
||
much for money and -as you can see- I am giving away the basis
|
||
|
||
of what I know for free with this tutorial. The programs we crack
|
||
|
||
should be made free for everybody, even if we spent some of our
|
||
|
||
time deprotecting them. We could not care less of the commercial
|
||
|
||
value of a given program, not to mention the holy work of the
|
||
|
||
ethical programmers... we program ourselves, but only because we
|
||
|
||
LIKE it... if somebody does something only in order to gain
|
||
|
||
money, he does not deserve anything. It's the mind challenge that
|
||
|
||
counts, NEVER the profit! (Even if you can make good use of the
|
||
|
||
cracked programs and even if -as I said- there is at times a
|
||
|
||
personal profit).
|
||
|
||
This is an indispensable attitude! Only a non-mercantile
|
||
|
||
mind can leap forward to the "satori" knowledge that you
|
||
|
||
desperately need if you want to crack quickly and elegantly huge
|
||
|
||
iperbloated monstruosities that somebody else wrote and
|
||
|
||
protected, or if you want to gain access to some hidden
|
||
|
||
information, data that you would like to snoop but that somebody
|
||
|
||
declared "off limits", coz a stupid government, or useless
|
||
|
||
industry sector, or money oriented programmer or dirty lobby of
|
||
|
||
interest decided it.
|
||
|
||
If you do accept the society where we are compelled to live,
|
||
|
||
its awfully egoistic way of life and its dirty "profit" values,
|
||
|
||
you may eventually learn how to disable some simple protections,
|
||
|
||
but you'll never be able to crack in the "right" way. You must
|
||
|
||
learn to despise money, governments, televisions, trends,
|
||
|
||
opinion-makers, public opinion, newspapers and all this
|
||
|
||
preposterous, asinine shit if you want to grasp the noble art,
|
||
|
||
coz in order to be emphatic with the code you must be free from
|
||
|
||
all trivial and petty conventions, strange as it may sound. So
|
||
|
||
you better take a good look around you... you'll find plenty of
|
||
|
||
reasons to hate society and act against it, plenty of sparks to
|
||
|
||
crackle programs in the right way... Hope all this did not sound
|
||
|
||
too cretin.
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 3.1: hands on, paper protections (1)
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[UMS.EXE] [LIGHTSPD.EXE] [GENERAL.EXE]
|
||
|
||
--------------------------------------
|
||
|
||
SOME PROBLEMS WITH INTEL's INT
|
||
|
||
The INT instruction is the source of a great deal of the
|
||
|
||
flexibility in the PC architecture, because the ability to get
|
||
|
||
and set interrupt vectors means that system services (included
|
||
|
||
DOS itself) are infinitely extensible, replaceable and
|
||
|
||
MONITORABLE. Yet the Int instruction is also remarkably
|
||
|
||
inflexible in two key ways:
|
||
|
||
- an interrupt handler DOES NOT KNOW which interrupt number
|
||
|
||
invoked it.
|
||
|
||
- the int instruction itself expects an IMMEDIATE operand:
|
||
|
||
you cannot write MOV AX,x21, and then INT AX; you must
|
||
|
||
write INT x21.
|
||
|
||
That would be very good indeed for us cracker... unfortunately
|
||
|
||
many high level language compilers compile interrupts into PUSHF
|
||
|
||
and FAR CALL instruction sequences, rather than do an actual INT.
|
||
|
||
Another method is to PUSH the address of the handler on the stack
|
||
|
||
and do RETF to it.
|
||
|
||
Some protection schemes attempt to disguise interrupt calls,
|
||
|
||
1) camouflaging the code, 2) putting in substitute interrupt
|
||
|
||
instructions which look harmless and modifying them "on the fly"
|
||
|
||
or 3) replicating whole interrupt routines inside the code. This
|
||
|
||
is particularly frequent in the various "disk access" protection
|
||
|
||
schemes that utilize INT_13 (the "disk" interrupt) and will
|
||
|
||
therefore be thoroughly explained in -> lesson 5.
|
||
|
||
A LITTLE BASIC ASSEMBLER
|
||
|
||
In order to understand the protection schemes and to defeat them,
|
||
|
||
you must acquire a passing knowledge of assembler, the "machine
|
||
|
||
language" code. You can find a lot of good, well explained code
|
||
|
||
for free: viruses are one of the best sources for good "tight and
|
||
|
||
tricky" assembler code. You can find the source code of almost
|
||
|
||
all viruses on the web: oddly all the would be hackers seem to
|
||
|
||
have an aberrant passion for this kind of stuff instead of
|
||
|
||
studying cracking techniques. But there are millions of lines of
|
||
|
||
good explained "commercial" assembler code on the net, just fish
|
||
|
||
it out and study it: the more you know, the better you crack.
|
||
|
||
I'll restrict myself to some observations, sprinkled throughout
|
||
|
||
this tutorial. Let's start with some must_know:
|
||
|
||
------------------------ STRINGS ----------------------------
|
||
|
||
The string instructions are quite powerful (and play a great role
|
||
|
||
in password protection scheme). ALL of them have the property
|
||
|
||
that:
|
||
|
||
1) The source of data is described by the combination DS:SI
|
||
|
||
2) The destination of data is described by the combination
|
||
|
||
ES:DI
|
||
|
||
3) As part of the operation, the SI and/or DI register(s)
|
||
|
||
is(are) incremented or decremented so the operation can be
|
||
|
||
repeated.
|
||
|
||
------------------------- JUMPS -----------------------------
|
||
|
||
JZ ero means what it says
|
||
|
||
JNZ ero means what it says
|
||
|
||
JG reater means "if the SIGNED difference is positive"
|
||
|
||
JA bove means "if the UNSIGNED difference is positive"
|
||
|
||
JL ess means "if the SIGNED difference is negative"
|
||
|
||
JB elow means "if the UNSIGNED difference is negative"
|
||
|
||
JC arry assembles the same as JB, it's a matter of
|
||
|
||
aesthetic choice
|
||
|
||
CRACKING PASSWORD PROTECTED PROGRAMS
|
||
|
||
Refer to lesson one in order to understand why we are using
|
||
|
||
games instead of commercial applications as learn material: they
|
||
|
||
offer the same protection used by the more "serious" applications
|
||
|
||
(or BBS & servers) although inside files that are small enough
|
||
|
||
to be cracked without loosing too much time.
|
||
|
||
A whole series of programs employ copy protection schemes
|
||
|
||
based upon the possess of the original manual or instructions.
|
||
|
||
That's obviously not a very big protection -per se- coz everybody
|
||
|
||
nowadays has access to a photocopier, but it's bothering enough
|
||
|
||
to motivate our cracks and -besides- you'll find the same schemes
|
||
|
||
lurking in many other password protected programs.
|
||
|
||
Usually, at the beginning of the program, a "nag screen"
|
||
|
||
requires a word that the user can find somewhere inside the
|
||
|
||
original manual, something like: "please type in the first word
|
||
|
||
of line 3 of point 3.3.2". Often, in order to avoid mistakes, the
|
||
|
||
program indicates the first letter of the password... the user
|
||
|
||
must therefore only fill the remaining letters.
|
||
|
||
Some examples, some cracks:
|
||
|
||
---------------------------------------------------
|
||
|
||
UMS (Universal Military Simulator) version 1
|
||
|
||
by Dr Ezra SIDRAN
|
||
|
||
(c) 1987 Intergalactic Development
|
||
|
||
European Union: Rainbird Software
|
||
|
||
United States: Firebird Software
|
||
|
||
---------------------------------------------------
|
||
|
||
This very old EGA program is one of the first I cracked in
|
||
|
||
my youth, and it's very interesting coz it employs a very basilar
|
||
|
||
protection scheme (a "PRIMITIVE"! More than 80% of the protection
|
||
|
||
schemes used to day (January 1996) are directly derived from one
|
||
|
||
of the 12 primitives.
|
||
|
||
The nag screen snaps at the beginning and keeps indefinitely
|
||
|
||
asking your answer, only the use of CTRL+C will bring you out of
|
||
|
||
it, back to DOS. That's a clear sign of older protection schemes:
|
||
|
||
newer schemes let you in for only 3 attempts or even only one,
|
||
|
||
and pop out to the OS if you fail. In UMS, besides, there is no
|
||
|
||
"first letter" aid, a later improvement.
|
||
|
||
The cracking procedure for password protected programs is,
|
||
|
||
first of all, to find out where are stored the letters that you
|
||
|
||
type in. So examine your memory map, find out where the program
|
||
|
||
dwells in memory, do a snap save of these memory areas and a
|
||
|
||
series of snap compares as you type your password in.
|
||
|
||
Strangely enough, in the case of UMS, as you type your
|
||
|
||
password there seems to be no difference at all in the memory
|
||
|
||
locations where this program dwells... yet the data must be
|
||
|
||
somewhere... Usually such a situation is a clear sign that an
|
||
|
||
hooked interrupt is used to hide the data.
|
||
|
||
Checking the hooked vectors you find out the following:
|
||
|
||
vecs 00, 02, 22 are hooked where needs be
|
||
|
||
vecs 34-3D are hooked at xxxx:0
|
||
|
||
vec 3E is hooked at xxxx:00CA
|
||
|
||
Ha! Let's have a closer look at this bizarre 3E hook. Let's
|
||
|
||
search for some words used in the nag_screen and then let's dump
|
||
|
||
the area where we find them (in UMS that will be at 3E_hook
|
||
|
||
address + 7656) and loo! You'll see the content of the nag screen
|
||
|
||
and, immediately afterwards, ALL the passwords "in extenso", i.e.
|
||
|
||
not encoded, not scrambled, nothing at all... THERE THEY ARE
|
||
|
||
(that's a very old protection scheme indeed). You could now, for
|
||
|
||
instance, easily patch all the different passwords to (for
|
||
|
||
instance) "PASS", and this would work... it's a very primitive
|
||
|
||
protection, as we said, nevertheless the use of a hooked vector
|
||
|
||
as hiding place for the protection code is not yet obsolete...
|
||
|
||
we'll find it elsewhere, in many "more modern" programs.
|
||
|
||
Now let's go deeper and examine the "compare" mechanism, we
|
||
|
||
want to crack, here, not just to patch.
|
||
|
||
Password protected programs (and access protection routines
|
||
|
||
for server and BBS, for that matter) have quite a lot of weak
|
||
|
||
points. The most obvious one (you 'll find out the other when
|
||
|
||
you'll high crack) is that they MUST compare the password of the
|
||
|
||
user with the original one(s). So you do not need to steal a
|
||
|
||
password, you just need to "ear" the echo of the original one in
|
||
|
||
the memory locations used for the compare, or, and that's more
|
||
|
||
correct, to crack the compare mechanism itself so as to make it
|
||
|
||
let you in even with a totally false password.
|
||
|
||
The compare mechanism of UMS can be found setting a
|
||
|
||
breakpoint on the memory range that covers the three locations
|
||
|
||
where the password is stored (and you 'll find these with your
|
||
|
||
search capabilities and with a pair of snap compares):
|
||
|
||
ES:0F8E (here you 'll see a copy of the password that the
|
||
|
||
program is asking)
|
||
|
||
ES:0F5C (here you 'll see a copy of the password that the user
|
||
|
||
types in)
|
||
|
||
INT_3E hook_address + 7656 (here are all the possible passwords
|
||
|
||
in extenso).
|
||
|
||
Here is how the protection scheme looks out:
|
||
|
||
MOV CX,FFFF Charge MAX in CX
|
||
|
||
REPNZ SCASB Scan ES:DI (the user password)
|
||
|
||
NOT CX Now CX holds the number of the
|
||
|
||
character that the user typed in
|
||
|
||
MOV DI,SI Real password offset to DI
|
||
|
||
LDS SI,[BP+0A] User password offset in SI
|
||
|
||
REPZ CMPSB Compares DS:SI with ES:DI (user
|
||
|
||
password and real password) then snap
|
||
|
||
out at CX=0 or at char_different,
|
||
|
||
whichever comes first.
|
||
|
||
Nice, we found the compare schema... how do we crack it now?
|
||
|
||
There are many elegant solutions, but let's remain on a basic
|
||
|
||
level... you look at the code that follows the CMPSB searching
|
||
|
||
the "snapping schema"... here it is immediately afterwards
|
||
|
||
(that's the case in most of the primitives). Remember: we sprung
|
||
|
||
out of the CMPSB check at the first different char, OR at the end
|
||
|
||
of the count of the user chars. Here it is what follows:
|
||
|
||
MOV AL,[SI-01] loads in AL the before_different char
|
||
|
||
of the user password (should be zero)
|
||
|
||
SUB AL,ES:[DI-01] subs with the before_different char of
|
||
|
||
the real password (should be zero)
|
||
|
||
CBW zero flag set, "TRUE", if OK_match
|
||
|
||
Well let's now look for the next JZ near (it's a "74" code)
|
||
|
||
CS:IP 740D JZ location no_good
|
||
|
||
Wait, let's continue a little... is there another check (often
|
||
|
||
you have a double check on DI)... yes there is!
|
||
|
||
CS:IP 7590 JNZ location no_good
|
||
|
||
Cracking such a schema is very easy: you just need to substitute
|
||
|
||
75 to 74 and 74 to 75: transform your JZ in a JNZ and the JNZ in
|
||
|
||
a JZ... now you will always pass, no matter what you write,
|
||
|
||
unless you exactly guess the password!
|
||
|
||
Now let's quickly crack it:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING UMS.EXE (by +ORC, January 1996)
|
||
|
||
ren ums.exe ums.ded
|
||
|
||
symdeb ums.ded
|
||
|
||
- s (cs+0000):0 Lffff 74 0D 1E B8 C2 3F
|
||
|
||
(nothing)
|
||
|
||
- s (cs+1000):0 Lffff 74 0D 1E B8 C2 3F
|
||
|
||
(nothing)
|
||
|
||
- s (cs+2000):0 lffff 74 0D 1E B8 C2 3F
|
||
|
||
xxxx:yyyy (this is the answer of the debugger)
|
||
|
||
- e xxxx:yyyy 75
|
||
|
||
- e xxxx:yyyy+17 74
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren ums.ded ums.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
In the debug/symdeb crack above we use as search string the
|
||
|
||
bytes comprising and following immediately the first JZ.
|
||
|
||
I know, I know... we saw them in [Soft-ice] and we could have
|
||
|
||
modified them there, but I'm teaching also pupils who may not
|
||
|
||
have [Soft-ice].
|
||
|
||
Note that the program is x431A0 bytes long, and therefore
|
||
|
||
has a BX=4 sectors adding to the CX=31A0 in the initial
|
||
|
||
registers... that's the reason I wanted to examine all the
|
||
|
||
sectors (even if I knew that the snap was in sector (cs+2000):
|
||
|
||
that's good practice! If you do not find your string in the first
|
||
|
||
sector you must search for it in the next sectors, till you find
|
||
|
||
it, coz in many programs there may be MORE THAN ONE repetitions
|
||
|
||
of the same schema (more about this double check later).
|
||
|
||
That's it, pupils, that's the way to crack old [UMS.EXE].
|
||
|
||
Let's go over, now, to more elaborate and more modern password
|
||
|
||
protection schemes.
|
||
|
||
--------------------------------------------------------
|
||
|
||
LIGHTSPEED, from Microprose (we crack here version 461.01)
|
||
|
||
--------------------------------------------------------
|
||
|
||
This program, released in 1990, operates a more "modern"
|
||
|
||
variation of the previous scheme. You 'll find this variation in
|
||
|
||
many access routines of remote servers (and this makes it very
|
||
|
||
interesting indeed).
|
||
|
||
Let's begin as usual, with our hooked vectors examination
|
||
|
||
and our snap compares.
|
||
|
||
Hooked vectors: 00, 08, 1B, 22, 23: nothing particular.
|
||
|
||
The snap_comparisons of the main memory area -as you type the
|
||
|
||
password in- gives more than six pages of changing locations...
|
||
|
||
that's clearly much too much to examine.
|
||
|
||
What now?
|
||
|
||
Sit down, have a Martini Wodka (I'm afraid that only
|
||
|
||
Moskovskaja 'll do) and meditate. Get the memory map of the
|
||
|
||
program's layout. Start anew: snap_save (before typing anything
|
||
|
||
in). Type as password "ABCDE". Get the print of the snap
|
||
|
||
compares. Sit down, sip Martini Wodka, relax. You know that the
|
||
|
||
code for A is x41, for B x42, for C x43 and so on... and in the
|
||
|
||
snap_compares, that you made between letters, you 'll have only
|
||
|
||
some locations with these values changing. Focus on these.
|
||
|
||
You 'll soon enough find out that for LIGHTSPEED absolute
|
||
|
||
location (in my computer) 404307, i.e.: relative locations (in
|
||
|
||
my computer) 30BE:F857 or 4043:0007 evoke the characters you
|
||
|
||
type, i.e. something like
|
||
|
||
-----------------------------------------------------
|
||
|
||
F855 F856 F857 F858 F859...
|
||
|
||
41 3E first_ready_letter your_1st_letter your_2nd_one...
|
||
|
||
-----------------------------------------------------
|
||
|
||
Inspecting the same prints, you 'll find out that absolute
|
||
|
||
location 30C64 (imc) or relative location 30BE:F83E evokes the
|
||
|
||
LAST character you typed in. The relative code line is:
|
||
|
||
CS:0097 MOV AX,[BP-08] where SS:F83E = 00+letter_code
|
||
|
||
Now breakpoint at these locations and investigate what's
|
||
|
||
going on (for instance, the instruction that follows is
|
||
|
||
CS:009A MOV [BX], AX
|
||
|
||
and this means that the code of the letter you just typed in will
|
||
|
||
be now copied in BX=F85A. What else can you do? Time to use a
|
||
|
||
little intuition: look for an instruction "CMP AX,000D", which
|
||
|
||
is the typical "IF the user hits ENTER then" instruction, coz
|
||
|
||
"x1D" its the ENTER keystroke. This must be somewhere around
|
||
|
||
here. Ha! You 'll soon enough find the line
|
||
|
||
CS:0073 3D0D00 CMP AX,000D
|
||
|
||
And now the way is open to the crack. But YOU DO NOT NEED ALL
|
||
|
||
THIS! Since the password protection schemes are -as I told you-
|
||
|
||
all more or less the same, I would suggest that you use first of
|
||
|
||
all following trick: in the largest part of the program (use
|
||
|
||
memory map to see where the program dwells) search the "F3A6"
|
||
|
||
sequence, that's instruction REPZ CMPSB.
|
||
|
||
In the case of Lightspd you 'll get as answer FOUR addresses
|
||
|
||
with this instruction: (pgsg=program main segment)
|
||
|
||
pgsg:C6F9
|
||
|
||
pgsg:E5CA
|
||
|
||
pgsg:E63E
|
||
|
||
pgsg:EAB0
|
||
|
||
There you are! Only four... have a short look at each of them:
|
||
|
||
you 'll see that the second one (pgsg:E5CA) is the "good" one.
|
||
|
||
The compare mechanism in this program of 1990 it's more or less
|
||
|
||
the same as in 1987'UMS (and do believe me: the same mechanism
|
||
|
||
is still in use to day (1996)!
|
||
|
||
B9FFFF MOV CX,FFFF charge Max in CX
|
||
|
||
F2AE REPNZ SCASB this scans ES:DI (the original
|
||
|
||
password)
|
||
|
||
F7D1 NOT CX so many chars in the original pw
|
||
|
||
2BF9 SUB DI,CX change DI for compare
|
||
|
||
F3A6 REPZ CMPSB compares DS:SI with ES:DI (real
|
||
|
||
pw with user pw) then snaps out
|
||
|
||
at CX=0 or at char_differs
|
||
|
||
See how easy? They all use the same old tricks the lazy
|
||
|
||
bastards! Here the section is preceded by a small routine to
|
||
|
||
lowercase the user password, coz the original muster is always
|
||
|
||
lowercased.
|
||
|
||
Now you would like, may be, to breakpoint at one of these
|
||
|
||
locations, in order to stop the program "in the snap area" and
|
||
|
||
inspect the snap mechanism... that WILL NOT DO with a "fixed"
|
||
|
||
breakpoint, coz these locations are called by the snap with a
|
||
|
||
different segment:offset numeration as the one you found (that's
|
||
|
||
old dos magic). So you MUST first set a memory_read/write
|
||
|
||
breakpoint on these locations, and then get at them at the snap.
|
||
|
||
Now you can find out the segment:offset used by the snap and only
|
||
|
||
now you'll be able to set a fixed breakpoint (for instance on the
|
||
|
||
NOT CX instruction).
|
||
|
||
Now run the program and breakpoint in: have a dump of the
|
||
|
||
ES:DI and see the original password. How nice! We have now the
|
||
|
||
original password in extenso in our memory dump window. That's
|
||
|
||
the "echo". By the way, there is a whole school of cracking
|
||
|
||
devoted to find and use these echoes... we work on different
|
||
|
||
paths, nevertheless password fishing can be interesting: where
|
||
|
||
are the password stored? From which locations do they come from?
|
||
|
||
A common practice of the protectionists is to hide them in
|
||
|
||
different files, far away, or in hooked vectors, or in SMC parts.
|
||
|
||
This is a program of 1990, that differs in respect to UMS: the
|
||
|
||
passwords are not "hidden" inside a hooked vector, coz that's a
|
||
|
||
pretty stupid protection: any hexdump utility would still permit
|
||
|
||
you to see them. Here the passwords are encoded (albeit in a very
|
||
|
||
primitive manner): looking for them (with memory range
|
||
|
||
breakpoints) you'll quickly find a section of the program code
|
||
|
||
that looks like this:
|
||
|
||
sg:0118 8C 91 9D 95 9B 8D 00 B8 EC 94 9B 8D 8F 8B 9B
|
||
|
||
sg:0128 94 9B 8D 00 AE EC 9C 9B 8A 9B 86 00 A9 EC 91
|
||
|
||
This is a typical encoded matrix, with clear 00 fences between
|
||
|
||
the encoded passwords.
|
||
|
||
Ha! If all codes where so easy to crack! This is no better than
|
||
|
||
children's crypt! It's a NEG matrix! And there is direct
|
||
|
||
correspondence: 91=6F="o"; 92=6E="n"; 93=6D="m" and so on... Ha!
|
||
|
||
Let's now leave the "hidden" passwords and proceed with our
|
||
|
||
cracking... let's follow the snap procedure after the REPZ CMPSB
|
||
|
||
instruction looking for the "jump to OK" instruction...
|
||
|
||
F3A6 REPZ CMPSB ; compares DS:SI with ES:DI
|
||
|
||
7405 JZ preserved_AX=0000 <--- Here the first JZ
|
||
|
||
1BC0 SBB AX,AX
|
||
|
||
ADFFFF SBB AX,FFFF
|
||
|
||
:preserved_AX=0000
|
||
|
||
8BF3 MOV SI,BX
|
||
|
||
8BFA MOV DI,DX
|
||
|
||
5D POP BP
|
||
|
||
CB RETF
|
||
|
||
....
|
||
|
||
83C404 ADD SP,+04
|
||
|
||
0BC0 OR AX,AX
|
||
|
||
7509 JNZ 0276 <------ And here it is!
|
||
|
||
Now, remembering the UMS crack, you would probably want to
|
||
|
||
change the JZ instruction in a JNZ instruction (you tried it on
|
||
|
||
the fly INSIDE [Soft-Ice] and it did work!), the "74" with a
|
||
|
||
"75" also. And then you would like to change the JNZ instruction
|
||
|
||
in a JZ instruction... Please feel free to try it... it will NOT
|
||
|
||
work! (You will not even find the second JNZ in the program
|
||
|
||
code). You should always be aware of the SMC (self modifying
|
||
|
||
code) protections: parts of the code my be decrypted "on the
|
||
|
||
fly", as needs arise, by the program. The code you modify while
|
||
|
||
the program is running may be different from the code of the
|
||
|
||
"dead" program.
|
||
|
||
Here we have a small "improvement" of the primitive: the
|
||
|
||
same instruction is used as "muster" for manipulation of other
|
||
|
||
parts of the program... if you do change it in a JNZ you get an
|
||
|
||
overlay message and the program pops out with instability! You
|
||
|
||
cannot easily modify the JNZ instruction either, coz the part
|
||
|
||
after the RETF will be compiled "on the fly" by lightspeed, and
|
||
|
||
you would therefore have to search the decryption mechanism and
|
||
|
||
modify the original encrypted byte somewhere... and may be they
|
||
|
||
do encrypt it twice... and then you must hack all night long...
|
||
|
||
very annoying.
|
||
|
||
So do the following: back to the snap, a sip of martini-
|
||
|
||
Wodka and meditate: loo! The only thing that happens after the
|
||
|
||
JZ, is the setting of the AX register to flag *FALSE* (AX=1...
|
||
|
||
that's what the two SBB instructions do) if the snap went out
|
||
|
||
with a non-zero flag... i.e. if you did not know the password.
|
||
|
||
So let's nop the 5 bytes of the two SBB instructions, or, more
|
||
|
||
elegantly, let's have a INC AX, DEC AX, NOP, INC AX, DEC AX
|
||
|
||
sequence instead of the two SBB! There is a good reason to use
|
||
|
||
a sequence of working instructions instead of a series of NOPs:
|
||
|
||
recent protection schemes "smell" patched nops inside the program
|
||
|
||
and trash everything if they find more than -say- three
|
||
|
||
consecutive NOPs! You should always try to choose THE LESS
|
||
|
||
INTRUSIVE and MORE "CAMOUFLAGED" solution when you crack!
|
||
|
||
Eliminating the two SBBs we get our crack! No need to bother
|
||
|
||
with the second JNZ either... the program will work as if you got
|
||
|
||
the password if you have it AND if you do not (that's better as
|
||
|
||
the previous type of crack -seen for UMS- when you crack computer
|
||
|
||
accesses: hereby the legitimate user will not have any suspects
|
||
|
||
'coz the system will not shut him out... everybody will access:
|
||
|
||
the good guys and the bad ones... that's nice isn't it?).
|
||
|
||
Now let's quickly crack LIGHTSPD:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING LIGHTSPEED.EXE (by +ORC, January 1996)
|
||
|
||
ren lightspd.exe lightspd.ded
|
||
|
||
symdeb lightspd.ded
|
||
|
||
- s (cs+0000):0 Lffff 2B F9 F3 A6 74
|
||
|
||
xxxx:yyyy (this is the answer of the debugger)
|
||
|
||
- s (cs+1000):0 Lffff 2B F9 F3 A6 74
|
||
|
||
(nothing, but do it nonetheless, just to be sure)
|
||
|
||
- s (cs+2000):0 lffff 2B F9 F3 A6 74
|
||
|
||
(nothing, just to be sure, now it's enough)
|
||
|
||
- e xxxx:yyyy+6 40 [SPACE] 48 [SP] 90 [SP] 40 [SP] 48
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren lightspd.ded lightspd.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
All this CMPSB is very common. Some programs, nevertheless,
|
||
|
||
utilize a password protection scheme that is slightly different,
|
||
|
||
and does not rely on a F3A6 REPZ CMPSB instruction. Let's
|
||
|
||
analyze, for instance, the protection scheme used in the first
|
||
|
||
version of Perfect general I from QQP-White wolf, July 1992.
|
||
|
||
When you break in, at the nag screen, you are in the middle of
|
||
|
||
the BIOS procedures, coz the program expects your input (your
|
||
|
||
password, that's is). You 'll quickly find out (MAP MEMORY
|
||
|
||
USAGE!) that [General.exe] dwells in two main areas; Setting
|
||
|
||
breakpoints on memory write you 'll find out that the memory area
|
||
|
||
"queried" by the protection mechanism is
|
||
|
||
xxxx:1180 to xxxx:11C0
|
||
|
||
where xxxx represents the second of the memory segments where the
|
||
|
||
program dwells. Now do the following (a very common cracking
|
||
|
||
procedure):
|
||
|
||
* Breakpoint on memory range WRITE for the small memory area
|
||
|
||
touched by the program in querying you for the password.
|
||
|
||
* Breakpoint TRACE on the whole memory range of the MAIN
|
||
|
||
CODE.
|
||
|
||
* Run anew everything
|
||
|
||
It's already done! Now it's your intuition that should work a
|
||
|
||
little: Here the last 9 traces (traces [!], not instructions
|
||
|
||
following on a line) before the calling of the procedure sniffing
|
||
|
||
your memory area:
|
||
|
||
-9 xxxx:0185 7425 JZ somewhere, not taken
|
||
|
||
-8 xxxx:0187 2D1103 SUB AX,0311
|
||
|
||
-7 xxxx:018A 7430 JZ somewhere, not taken
|
||
|
||
-6 xxxx:018C 2DFD04 SUB AX,04FD
|
||
|
||
-5 xxxx:018F 7443 JZ next_trace, taken
|
||
|
||
-4 xxxx:01D4 E85500 CALL funny_procedure
|
||
|
||
-3 xxxx:022C 803E8F8C11 CMP BYTE PTR[8C8F],11
|
||
|
||
-2 xxxx:0231 750E JNZ somewhere, not taken
|
||
|
||
-1 xxxx:0233 9A0A0AC33E CALL procedure_that_sniffs
|
||
|
||
our_memory_area
|
||
|
||
Well, the call to funny_procedure followed by a byte compare
|
||
|
||
"feels" fishy from very far away, so let's immediately look at
|
||
|
||
this part of the code of [General.exe]
|
||
|
||
:funny_procedure
|
||
|
||
803E8F8C11 CMP BYTE PTR[8C8F],11
|
||
|
||
750E JNZ compare_byte
|
||
|
||
9A0A0AC333 CALL procedure_that_sniffs
|
||
|
||
0AC0 OR AL,AL
|
||
|
||
7405 J2 compare_byte
|
||
|
||
C6068F8C2A MOV BYTE PTR [8C8F],2A
|
||
|
||
:compare_byte
|
||
|
||
803E8F8C2A CMP BYTE PTR [8C8F],2A
|
||
|
||
7504 JNZ after_ret
|
||
|
||
B001 MOV AL,01
|
||
|
||
C3 RET
|
||
|
||
You should be enough crack-able ;=), by this lesson, to notice
|
||
|
||
immediately the inconsistency of the two successive instructions
|
||
|
||
MOV 2A and CMP 2A, coz there would be no sense in comparing the
|
||
|
||
"2A" in order to JNZ to after_ret if you just had the 2A set with
|
||
|
||
the precedent MOV instruction... but the first JNZ jumps to the
|
||
|
||
compare WITHOUT putting the "2A" inside. And "2A" is nothing else
|
||
|
||
as the "*" symbol, commonly used by programmer as "OK"! This
|
||
|
||
protection works in the following way (this is the above code
|
||
|
||
explained):
|
||
|
||
- compare holy_location with 11
|
||
|
||
- jump non zero to compare holy_loc with "*"
|
||
|
||
- else call sniffing protection part
|
||
|
||
- or al,al (al must be zero, else)
|
||
|
||
- jump zero to compare holy_loc with "*"
|
||
|
||
- if al was zero mov "*" inside holy_loc
|
||
|
||
- compare holy_loc with "*"
|
||
|
||
- if there is a difference then JNZ beggar_off_ugly_copier
|
||
|
||
- else ret_ahead_nice_buyer
|
||
|
||
Now let's quickly crack it:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING GENERAL.EXE (by +ORC, January 1996)
|
||
|
||
ren general.exe general.ded
|
||
|
||
symdeb general.ded
|
||
|
||
- s (cs+0000):0 Lffff 8C 11 75 0E
|
||
|
||
xxxx:yyyy (this is the answer of the debugger)
|
||
|
||
- e xxxx:yyyy+2 EB [SPACE] 09
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren general.ded general.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
And in this way you changed the JNZ to the cmp "*" instruction
|
||
|
||
in a JMP to the mov "*" instruction. So no more nag screens, no
|
||
|
||
more protections... serene, placid, untroubled [general.exe].
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 3.2: hands on, paper protections (2)
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[TOP.EXE] [F19.EXE] [POPULOUS.EXE] [MAP.EXE]
|
||
|
||
--------------------------------------
|
||
|
||
You have seen in the previous lesson that the use of a password
|
||
|
||
protection, independently of the coding and hiding methods used
|
||
|
||
to store them in memory, implies the use of a comparing procedure
|
||
|
||
with the password that the user types in. You therefore have many
|
||
|
||
options to begin your cracking work:
|
||
|
||
- find the location of the user password
|
||
|
||
- find the "echo" in memory of the real password
|
||
|
||
- find the routine that compares both
|
||
|
||
- find the passwords hideout and encryption type
|
||
|
||
- find the go_ahead_nice_buyer exit or jump
|
||
|
||
- find the beggar_off_ugly_copier exit or jump
|
||
|
||
just to name the more obvious ones. In order to make things more
|
||
|
||
difficult for us crackers, the protectionists have devised many
|
||
|
||
counter-strategies, the more obvious ones being:
|
||
|
||
- keeping the various part of the store/compare/hide routines
|
||
|
||
well apart in code (no match for zen-cracking);
|
||
|
||
- filling these routines with "bogus" compares, bogus jumps
|
||
|
||
and bogus variables, in order to make things more difficult for
|
||
|
||
the crack (no match for decent crackers);
|
||
|
||
- disseminating the code with anti-debugger tricks, like INT_3
|
||
|
||
instructions or jumps in and out protected mode (no match for our
|
||
|
||
beloved [Soft-Ice]);
|
||
|
||
- trying to eliminate the need for passwords altogether
|
||
|
||
letting the user input "one letter" or "one number" or "one
|
||
|
||
image" as answer to some variable question. In this lesson I'll
|
||
|
||
teach you how to crack these "passletters" protection techniques.
|
||
|
||
Let's first resume the "uses" of a password protection:
|
||
|
||
PASSWORDS AS PERMISSION TO ACCESS
|
||
|
||
These passwords serve to acknowledge that a legitimate user is
|
||
|
||
using the program. This is the type of password that you'll find,
|
||
|
||
for example, protecting your user account on Compuserve, on
|
||
|
||
Networks or even in ATM machines used by banks or corporations.
|
||
|
||
These require a little hardwiring to crack: ATM passnumber
|
||
|
||
protection schemes rely on an answer from the central computer
|
||
|
||
(they do NOT verify only the three magnetic areas in the magnetic
|
||
|
||
strip on the card). The lines between ATM's & their hosts are
|
||
|
||
usually 'weak' in the sense that the information transmitted on
|
||
|
||
them is generally not encrypted in any way. (Some banks use
|
||
|
||
encrypted information, but this is fairly easy to crack too).
|
||
|
||
So for ATMs you should do the following 1) cross over the
|
||
|
||
dedicated line between the ATM and the host; 2) insert your
|
||
|
||
computer between the ATM and the host; 3) Listen to the "normal"
|
||
|
||
messages and DO NOT INTERFERE YET; 4) Try out some operations
|
||
|
||
with a legal card, make some mistakes, take note of the various
|
||
|
||
codes; 5) When you are ready insert a fraudulent card into the
|
||
|
||
ATM. Now the following happens:
|
||
|
||
- the ATM sends a signal to the host, saying "Hey! Can I give
|
||
|
||
this guy money, or is he broke, or is this funny card invalid?";
|
||
|
||
- the microcomputer intercepts the signal from the host,
|
||
|
||
discards it, sends on the "there's no one using the ATM" signal;
|
||
|
||
- the host gets the "no one using" signal and sends back its
|
||
|
||
"good, keep watching out if somebody comes by, and for God's sake
|
||
|
||
don't spit out any money on the street!" signal to the ATM;
|
||
|
||
- the microcomputer intercepts this signal (again), throws it
|
||
|
||
away (again), and sends the "Wow! That guy is like TOO rich! Give
|
||
|
||
him as much money as he wants. In fact, he's so loaded, give him
|
||
|
||
ALL the cash we have! He is a really valued customer." signal.
|
||
|
||
- the ATM obediently dispenses cash till the cows come home.
|
||
|
||
All this should be possible, but as a matter of fact it has
|
||
|
||
not much to do with cracking, unless there is a special software
|
||
|
||
protection on the line... so if you want to work on ATMs contact
|
||
|
||
our fellow phreakers/hackers and learn their trade... and
|
||
|
||
please remember to hack only cash dispenser that DO NOT HAVE a
|
||
|
||
control camera :=)
|
||
|
||
PASSWORDS AS REGISTRATION
|
||
|
||
This type of password is often used in shareware programs. When
|
||
|
||
you register the shareware program, you are sent a password that
|
||
|
||
you use to upgrade your shareware program to a complete and more
|
||
|
||
powerful version. This method, used frequently for commercial
|
||
|
||
applications, has recently been used quite a lot by many windows
|
||
|
||
applications that come "crippled" on the magazines cover CD-roms,
|
||
|
||
requiring you to telephone a hot line (and paying) in order to
|
||
|
||
get the "unique key" to unlock the "special protection". It's all
|
||
|
||
bullshit: we'll learn in the "how to crack windows" lessons how
|
||
|
||
easy it is to disable the various routines that verify your
|
||
|
||
entry.
|
||
|
||
PASSWORDS AS COPY PROTECTIONS
|
||
|
||
This type of password is often used for games and entertainment
|
||
|
||
software. The password query does not usually appear any more at
|
||
|
||
the start of the program, or as the program is loading. Instead,
|
||
|
||
the password query appears after one or more levels are completed
|
||
|
||
(this innovation was pioneered by "EOB I" and the "Ultima"
|
||
|
||
series) or when the user reloads a saved game or session.
|
||
|
||
DONGLE PASSWORDS
|
||
|
||
A few extremely expensive programs use a dongle (also called
|
||
|
||
an hardware key). A dongle is a small hardware device containing
|
||
|
||
a password or checksum which plugs into either a parallel or a
|
||
|
||
serial port. Some specially designed dongles even include
|
||
|
||
complete program routines. Dongles can be cracked, but the amount
|
||
|
||
of work involved is considerable and the trial and error
|
||
|
||
procedure currently used to crack them via software is extremely
|
||
|
||
tedious. It took me more than a week to crack MULTITERM,
|
||
|
||
Luxembourger dongle protected program. The quickest method to
|
||
|
||
crack dongle protected programs, involves the use of pretty
|
||
|
||
complicated hardware devices that cannot be dealt with here. I
|
||
|
||
myself have only seldom seen them, and do not like at all to
|
||
|
||
crack dongles via software, coz it requires a huge amount of zen
|
||
|
||
thinking and of luck and of time. If you want more information
|
||
|
||
on the hardware way to crack dongles, try to contact the older
|
||
|
||
ones on the appropriate web sites, they may even answer you if
|
||
|
||
you are nice, humble and really technically interested.
|
||
|
||
The obvious principle, that applies to the software password
|
||
|
||
types mentioned above is the following: The better the password
|
||
|
||
is hidden, and the better it is encrypted, the more secure the
|
||
|
||
program will be. The password may be
|
||
|
||
- encrypted and/or
|
||
|
||
- in a hooked vector and/or
|
||
|
||
- in an external file and/or
|
||
|
||
- in a SMC (Self modifying code) part
|
||
|
||
Let's finally inspect the common "ready_made" protection
|
||
|
||
schemes (used by many programmers that do not program
|
||
|
||
themselves):
|
||
|
||
* password read in
|
||
|
||
* letters added to a key to be entered
|
||
|
||
* complement of the letters formed xoring with 255
|
||
|
||
* saved key (1 char)
|
||
|
||
* saved password (256 chars)
|
||
|
||
* saved checksum (1 char), as protection, against simple
|
||
|
||
manipulations
|
||
|
||
* generating file PASSWORD.DAT with password, to be inserted
|
||
|
||
inside a different file than the one containing the calling
|
||
|
||
routine
|
||
|
||
Now the lazy programmer that wants to "protect" his program
|
||
|
||
searches first the file where the password is stored, then loads
|
||
|
||
the key, the password and the checksum. He uses a decrypt
|
||
|
||
procedure to decrypt the password and a check_checksum procedure
|
||
|
||
to check whether the password was modified. All this is obviously
|
||
|
||
crackabe in few seconds.
|
||
|
||
[PASSWORD ACCESS INSIDE THE SETUP]
|
||
|
||
Some computers have a password protected access INSIDE the
|
||
|
||
Setup (at the beginning), the protection scheme does not allow
|
||
|
||
a boot with a floppy and does not allow a setup modify. In these
|
||
|
||
cases the only possible crack is an old hack method:
|
||
|
||
* open the PC
|
||
|
||
* find on the motherboard a small jumper (bridge) with the
|
||
|
||
words "Pw"
|
||
|
||
* take it away
|
||
|
||
* PC on
|
||
|
||
* run the setup with F1 or Del (depending from the BIOS) (the
|
||
|
||
protection will not work any more)
|
||
|
||
* deactivate inside the setup the option password
|
||
|
||
* PC off
|
||
|
||
* put the small jumper (bridge) back again
|
||
|
||
* close the PC
|
||
|
||
* PC on, cracked (if you want to be nasty you could now use
|
||
|
||
the setup to set YOUR password)
|
||
|
||
If you want to know more about access refuse and access
|
||
|
||
denying, encryption and locking of the FAT tables, get from the
|
||
|
||
web, and study, the (very well written) code of a virus called
|
||
|
||
"Monkey", that does exactly this kind of devastation. Virus
|
||
|
||
studying is, in general, very useful for cracking purposes, coz
|
||
|
||
the virus'code is at times
|
||
|
||
- very well written (pure, tight assembly)
|
||
|
||
- using concealing techniques not much different from the
|
||
|
||
protection schemes (often far superior)
|
||
|
||
- using the most recent and best SMC (self modifying code)
|
||
|
||
tricks
|
||
|
||
But, and this is very important, do not believe that the
|
||
|
||
protection schemes are very complicated! Most of the time the
|
||
|
||
protection used are incredibly ordinary: as a final example of
|
||
|
||
our paper protection schemes, let's take a program released not
|
||
|
||
long ago (1994), but with a ridiculous protection scheme: TOP
|
||
|
||
(Tiger on the prowl) a simulation from HPS.
|
||
|
||
Here the cracking is straightforward:
|
||
|
||
- MAP(memory_usage) and find main_sector
|
||
|
||
- type "AAAA" as password
|
||
|
||
- (s)earch main_sector:0 lffff "AAAA"
|
||
|
||
- dump L80 "AAAA" location -40 (gives you a "wide" dump),
|
||
|
||
this gives you already the "echo" of the correct password
|
||
|
||
- breakpoint on memory read & write to "AAAA" location and
|
||
|
||
backtrace the complete main_sector
|
||
|
||
it's done! Here the code_lines that do protect TOP:
|
||
|
||
8A841C12 MOV AL,[SI+121C] move in AL first user letter
|
||
|
||
3A840812 CMP AL,[SI+1208] compare with echo
|
||
|
||
7402 JZ go_ahead_nice_buyer
|
||
|
||
EB13 JMP beggar_off_ugly_cracker
|
||
|
||
Now let's quickly crack it:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING TOP.EXE (by +ORC, January 1996)
|
||
|
||
ren top.exe top.ded
|
||
|
||
symdeb top.ded
|
||
|
||
- s (cs+0000):0 Lffff 8A 84 1C 12 3A 84
|
||
|
||
xxxx:yyyy (this is the answer of the debugger)
|
||
|
||
- e xxxx:yyyy+2 08 (instead of 1C)
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren top.ded top.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
And you changed the MOV AL, [SI+121C] instruction in a MOV AL,
|
||
|
||
[SI+1208] instruction... it is now reading the ECHO instead of
|
||
|
||
the characters you typed in... no wonder that the ECHO does
|
||
|
||
compare exactly with itself... and you pass!
|
||
|
||
"SOMETHING FISHY UNDER COVERS"
|
||
|
||
Back to the "Passletter" type of password protected programs.
|
||
|
||
Let's take as an example the protection used in a game of 1990:
|
||
|
||
"F19", where the protection scheme asks you to identify a
|
||
|
||
particular plane's silhouette. This kind of protection is used
|
||
|
||
in order to avoid the use of memory locations where the passwords
|
||
|
||
are stored: we saw in the first part of our "passwords hands on"
|
||
|
||
how easy it is to crack those schemes.
|
||
|
||
To crack this kind of protection, you could try a technique know
|
||
|
||
as "memory snuffing". The protected program, START.EXE, install
|
||
|
||
itself first at location xxxx:0000 with a length of 6C62 bytes,
|
||
|
||
but proceeds to a relocation of its modules (with some SMC, self
|
||
|
||
modifying code parts) in different locations. What does all this
|
||
|
||
mean? Well, this could mean quite many things... the most
|
||
|
||
important one for crackers is that the protection code will
|
||
|
||
probably snap way ahead of the actual user input phase.
|
||
|
||
Now you 'll quickly find out that the routine determining
|
||
|
||
(randomly) which plane is being chosen, leaves the progressive
|
||
|
||
number of this plane in one memory location: (imc) 43CD:DADA.
|
||
|
||
This brings us to the random triggering mechanism:
|
||
|
||
E87FAF CALL random_seed
|
||
|
||
83C402 ADD SP,02
|
||
|
||
8946E8 MOV [BP-18],AX and ds:(BP-18) is the location
|
||
|
||
you are looking for
|
||
|
||
Now, every time this random triggers, you get a different number
|
||
|
||
(00-x14) in this location, corresponding to the different plane
|
||
|
||
the user should choose.
|
||
|
||
The random seed routine, evidently, comes back with the random
|
||
|
||
seed in AX... what we now need is to zero it: the user will
|
||
|
||
always have to choose the same plane: "plane 0", and he will have
|
||
|
||
given the correct answer. Note how elegant all this is: we do not
|
||
|
||
need to interfere with the whole mouse pointing routines, nor
|
||
|
||
with the actual choosing of the planes... the random seed may
|
||
|
||
choose whatever plane it wishes... the memory location for this
|
||
|
||
choice will always report the (legitimate) choice of zero.
|
||
|
||
So, let's quickly crack this program:
|
||
|
||
---------------------------------------------------
|
||
|
||
CRACKING "F19" [START.EXE] (by +ORC, January 1996)
|
||
|
||
ren start.exe start.ded <- let's have a dead file
|
||
|
||
symdeb start.ded <- let's debug it
|
||
|
||
- s cs:O lffff 83 C4 02 89 46 E8 <- search ADD SP,02
|
||
|
||
xxxx:yyyy <- debugger's answer
|
||
|
||
- e xxxx:yyyy 58 [SPACE] 31 [SPACE] C0 [SPACE]
|
||
|
||
- w <- write the crack
|
||
|
||
- q <- back to the OS
|
||
|
||
ren start.ded start.exe <- re-write the exe
|
||
|
||
----------------------------------------------------
|
||
|
||
You just transformed the instruction you searched for
|
||
|
||
83C402 ADD SP,+02
|
||
|
||
in the following sequence:
|
||
|
||
58 POP AX <- respecting ADD SP,+02
|
||
|
||
31C0 XOR AX,AX <- xoring to zero
|
||
|
||
(the POP AX instruction increments the stack pointer by 2, in
|
||
|
||
order to respect the previous ADD SP,+02).
|
||
|
||
Well, nice. It's getting easier, isnt'it? Now let's take as
|
||
|
||
example a protection that has no "echo" in memory. (At the
|
||
|
||
beginning this was a smart idea: "the cracker won't find the
|
||
|
||
correct password, 'coz it's not there, ah!". We'll now therefore
|
||
|
||
crack one of the first programs that used this scheme:
|
||
|
||
[Populous.exe], from Bullfrog.
|
||
|
||
[POPULOUS.EXE]
|
||
|
||
A old example of the protection scheme "password that is not
|
||
|
||
a password" can be found in [Populous.exe], from Bullfrog. It's
|
||
|
||
a very widespread program, and you'll surely be able to find a
|
||
|
||
copy of it in order to follow this lesson. The program asks for
|
||
|
||
the identification of a particular "shield", a combination of
|
||
|
||
letters of various length: the memory location were the user
|
||
|
||
password is stored is easily found, but there is (apparently) no
|
||
|
||
"echo" of the correct password. You should be able, by now, to
|
||
|
||
find by yourself the memory location were the user password is
|
||
|
||
stored. Set a breakpoint memory read & write on this area, and
|
||
|
||
you 'll soon come to the following section of code:
|
||
|
||
F7AE4EFF IMUL WORD PTR [BP+FF4E] <- IMUL with magic_N<5F>
|
||
|
||
40 INC AX
|
||
|
||
3B460C CMP AX, [BP+0C]
|
||
|
||
7509 JNZ beggar_off_ugly_copier
|
||
|
||
8B460C MOV AX, [BP+0C]
|
||
|
||
A3822A MOV [2A82], AX
|
||
|
||
E930FE JMP nice_buyer
|
||
|
||
817E0C7017CMP WORD PTR[BP+0C],1770 <- beggar_off
|
||
|
||
I don't think that you need much more now... how do you prefer
|
||
|
||
to crack this protection scheme? Would you choose to insert a MOV
|
||
|
||
[BP+0C], AX and three NOPS (=6 bytes) after the IMUL instruction?
|
||
|
||
Wouldn't you rather prefer the more elegant JMP to nice_buyer
|
||
|
||
instruction at the place of the JNZ beggar_off? This solution has
|
||
|
||
less nops: remember that newer protection schemes smell
|
||
|
||
NOPs_patches!). Yeah, let's do it this way:
|
||
|
||
---------------------------------------------------
|
||
|
||
CRACKING [Populous.exe] (by +ORC, January 1996)
|
||
|
||
ren populous.exe populous.ded <- let's have a dead file
|
||
|
||
symdeb populous.ded <- let's debug it
|
||
|
||
- s cs:O lffff F7 AE 4E FF <- the imul magic_N<5F>
|
||
|
||
xxxx:yyyy <- debugger's answer
|
||
|
||
- e xxxx:yyyy+4 EB [SPACE] 03 <- JMP anyway
|
||
|
||
- w <- modify ded
|
||
|
||
- q <- back to the OS
|
||
|
||
ren populous.ded populous.exe <- let's re-have the exe
|
||
|
||
----------------------------------------------------
|
||
|
||
This time was easy, wasnt'it?
|
||
|
||
Now you are almost ready with this course... let's crack a
|
||
|
||
last application, a memory utility that is very widespread, very
|
||
|
||
good (the programmers at Clockwork software are Codemasters),
|
||
|
||
very useful for our purposes (you'll use it later to crack a lot
|
||
|
||
of TSR) and, unfortunately for Clockworkers, very easy to crack
|
||
|
||
at the level you are now.
|
||
|
||
But, Hey! Do not forget that you would have never done it without
|
||
|
||
this tutorial, so do the following: look toward east from your
|
||
|
||
window, sip a Martini-Wodka (Two blocks of ice first, 1/3 dry
|
||
|
||
Martini from Martini & Rossi, 1/3 Moskovskaia Wodka, 1/3
|
||
|
||
Schweppes indian tonic) and say three times: Thank-you +ORC!.
|
||
|
||
[MAP.EXE]
|
||
|
||
Let's now go over to one of the best TOOLS for mapping your
|
||
|
||
memory usage that exist: MAP.EXE (version 2) from the masters at
|
||
|
||
Clockwork software. The usage of this tool has been recommended
|
||
|
||
in Lesson 2, and you should learn how to crack it, coz it comes
|
||
|
||
with an annoying nag-screen ("Nigel" screen). In [Map.exe] this
|
||
|
||
ubiquitous "Nigel" screen appears at random waiting for a random
|
||
|
||
amount of time before asking the user to press a key which varies
|
||
|
||
every time and is also selected at random.
|
||
|
||
The use of a single letter -mostly encrypted with some XOR
|
||
|
||
or SHR- as "password" makes the individuation of the relevant
|
||
|
||
locations using "snap compares" of memory much more difficult.
|
||
|
||
But the crack technique is here pretty straightforward: just
|
||
|
||
break in and have a good look around you.
|
||
|
||
The INT_16 routine for keyboard reading is called just after
|
||
|
||
the loading of the nag screen. You 'll quickly find the relative
|
||
|
||
LODSB routine inside a routine that paints on screen the word
|
||
|
||
"Press" and a box-edge after a given time delay:
|
||
|
||
B95000 MOV CX,0050
|
||
|
||
2EFF366601 PUSH CS:[0166]
|
||
|
||
07 POP ES
|
||
|
||
AC LODSB
|
||
|
||
...
|
||
|
||
You could already eliminate the delay and you could already force
|
||
|
||
always the same passletter, in order to temperate the effects of
|
||
|
||
the protection... but we crack deep!: let's do the job and track
|
||
|
||
back the caller! The previous routine is called from the
|
||
|
||
following section of the code:
|
||
|
||
91 XCHG AX,CX
|
||
|
||
6792 XCHG AX,DX
|
||
|
||
28939193 SUB [BP+DI+9391],DL
|
||
|
||
2394AA94 AND DX,[SI+94AA]
|
||
|
||
2EC7064B880100 MOV WORD PTR CS:[884B],0001
|
||
|
||
2E803E5C0106 CMP BYTE PTR CS:[015C],06
|
||
|
||
7416 JZ ret <- Ha! jumping PUSHa & POPa!
|
||
|
||
505351525756 PUSH the lot
|
||
|
||
E882F3 CALL 8870
|
||
|
||
2E3B064B88 CMP AX,CS:[884B]
|
||
|
||
7307 JAE after RET <- Ha! Not taking the RET!
|
||
|
||
5E5F5A595B58 POP the lot
|
||
|
||
C3 RET
|
||
|
||
... <- some more instructions
|
||
|
||
E86700 CALL delay_user
|
||
|
||
BE9195 MOV SI,9591
|
||
|
||
2E8B3E255C MOV DI,CS:[5C25]
|
||
|
||
83EF16 SUB DI,+16
|
||
|
||
2E8A263D01 MOV AH,CS:[013D]
|
||
|
||
50 PUSH AH
|
||
|
||
E892C7 CALL routine_LODSB <-- HERE!
|
||
|
||
B42C MOV AH,2C
|
||
|
||
CD21 INT 21 <- get seconds in DH
|
||
|
||
80E60F AND DH,0F
|
||
|
||
80C641 ADD DH,41
|
||
|
||
58 POP AX
|
||
|
||
8AC6 MOV AL,DH
|
||
|
||
83EF04 SUB DI,+4
|
||
|
||
AB STOSW
|
||
|
||
E85A00 CALL INT_16_AH=01
|
||
|
||
B400 MOV AH,00
|
||
|
||
CD16 INT 16
|
||
|
||
24DF AND AL,DF <- code user's letter_answer
|
||
|
||
3AC6 CMP AL,DH <- pass_compare
|
||
|
||
75F3 JNZ CALL INT_16_AH=01
|
||
|
||
E807F3 go_ahead
|
||
|
||
You just need to look at these instructions to feel it: I
|
||
|
||
think that unnecessary code segments (in this case protections)
|
||
|
||
are somehow like little snakes moving under a cover: you cannot
|
||
|
||
easily say what's exactly going on yet, but you could bet that
|
||
|
||
there is something fishy going on. Look at the code preceding
|
||
|
||
your LODSB routine call: you find two JUMPS there: a JZ ret, that
|
||
|
||
leaves a lot of pusha and popa aside, and a JAE after RET, that
|
||
|
||
does not take the previous ret. If you did smell something here
|
||
|
||
you are thoroughly right: The first JZ triggers the NIGEL screen
|
||
|
||
protection, and the second JAE does THE SAME THING (as usual,
|
||
|
||
there are always redundances, exactly as there are a lot of
|
||
|
||
possibilities to disable a single protection). Now you know...
|
||
|
||
you can disable this protection at different points: the two
|
||
|
||
easiest blueprints being
|
||
|
||
1) to change 7416 (JZ ret) in a EB16 (JMP ret anyway)
|
||
|
||
2) to change 7307 (JAE after ret) in a 7306 (JAE ret).
|
||
|
||
We have not terminated yet: if you try locating this part
|
||
|
||
of the code in order to change it, you won't have any luck: it's
|
||
|
||
a SMC (Self modifying code) part: it is loaded -partly- from
|
||
|
||
other sections of the code (here without any encryption). You
|
||
|
||
must therefore first of all set a breakpoint on memory range;
|
||
|
||
find out the LODSW routine; find out the real area; dump that
|
||
|
||
memory region; find out a search sequence for the "dead" code...
|
||
|
||
and finally modify the "dead" program.
|
||
|
||
Now let's quickly crack it:
|
||
|
||
------------------------------------------------
|
||
|
||
CRACKING MEM.EXE (version 2) (by +ORC, January 1996)
|
||
|
||
ren map.exe map.ded
|
||
|
||
symdeb map.ded
|
||
|
||
- s (cs+0000):0 Lffff 74 16 50 53 51 52 57
|
||
|
||
xxxx:yyyy <- this is the debugger's answer
|
||
|
||
- e xxxx:yyyy EB
|
||
|
||
- w
|
||
|
||
- q
|
||
|
||
ren map.ded map.exe
|
||
|
||
-------------------------------------------------
|
||
|
||
Now you have done it, NIGEL has been cracked!
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 5.1: Disk & CD-Rom access (basics)
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[MARIO ANDRETTI] [REACH FOR THE SKY] [FS v.2.12]
|
||
|
||
--------------------------------------
|
||
|
||
LESSON 5 (1) - HOW TO CRACK, HANDS ON - Disk/CDROM access (plus
|
||
|
||
bypasses "on the fly")
|
||
|
||
Somewhere I have to put the bypasses (loader programs) in this
|
||
|
||
tutorial, allow me to put them here:
|
||
|
||
Preparing a loader to bypass a protection [MARIO ANDRETTI]
|
||
|
||
At time the protectionists hook vectors in order to impose
|
||
|
||
a particular protection. In this (and similar) cases a good
|
||
|
||
crack-way is to prepare a "loader" program, that "de-hooks" the
|
||
|
||
vector used for the protection. This kind of crack can be used
|
||
|
||
also for internet cracking (on some firewall configurations, see
|
||
|
||
lesson A.2).
|
||
|
||
As example let's take "Mario andretti racing challenge", a
|
||
|
||
stupid game that uses the SAME (!) protection scheme you'll still
|
||
|
||
find to day on some access routines of military servers around
|
||
|
||
the witlessly called "free" world.
|
||
|
||
In order to crack this cram you would prepare a loader on the
|
||
|
||
following lines:
|
||
|
||
loc code instruction what's going on
|
||
|
||
-------------------------------------------------------
|
||
|
||
:0100 EB44 JMP 0146
|
||
|
||
...
|
||
|
||
:0142 0000 <- storing for offset of INT_21
|
||
|
||
:0144 5887 <- storing for segment of INT_21
|
||
|
||
:0146 FA CLI
|
||
|
||
:0147 0E PUSH CS
|
||
|
||
:0148 1F POP DS
|
||
|
||
:0149 BCB403 MOV SP,03B4
|
||
|
||
:014C FB STI
|
||
|
||
:014D 8C1EA901 MOV [01A9],DS <- save DS
|
||
|
||
:0151 8C1EAD01 MOV [01AD],DS three
|
||
|
||
:0155 8C1EB101 MOV [01B1],DS times
|
||
|
||
:0159 B82135 MOV AX,3521 <- get INT_21
|
||
|
||
:015C CD21 INT 21 in ES:BX
|
||
|
||
:015E 891E4201 MOV [0142],BX <- store offset
|
||
|
||
:0162 8C064401 MOV [0144],ES <- store segment
|
||
|
||
:0166 BA0201 MOV DX,0102
|
||
|
||
:0169 B82125 MOV AX,2521 <- set INT_21 to
|
||
|
||
:016C CD21 INT 21 DS:0102
|
||
|
||
:016E 0E PUSH CS
|
||
|
||
:016F 07 POP ES <- ES= current CS
|
||
|
||
:0170 BBB403 MOV BX,03B4
|
||
|
||
:0173 83C30F ADD BX,+0F
|
||
|
||
:0176 B104 MOV CL,04
|
||
|
||
:0178 D3EB SHR BX,CL <- BX= 3C
|
||
|
||
:017A B8004A MOV AX,4A00 <- Modify memory block
|
||
|
||
:017D CD21 INT 21 to 3C paragraphs
|
||
|
||
:017F BA9E01 MOV DX,019E <- ds:dx=program name
|
||
|
||
:0182 BBA501 MOV BX,01A5 <- es:bx = param. block
|
||
|
||
:0185 B8004B MOV AX,4B00 <- load ma.com
|
||
|
||
:0188 CD21 INT 21
|
||
|
||
:018A 2E8B164201 MOV DX,CS:[0142] <- reset old int_21
|
||
|
||
:018F 2E8E1E4401 MOV DS,CS:[0144]
|
||
|
||
:0194 B82125 MOV AX,2521
|
||
|
||
:0197 CD21 INT 21
|
||
|
||
:0199 B8004C MOV AX,4C00 <- terminate with return
|
||
|
||
:019C CD21 INT 21 code
|
||
|
||
:019E 6D612E636F6D00 "ma.com"
|
||
|
||
0000 fence
|
||
|
||
:01A7 B2015887
|
||
|
||
:01AB B2015887
|
||
|
||
:O1AF B2015887
|
||
|
||
0000 fence
|
||
|
||
let's now prepare a routine that hooks INT_21:
|
||
|
||
push all
|
||
|
||
CMP AX,2500 <- go on if INT_21 service 25
|
||
|
||
JNZ ret
|
||
|
||
CMP Word Ptr [0065], C00B <- go on if location 65 = C00B
|
||
|
||
JNZ ret
|
||
|
||
MOV Byte Ptr [0060], EB <- crack instructions
|
||
|
||
MOV Byte Ptr [0061], 3C
|
||
|
||
MOV Byte Ptr [0062], 40 <- INC AX
|
||
|
||
MOV Byte Ptr [0063], 90 <- NOP
|
||
|
||
MOV Byte Ptr [0064], 48 <- DEC AX
|
||
|
||
pop all
|
||
|
||
JMP FAR CS:[0142] <- JMP previous INT_21
|
||
|
||
From now on this loader will work every time that a program
|
||
|
||
with location [0065] containing an 0R AX,AX instruction (0BC0:
|
||
|
||
it's the case of ma.com) calls INT_21 service 25 (hook a vector),
|
||
|
||
the target program will be modified on the fly and will get, at
|
||
|
||
location [0060], the instruction JMP 3C locations ahead, despite
|
||
|
||
the fact that it has routines capable of self checking in order
|
||
|
||
to make sure it has not been modified.
|
||
|
||
The most important thing is the routine that YOU write that
|
||
|
||
will precede the call to INT_21 (or any other INT) service 25 (or
|
||
|
||
any other service) in order to crack on the fly the offending
|
||
|
||
program. I'll show you another one, this one for [Reach for the
|
||
|
||
skies] (reach.com):
|
||
|
||
push all
|
||
|
||
CMP AH,3D <- is it service 3D? (open file)
|
||
|
||
JNZ ret <- no, so ret
|
||
|
||
CMP DX,13CE <- you wanna open file at 13CE?
|
||
|
||
JNZ ret <- no, so ret
|
||
|
||
MOV AX,[BP+04] <- in this case
|
||
|
||
MOV DS,AX
|
||
|
||
CMP Byte Ptr [B6DA],74 <- old instructions
|
||
|
||
JNZ 015B
|
||
|
||
CMP Byte Ptr [B6DB],0F <- ditto
|
||
|
||
JNZ 015B
|
||
|
||
CMP Byte Ptr [B6DC],80 <- ditto, now we now where we are
|
||
|
||
JNZ 015B
|
||
|
||
MOV Byte Ptr [B6DA],EB <- crack
|
||
|
||
MOV Byte Ptr [B697],40 <- camouflaged no-opping
|
||
|
||
MOV Byte Ptr [B698],48 <- cam nop
|
||
|
||
MOV Byte Ptr [B699],90 <- cam nop
|
||
|
||
MOV Byte Ptr [B69A],40 <- cam nop
|
||
|
||
MOV Byte Ptr [B69B],48 <- cam nop
|
||
|
||
MOV DX,CS:[0165]
|
||
|
||
MOV DS,CS:[0167]
|
||
|
||
MOV AX,2521 <- set hook
|
||
|
||
INT 21
|
||
|
||
POP all
|
||
|
||
JMP FAR CS:[0165]
|
||
|
||
Here you did change the instruction 740F in the instruction EB0F,
|
||
|
||
and you did "noop" the instructions at B697-B69B. (Well, more
|
||
|
||
elegantly than "noop" them with "90" bytes, you choose a INC AX,
|
||
|
||
DEC AX, NOP, INC AX, DEC AX sequence instead! There are sound
|
||
|
||
reasons to use a sequence of "working" instructions instead of
|
||
|
||
NOPs: recent protection schemes "smell" patched nops inside the
|
||
|
||
program and trash everything if they find more than -say- three
|
||
|
||
consecutive NOPs! You should always try to choose THE LESS
|
||
|
||
INTRUSIVE and MORE "CAMOUFLAGED" solution when you crack!)
|
||
|
||
You can apply this kind of crack, on the same lines, to many
|
||
|
||
programs that perform self checking of the code and hook the
|
||
|
||
vectors.
|
||
|
||
REAL DISK ACCESS STUFF
|
||
|
||
Now we may come to the subject of this lesson:
|
||
|
||
As usual, let's begin from the beginning: history is always
|
||
|
||
the key that allows an understanding of present and future, in
|
||
|
||
cracking matters too. As the older 5 1/4 inch big black floppy
|
||
|
||
disks were still used (the 320K/8 tracks or 360K/9 tracks ones,
|
||
|
||
that were really "floppy" and have nowadays almost disappeared)
|
||
|
||
one of the more common methods to protect a program, was to
|
||
|
||
format the "master" (key) disk in a weird way. Old floppy disk
|
||
|
||
for the PC did usually store 360K at 9 sectors per track.
|
||
|
||
Some basics for those of you that do not know anything: in
|
||
|
||
order to defeat this kind of cracks you need to know two things:
|
||
|
||
the floppy disk parameter block (FDPB) and the interrupt routines
|
||
|
||
dealing with format/read disk (basically INT_13).
|
||
|
||
Most often, the protection scheme is to either format one
|
||
|
||
or more sectors or tracks with sector sizes other than the
|
||
|
||
standard 512 bytes, or to either give one of the sectors a wild
|
||
|
||
sector number like 211 or just not format a whole track of
|
||
|
||
eight/nine/15 sectors. If you, for instance, have got the same
|
||
|
||
(very old) copy of VisiCalc master I do, you'll find that sector
|
||
|
||
8 on track 39 is missing entirely. The interrogation with
|
||
|
||
assembly or with an "ad hoc" utility (I use the tools I wrote
|
||
|
||
myself, but you 'll be able to find many such utilities in public
|
||
|
||
domain, the oldest one, from 1984 (!) being the seasoned [U-ZAP]
|
||
|
||
an "Ultra utility" from the "Freesoft company") will tell you
|
||
|
||
which sector numbers were altered, their size in bytes, and if
|
||
|
||
they were formatted with a CRC error (another not so fancy
|
||
|
||
trick).
|
||
|
||
The floppy disk parameters are stored in the BIOS: interrupt
|
||
|
||
vector 1E contains the address of the floppy disk parameter
|
||
|
||
block. The FDPB's contents are the following:
|
||
|
||
Offset Function crackworthy? Example
|
||
|
||
0 Step rate & head unload no DF
|
||
|
||
1 head load time no 02
|
||
|
||
2 Motor on delay no 25
|
||
|
||
3 Number of bytes per sector yes 02
|
||
|
||
4 Last sector number yes 12
|
||
|
||
5 Gap length yes 1B
|
||
|
||
6 Data track length yes FF
|
||
|
||
7 Format gap length yes 54
|
||
|
||
8 Format byte no F6
|
||
|
||
9 Head settle time no 0F
|
||
|
||
A Motor start time no 02
|
||
|
||
0) Offset #0: the left "nybble" (single digit) of this value
|
||
|
||
is the step rate time for the disk drive head. The right
|
||
|
||
nybble is the disk head unload time. These values are best
|
||
|
||
left alone.
|
||
|
||
1) Offset #1: again, don't fool around with these values. The
|
||
|
||
left nybble is the disk head load time, and the right
|
||
|
||
nybble is the direct memory access mode select.
|
||
|
||
2) Wait time until motor is turned off. Not normally of use.
|
||
|
||
3) Bytes-per-sector value: AH-HAH! If you place a "0" in this
|
||
|
||
value, the PC expects all sectors to be 128 bytes long. A
|
||
|
||
"1" means a sector size of 256 bytes, a "2" means 512
|
||
|
||
bytes (this is the standard DOS value), and a "3" means
|
||
|
||
1024 bytes per sector.
|
||
|
||
4) Highest sector number on a track: this is used for
|
||
|
||
formatting and tells DOS how many sectors there are on each
|
||
|
||
track.
|
||
|
||
5) Gap length for diskette reads: this is what you fool around
|
||
|
||
with if you keep getting CRC errors when you try to read a
|
||
|
||
non-standard size sector. Normally, you can just leave this
|
||
|
||
alone except when formatting with a U-Format tool.
|
||
|
||
6) Data length: This contains the number of bytes in a sector
|
||
|
||
when the value in table byte #4 doesn't contain a 0, 1, 2,
|
||
|
||
or 3.
|
||
|
||
7) Number of bytes in the gap between sectors: this is also
|
||
|
||
only used when formatting special tracks.
|
||
|
||
8) Format fill byte: When formatting, this is the
|
||
|
||
initialization byte that will be placed in all new sectors.
|
||
|
||
9) Head settle time: leave this alone.
|
||
|
||
A) Motor start time: don't fool with this either.
|
||
|
||
In order to modify globally the number of tracks on a given disk
|
||
|
||
and the number of sectors per track you can always format with
|
||
|
||
the DOS command switches "/t:" and "/n:"
|
||
|
||
FORMAT /t:tracks /n:sectors
|
||
|
||
If you want to find out what the existing parameters are,
|
||
|
||
run [Debug.exe] or [Symdeb.exe] and enter the following commands:
|
||
|
||
- d 0:78 l 4 <- get FDPB address
|
||
|
||
0000:0070 22 05 00 <- debugger's likely response
|
||
|
||
- d 0:522 l a <- get 10 FDPB values
|
||
|
||
0000:520 DF 02 25 02 12 1B FF... <- see preceding table
|
||
|
||
Remember that all standard disk formats under DOS support
|
||
|
||
a sector size of 512 bytes, therefore, for one-sided 5.25 inch
|
||
|
||
floppies:
|
||
|
||
40t*8s*512b=163.840 bytes (160Kb)
|
||
|
||
40t*9s*512b=184.320 bytes (180Kb)
|
||
|
||
and for two-sided 5.25 inch floppies:
|
||
|
||
40t*8s*512b*2sides=327.680 bytes (320Kb)
|
||
|
||
40t*9s*512b*2sides=368.640 bytes (360Kb)
|
||
|
||
Beginning with DOS version 3.0 (Yeah, more and more
|
||
|
||
history!) a new floppy disk format has been supported: The IBM
|
||
|
||
AT (80286 CPU) introduced the so called "high capacity" 5.25 u-
|
||
|
||
inch floppy, capable of storing 1.2M at 15 sectors per track:
|
||
|
||
80t*15s*512b*2sides=1.228.800 bytes (1.2Mb)
|
||
|
||
Later on were introduced the to-day universally used 3.5
|
||
|
||
inch floppies, the ones inside a rigid small plastic cartridge,
|
||
|
||
and we have, similarly:
|
||
|
||
3.5-inch double sided/double density 720K
|
||
|
||
3.5-inch double sided/quad density (HD) 1440K
|
||
|
||
3.5-inch double sided/high density 2880K
|
||
|
||
[INT_13, AH=18, Set media type for format]
|
||
|
||
In order to create weird layouts, the protectionists use
|
||
|
||
interrupt 13h, service 18h, that specifies to the formatting
|
||
|
||
routines the number of tracks and sectors per track to be placed
|
||
|
||
on the media:
|
||
|
||
* Registers on entry: AH=18h; CH=N<> of tracks; CL= Sectors
|
||
|
||
per track; DL= Drive number (A=0; B=1;C=2... bit 7 is set
|
||
|
||
if the drive is an hard disk)
|
||
|
||
* Registers on Return: DI: Offset address of 11-byte
|
||
|
||
parameter table; ES: Segment address of 11-byte parameter
|
||
|
||
table.
|
||
|
||
[INT_13, AH=2, Read disk sectors]
|
||
|
||
In order to read them, they have to use INT_13, service 2, read
|
||
|
||
disk sectors, with following layout:
|
||
|
||
* Registers on entry: AH=2h; AL= N<> of sectors; BX= Offset
|
||
|
||
address of data buffer; CH=track; CL= Sector; DH= Head
|
||
|
||
(side) number; DL= Drive number; ES: Segment address of
|
||
|
||
data buffer.
|
||
|
||
* Registers on Return: AH= return code. If the carry flag is
|
||
|
||
not set, AH=0, therefore the weird sector has been read, if
|
||
|
||
on the contrary the carry flag is set, AH reports the
|
||
|
||
status byte as follows:
|
||
|
||
76543210 HEX DEC Meaning
|
||
|
||
1 80h 128 Time out - drive crazy
|
||
|
||
1 40h 064 Seek failure, could not move to track
|
||
|
||
1 20h 032 Controller kaputt
|
||
|
||
1 10h 016 Bad CRC on disk read
|
||
|
||
1 09h 009 DMA error - 64K boundary crossed
|
||
|
||
1 08h 008 DMA overrun
|
||
|
||
1 04h 004 Bad sector - sector not found
|
||
|
||
11 03h 003 Write protect!
|
||
|
||
1 02h 002 Bad sector ID (address mark
|
||
|
||
1 01h 001 Bad command
|
||
|
||
[Return code AH=9: DMA boundary error]
|
||
|
||
One of the possible errors should be explained, coz it is
|
||
|
||
used in some protection schemes: AH=9 DMA boundary error, means
|
||
|
||
that an illegal boundary was crossed when the in formation was
|
||
|
||
placed into RAM. DMA (Direct memory access) is used by the disk
|
||
|
||
service routines to place information into RAM. If a memory
|
||
|
||
offset address ending in three zeros (ES:1000, ES: 2000...) falls
|
||
|
||
in the middle of the area being overlaid by a sector, this error
|
||
|
||
will occur.
|
||
|
||
[INT_13, AH=4 Verify disk sectors]
|
||
|
||
Another possible protection interrupt is interrupt 13H,
|
||
|
||
service 4, Verify disk sectors. Disk verification takes place on
|
||
|
||
the disk and DOES NOT involve verification of the data on the
|
||
|
||
disk against data in memory! This function has no buffer
|
||
|
||
specification, does not read or write a disk: it causes the
|
||
|
||
system to read the data in the designated sector or sectors and
|
||
|
||
to check its computed cyclic redundancy check (CRC) against data
|
||
|
||
stored on the disk. See INT_13, AH=2 registers and error report.
|
||
|
||
[CRC]
|
||
|
||
The CRC is a checksum, that detects general errors. When a
|
||
|
||
sector is written to disk, an original CRC is calculated AND
|
||
|
||
WRITTEN ALONG with the sector data. The verification service
|
||
|
||
reads the sector, recalculates the CRC, and compares the
|
||
|
||
recalculated CRC with the original CRC.
|
||
|
||
We saw that some protection schemes attempt to disguise
|
||
|
||
interrupt calls. This is particularly frequent in the disk access
|
||
|
||
protection schemes that utilize INT_13 (the "disk" interrupt).
|
||
|
||
If you are attempting to crack such programs, the usual
|
||
|
||
course of action is to search for occurrences of "CD13", which
|
||
|
||
is machine language for interrupt 13. One way or another, the
|
||
|
||
protection scheme has to use this interrupt to check for the
|
||
|
||
special sectors of the disk. If you examine a cross section of
|
||
|
||
the program, however, you'll find programs which do not have
|
||
|
||
"CD13" in their machine code, but which clearly are checking the
|
||
|
||
key disk for weird sectors. How comez?
|
||
|
||
There are several techniques which can be used to camouflage
|
||
|
||
the protection scheme from our nice prying eyes. I'll describe
|
||
|
||
here the three such techniques that are more frequent:
|
||
|
||
1) The following section of code is equivalent to issuing an
|
||
|
||
INT 13 command to read one sector from drive A, side 0, track
|
||
|
||
29h, sector ffh, and then checking for a status code of 10h:
|
||
|
||
cs:1000 MOV AH,02 ;read operation
|
||
|
||
cs:1002 MOV AL,01 ;1 sector to read
|
||
|
||
cs:1004 MOV CH,29 ;track 29h
|
||
|
||
cs:1006 MOV CL,FF ;sector ffh
|
||
|
||
cs:1008 MOV DX,0000 ;side 0, drive A
|
||
|
||
cs:100B XOR BX,BX ;move 0...
|
||
|
||
cs:100D MOV DS,BX ;...to DS register
|
||
|
||
cs:100F PUSHF ;pusha flags
|
||
|
||
cs:1010 PUSH CS ;pusha CX
|
||
|
||
cs:1011 CALL 1100 ;push address for next
|
||
|
||
instruction onto stack and branch
|
||
|
||
cs:1014 COMP AH,10 ;check CRC error
|
||
|
||
cs:1017 ... rest of verification code
|
||
|
||
...
|
||
|
||
...
|
||
|
||
cs:1100 PUSHF ;pusha flags
|
||
|
||
cs:1101 MOV BX,004C ;address of INT_13 vector
|
||
|
||
cs:1104 PUSH [BX+02] ;push CS of INT_13 routine
|
||
|
||
cs:1107 PUSH [BX] ;push IP of INT_13 routine
|
||
|
||
cs:1109 IRET ;pop IP,CS and flags
|
||
|
||
Notice that there is no INT 13 command in the source code, so if
|
||
|
||
you had simply used a debugger to search for "CD13" in the
|
||
|
||
machine code, you would never have found the protection routine.
|
||
|
||
2) Another technique is to put in a substitute interrupt
|
||
|
||
instruction, such as INT 10, which looks harmless enough, and
|
||
|
||
have the program change the "10" to "13 (and then back to "10")
|
||
|
||
on the fly. A search for "CD13" would turn up nothing.
|
||
|
||
3) The best camouflage method for interrupts I have ever
|
||
|
||
cracked (albeit not on a INT 13) was a jump to a section of the
|
||
|
||
PROGRAM code that reproduces in extenso the interrupt code. This
|
||
|
||
elegant (if a little overbloated) disguise mocks every call to
|
||
|
||
the replicated interrupt.
|
||
|
||
LOADING ABSOLUTE DISK SECTORS
|
||
|
||
Old good [debug.com] has been called the "swiss army knife" of
|
||
|
||
the cracker. It allows a lot of nice things, inter alia the
|
||
|
||
loading, reading, modifying and writing of absolute sectors of
|
||
|
||
the disks. The sector count starts with the first sector of track
|
||
|
||
0, next sector is track 0, second side (if double sided), then,
|
||
|
||
back to the first side, track 1, and so on, until the end of the
|
||
|
||
disk. Up to 80h (128) sectors can be loaded at one time. To use
|
||
|
||
you must specify starting address, drive (0=A, 1=B, etc...),
|
||
|
||
starting sector and number of sectors to load.
|
||
|
||
- l 100 0 10 20
|
||
|
||
This instruction tells DEBUG to load, starting at DS:0100, from
|
||
|
||
drive A, sector 10h for 20h sectors. This allows at times the
|
||
|
||
retrieval of hidden and/or weird formatted data. If you get an
|
||
|
||
error, check the memory location for that data. Often times, part
|
||
|
||
of the data has been transferred before the error occurs, and the
|
||
|
||
remainder can be manually entered or gathered through repetitive
|
||
|
||
retries.
|
||
|
||
Bear all this in mind learning the following cracks.
|
||
|
||
Let's now crack an "oldie" primitive:
|
||
|
||
MS Flight simulator (old version 2.12, from 1985!)
|
||
|
||
This old program used -in 1985!- following beautiful protection
|
||
|
||
scheme: on the disk you had only a "stub", called FS.COM with few
|
||
|
||
bytes, which had following instructions:
|
||
|
||
loc code instruction what's going on
|
||
|
||
-------------------------------------------------------
|
||
|
||
:0100 FA CLI ;why not?
|
||
|
||
:0101 33C0 XOR AX,AX ;ax=0
|
||
|
||
:0103 8ED0 MOV SS,AX ;ss=0
|
||
|
||
:0105 BCB0C0 MOV SP,C0B0 ;SP=C0B0
|
||
|
||
:0108 8EC0 MOV ES,AX ;ES=0
|
||
|
||
:010A 26C70678003001 MOV Wptr ES:[0078],0130 ;Wp 0:78=130
|
||
|
||
:0111 268C0E7A00 MOV ES:[007A],CS ;0:7A=Segment
|
||
|
||
:0116 BB0010 MOV BX,1000 ;BX=1000
|
||
|
||
:0119 8EC3 MOV ES,BX ;ES=1000
|
||
|
||
:011B 33DB XOR BX,BX ;BX=0
|
||
|
||
:011D B80102 MOV AX,0201 ;AH=2 AL=1 sector
|
||
|
||
:0120 BA0000 MOV DX,0000 ;head=0 drive=0
|
||
|
||
:0123 B96501 MOV CX,0165 ;track=1 sector=65 (!)
|
||
|
||
:0126 CD13 INT 13 ;INT 13/AH=2
|
||
|
||
:0128 B83412 MOV AX,1234 ;AX=1234
|
||
|
||
:012B EA00000010 JMP 1000:0000 ;JMP to data we just read
|
||
|
||
:0130 CF IRET ;Pavlovian, useless ret
|
||
|
||
You see what's happening in this old protection scheme,
|
||
|
||
don't you? Herein you can watch the same snap that happens in
|
||
|
||
more recent (much more recent) protection schemes (as you'll see
|
||
|
||
in the next lesson): the protection searches for a weird
|
||
|
||
formatted sector and/or for particular data.
|
||
|
||
That should be no problem for you any more: you should just
|
||
|
||
reverse engineer everything (and that goes on pretty quickly:
|
||
|
||
just watch and break on the INT_13 calls), fetch the "weird"
|
||
|
||
data, tamper the whole crap and have your soup as you like it.
|
||
|
||
One more word about "old" protection schemes. Be careful not
|
||
|
||
to spurn them! Some of them are
|
||
|
||
-- CLEVER
|
||
|
||
-- STILL USED
|
||
|
||
-- DIFFICULT TO CRACK... I mean, this older DOS programs had
|
||
|
||
nice protections... it's pretty annoying to crack windows
|
||
|
||
programs that require a registration number: as you saw in Lesson
|
||
|
||
3, you just type your name and a serial number of your choice in,
|
||
|
||
say "666666666", break into the program with WINICE, search the
|
||
|
||
"666666666" and search too, for good measure, your own name, set
|
||
|
||
a memory read breakpoint where the number dwells and look at the
|
||
|
||
code that manipulates your input. As [Chris] rightly pointed out,
|
||
|
||
you can even rip the code straight out of the program and create
|
||
|
||
a key generator which will produce a valid code. This code will
|
||
|
||
work for any name you typed in only in the "pure maths
|
||
|
||
manipulation" protection schemes, and will on the contrary be
|
||
|
||
specific, following the name you typed in, the "alpha-maths
|
||
|
||
manipulation" protection schemes (like MOD4WIN, see the Windows
|
||
|
||
lessons), watch in this case the "pseudo-random xoring" of the
|
||
|
||
letters that compose your name.
|
||
|
||
-- STUNNING, coz new ideas have always been infrequent, and
|
||
|
||
they are getting more and more rare in this objectionable world
|
||
|
||
of lazy, incapable programmers patronizing us with ill-cooked
|
||
|
||
outrages like Windows'95... yeah, as usual there is no
|
||
|
||
"development" at all, quite the contrary, I would say. Take a
|
||
|
||
step backward, sip a good Martini-Wodka (please remember that
|
||
|
||
only Ice cubes, Dry Martini, Wodka Moskovskaja, Schweppes'
|
||
|
||
"Indian tonic" a green olive from Tuskany and a maltese lemon
|
||
|
||
zest will really be perfect) and watch from your balcony, with
|
||
|
||
unsullied eyes, your town and the people around you: slaves
|
||
|
||
everywhere, leaving home at 7.30 in the morning, stinking in a
|
||
|
||
progression of identical cars, forced to interminably watch
|
||
|
||
advertisement panels and endlessly listen to boorish publicity,
|
||
|
||
happy to go to work (if they happen to have the "luck" to work,
|
||
|
||
in this inequitable society) the whole day long in order to
|
||
|
||
produce other cars in order to buy, one day, a new car with a
|
||
|
||
different colour...
|
||
|
||
Why people don't look at the stars, love each other, feel
|
||
|
||
the winds, ban the stinking cars from the places where they live
|
||
|
||
and eat, study colours... name yourself a not-consumistic
|
||
|
||
activity? Why don't they read any poems any more? No poetry any
|
||
|
||
more, in the grey society of the publicity-spots slaves...poetry
|
||
|
||
will soon be forbidden, coz you cannot CONSUME as you read poems,
|
||
|
||
and in this farce of a society you are BOUND to consume, that's
|
||
|
||
the only thing they want you to do... you are CULTIVATED to
|
||
|
||
consume... no books worth to read any more... stupid american
|
||
|
||
conventional cram everywhere... boy, at times I'm missing some
|
||
|
||
well placed neutron bombs, the ones that would kill all these
|
||
|
||
useless zombies and leave noble books and good Wodka untouched.
|
||
|
||
It's difficult to believe in democracy any more... if I ever
|
||
|
||
did... all the useless zombie do -unfortunately- vote, and they
|
||
|
||
do vote for "smiling semblances", for "conventionally minded
|
||
|
||
idiots" that so act as if they would "really" be like what they
|
||
|
||
"look" like and could not care less about anything else than
|
||
|
||
making bucks and defend intolerant and petty patterns. The slaves
|
||
|
||
choose the people they have "seen" on TV... as if the egyptians
|
||
|
||
would VOTE for their pharaohs, exhilarated under the whips of
|
||
|
||
publicity... sorry, at times I forget that you are here for the
|
||
|
||
cracks, and could not care less about what I think...
|
||
|
||
You 'll obtain the OTHER missing lessons IF AND ONLY IF you
|
||
|
||
mail me back (via anon.penet.fi) with some tricks of the trade
|
||
|
||
I may not know that YOU discovered. Mostly I'll actually know
|
||
|
||
them already, but if they are really new you'll be given full
|
||
|
||
credit, and even if they are not, should I judge that you
|
||
|
||
"rediscovered" them with your work, or that you actually did good
|
||
|
||
work on them, I'll send you the remaining lessons nevertheless.
|
||
|
||
Your suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 6.1: Funny tricks (1)
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
LESSON 6 (1) - Funny tricks. Xoring, Junking, Sliding
|
||
|
||
EXERCISE 01: [LARRY in search of the King]
|
||
|
||
Before the next step let's resume what you have learned in
|
||
|
||
the lessons 3-5, beginning with a very simple crack exercise
|
||
|
||
(again, we'll use the protection scheme of a game, for the
|
||
|
||
reasons explained in lesson 1): SEARCH FOR THE KING (Version
|
||
|
||
1.1.). This old "Larry" protection sequence, is a "paper
|
||
|
||
protection" primitive. It's a very widespread (and therefore easy
|
||
|
||
to find) program, and one of the first programs that instead of
|
||
|
||
asking meaningful passwords (which offer us the possibility to
|
||
|
||
immediately track them down in memory) asked for a random number
|
||
|
||
that the good buyer could find on the manual, whereby the bad
|
||
|
||
cracker could not. (Here you choose -with the mouse- one number
|
||
|
||
out of 5 possible for a "gadget" choosen at random). I don't need
|
||
|
||
any more to teach you how to find the relevant section of code
|
||
|
||
(-> see lesson 3). Once you find the protection, this is what you
|
||
|
||
get:
|
||
|
||
:protection_loop
|
||
|
||
:C922 8E0614A3 MOV ES,[A314]
|
||
|
||
...
|
||
|
||
:C952 50 0E PUSH AX & CS
|
||
|
||
:C954 E81BFF CALL C872 <- call protection scheme
|
||
|
||
:C957 5B POP BX twice
|
||
|
||
:C959 8B76FA MOV SI,[BP-06] <- prepare store_room
|
||
|
||
:C95C D1E6 SHL SI,1 <- final prepare
|
||
|
||
:C95E 8942FC MOV [BP+SI-04],AX <- store AX
|
||
|
||
:C961 837EFA00 CMP Word Ptr [BP-06],+00 <- good_guy?
|
||
|
||
:C965 75BB JNZ C922 <- loop, bad guy
|
||
|
||
:C967 8E0614A3 MOV ES,[A314]
|
||
|
||
:C96B 26F606BE3501 TEST Byte Ptr ES:[35BE],01 <- bad_guy?
|
||
|
||
:C971 74AF JZ C922 <- loop, bad guy
|
||
|
||
:C973 8B46FC MOV AX,[BP-04]... <- go on good guy
|
||
|
||
Let's see now the protection scheme called from :C954
|
||
|
||
:C872 55 PUSH BP
|
||
|
||
...
|
||
|
||
:C8F7 90 NOP
|
||
|
||
:C8F8 0E PUSH CS
|
||
|
||
:C8F9 E87234 CALL FD6E <- call user input
|
||
|
||
:C8FC 5B POP BX
|
||
|
||
:C8FD 5B POP BX
|
||
|
||
:C8FE 8B5E06 MOV BX,[BP+06]
|
||
|
||
:C901 D1E3 SHL BX,1
|
||
|
||
:C903 39872266 CMP [BX+6622],AX <- right answer?
|
||
|
||
:C907 7505 JNZ C90E <- no, beggar_off
|
||
|
||
:C909 B80100 MOV AX,0001 <- yes, AX=1
|
||
|
||
:C90C EB02 JMP C910
|
||
|
||
:C90E 2BC0 SUB AX,AX <- beggar_off with AX=0
|
||
|
||
:C910 8BE5 MOV SP,BP
|
||
|
||
:C912 5D POP BP
|
||
|
||
:C913 CB RETF <- back to main
|
||
|
||
Here follow 5 questions, please answer all of them:
|
||
|
||
1) Where in memory (in which locations) are stored the "right"
|
||
|
||
passnumbers? Where in memory is the SEGMENT of this
|
||
|
||
locations stored? How does the scheme get the OFFSET?
|
||
|
||
2) Would setting NOPs instructions at :C965 and :C971 crack?
|
||
|
||
Would it be a good idea?
|
||
|
||
3) Would changing :C907 to JZ crack? Would it be a good idea?
|
||
|
||
4) Would changing :C907 to JNZ C909 crack? Would it be a good
|
||
|
||
idea?
|
||
|
||
5) Write down (and try) at least 7 OTHER different patches to
|
||
|
||
crack this scheme in spades (without using any NOP!).
|
||
|
||
Uff! By now you should be able to do the above 5 exercises in
|
||
|
||
less than 15 minutes WITHOUT USING THE DEBUGGER! Just look at the
|
||
|
||
data above and find the right answers feeling them... (you 'll
|
||
|
||
now which one are the right one checking with your debugger...
|
||
|
||
score as many points as you like for each correct answer and sip
|
||
|
||
a good Martini-Wodka... do you know that the sequence should
|
||
|
||
ALWAYS be 1) Ice cubes 2) Martini Dry 3) Wodka Moskovskaja 4)
|
||
|
||
olive 5) lemon 6) Schweppes Indian tonic?
|
||
|
||
Let's now come to the subject of this lesson:
|
||
|
||
-----> [Xoring] (Simple encryption methods)
|
||
|
||
One easy way to encrypt data is the XOR method. XOR is a bit
|
||
|
||
manipulation instruction that can be used in order to cipher and
|
||
|
||
decipher data with the same key:
|
||
|
||
Byte to encrypt key result
|
||
|
||
FF XOR A1 5E
|
||
|
||
5E XOR A1 FF
|
||
|
||
As you can see XOR offers a very easy way to encrypt or to
|
||
|
||
decrypt data, for instance using the following routine:
|
||
|
||
encrypt_decrypt:
|
||
|
||
mov bx, offset_where_encryption/decryption_starts
|
||
|
||
xor_loop:
|
||
|
||
mov ah, [bx] <- get current byte
|
||
|
||
xor ah, encrypt_value <- engage/disengage xor
|
||
|
||
mov [bx], ah <- back where you got it
|
||
|
||
inc bx <- ahead one byte
|
||
|
||
cmp bx, offset_start_+_size <- are we done?
|
||
|
||
jle xor_loop <- no, then next cycle
|
||
|
||
ret <- back where we came from
|
||
|
||
The encrypt_value can be always the same (fixed) or chosen at
|
||
|
||
random, for instance using INT_21, service 2Ch (get current time)
|
||
|
||
and choosing as encrypt_value the value reported in DL (but
|
||
|
||
remembering to discard the eventual value 0, coz otherwise it
|
||
|
||
would not xor anything at all!)
|
||
|
||
random_value:
|
||
|
||
mov ah,2Ch
|
||
|
||
int 21h
|
||
|
||
cmp dl,0
|
||
|
||
je random_value
|
||
|
||
mov encrypt_value,dl
|
||
|
||
The problem with XORing (and with many other encryption
|
||
|
||
methods), is that the part of the code that calls the encryption
|
||
|
||
routine cannot be itself encrypted. You'll somewhere have, "in
|
||
|
||
clear" the encryption key.
|
||
|
||
The protectionist do at times their best to hide the
|
||
|
||
decrypting routine, here are some common methods:
|
||
|
||
-----> JUNK FILLING, SLIDING KEYS AND MUTATING DECRYPTORS
|
||
|
||
These are the more common protection method for the small
|
||
|
||
decryption part of the program code. This methods, originally
|
||
|
||
devised to fool signature virus scanners, have been pinched from
|
||
|
||
the polymorphic virus engines of our fellows viriwriters, and are
|
||
|
||
still in use for many simple decryption protection schemes. For
|
||
|
||
parts of the following many thanks go to the [Black Baron], it's
|
||
|
||
a real pity that so many potential good crackers dedicate so much
|
||
|
||
time to useless (and pretty repetitive) virus writing instead of
|
||
|
||
helping in our work. This said, virus studying is VERY important
|
||
|
||
for crackers coz the code of the viri is
|
||
|
||
* ULTRAPROTECTED
|
||
|
||
* TIGHT AND EFFECTIVE
|
||
|
||
* CLOAKED AND CONCEALED.
|
||
|
||
Let's show as example of the abovementioned protection tactics
|
||
|
||
the following ultra-simple decryptor:
|
||
|
||
MOV SI,jumbled_data ;Point to the jumbled data
|
||
|
||
MOV CX,10 ;Ten bytes to decrypt
|
||
|
||
mn_loop: XOR BYTE PTR [SI],44 ;XOR (un_scramble!) a byte
|
||
|
||
INC SI ;Next byte
|
||
|
||
LOOP mn_loop ;Loop the 9 other bytes
|
||
|
||
This small program will XOR the ten bytes at the location pointed
|
||
|
||
to by SI with the value 44. Providing the ten bytes were XORed
|
||
|
||
with 44 prior to running this decryptor the ten bytes will be
|
||
|
||
restored to their original state.
|
||
|
||
In this very simple case the "key" is the value 44. But there are
|
||
|
||
several tricks involving keys, the simplest one being the use of
|
||
|
||
a "sliding" key: a key that will be increased, or decreased, or
|
||
|
||
multiplied, or bit-shifted, or whatever, at every pass of the
|
||
|
||
loop.
|
||
|
||
A possible protection can also create a true "Polymorph"
|
||
|
||
decryptor, a whole decryptor ROUTINE that looks completely
|
||
|
||
different on each generation. The trick is to pepper totally
|
||
|
||
random amounts of totally random instructions, including JUMPS
|
||
|
||
and CALLS, that DO NOT AFFECT the registers that are used for the
|
||
|
||
decryption. Also this kind of protection oft uses a different
|
||
|
||
main decryptor (possibly from a selection of pre-coded ones) and
|
||
|
||
oft alters on each generation also all the registers that the
|
||
|
||
decryptor uses, invariably making sure that the JUNK code that
|
||
|
||
it generates doesn't destroy any of the registers used by the
|
||
|
||
real decryptor! So, with these rules in mind, here is our simple
|
||
|
||
decryptor again:
|
||
|
||
MOV DX,10 ;Real part of the decryptor!
|
||
|
||
MOV SI,1234 ;junk
|
||
|
||
AND AX,[SI+1234] ;junk
|
||
|
||
CLD ;junk
|
||
|
||
MOV DI,jumbled_data ;Real part of the decryptor!
|
||
|
||
TEST [SI+1234],BL ;junk
|
||
|
||
OR AL,CL ;junk
|
||
|
||
mn_loop: ADD SI,SI ;junk instr, but real loop!
|
||
|
||
XOR AX,1234 ;junk
|
||
|
||
XOR BYTE PTR [DI],44 ;Real part of the decryptor!
|
||
|
||
SUB SI,123 ;junk
|
||
|
||
INC DI ;Real part of the decryptor!
|
||
|
||
TEST DX,1234 ;junk
|
||
|
||
AND AL,[BP+1234] ;junk
|
||
|
||
DEC DX ;Real part of the decryptor!
|
||
|
||
NOP ;junk
|
||
|
||
XOR AX,DX ;junk
|
||
|
||
SBB AX,[SI+1234] ;junk
|
||
|
||
AND DX,DX ;Real part of the decryptor!
|
||
|
||
JNZ mn_loop ;Real part of the decryptor!
|
||
|
||
As you should be able to see, quite a mess! But still executable
|
||
|
||
code. It is essential that any junk code generated by the
|
||
|
||
Polymorph protection is executable, as it is going to be peppered
|
||
|
||
throughout the decryptor. Note, in this example, that some of the
|
||
|
||
junk instructions use registers that are actually used in the
|
||
|
||
decryptor! This is fine, providing the values in these
|
||
|
||
registers aren't destroyed. Also note, that now we have random
|
||
|
||
registers and random instructions on each generation. So, a
|
||
|
||
Polymorph protection Engine can be summed up into three major
|
||
|
||
parts:
|
||
|
||
1 .. The random number generator.
|
||
|
||
2 .. The junk code generator.
|
||
|
||
3 .. The decryptor generator.
|
||
|
||
There are other discrete parts but these three are the ones where
|
||
|
||
most of the work goes on!
|
||
|
||
How does it all work? Well a good protection would
|
||
|
||
* choose a random selection of registers to use for the
|
||
|
||
decryptor and leave the remaining registers as "junk" registers
|
||
|
||
for the junk code generator.
|
||
|
||
* choose one of the compressed pre-coded decryptors.
|
||
|
||
* go into a loop generating the real decryptor, peppered with
|
||
|
||
junk code.
|
||
|
||
From the protectionist's point of view, the advantages of this
|
||
|
||
kind of method are mainly:
|
||
|
||
* the casual cracker will have to sweat to find the decryptor.
|
||
|
||
* the casual cracker will not be able to prepare a "patch" for
|
||
|
||
the lamers, unless he locates and patches the generators, (that
|
||
|
||
may be compressed) coz otherwise the decryptor will vary every
|
||
|
||
time.
|
||
|
||
To defeat this kind of protection you need a little "zen" feeling
|
||
|
||
and a moderate knowledge of assembler language... some of the
|
||
|
||
junk instructions "feel" quite singular when you look at them
|
||
|
||
(->see lesson B). Besides, you (now) know what may be going on
|
||
|
||
and memory breakpoints will immediately trigger on decryption...
|
||
|
||
the road is open and the rest is easy (->see lessons 3-5).
|
||
|
||
-----> Starting point number magic
|
||
|
||
For example, say the encrypted code started at address 10h, the
|
||
|
||
following could be used to index this address:
|
||
|
||
MOV SI,10h ;Start address
|
||
|
||
MOV AL,[SI] ;Index from initial address
|
||
|
||
But sometimes you'll instead find something like the following,
|
||
|
||
again based on the encrypted code starting at address 10h:
|
||
|
||
MOV DI,0BFAAh ;Indirect start address
|
||
|
||
MOV AL,[DI+4066h) ;4066h + 0BFAAh = 10010h (and FFFF = 10h)!!
|
||
|
||
The possible combinations are obviously infinite.
|
||
|
||
[BIG KEYS] (Complicated encryption methods)
|
||
|
||
Prime number factoring is the encryption used to protect
|
||
|
||
sensible data and very expensive applications. Obviously for few
|
||
|
||
digit keys the decoding is much easier than for, say, 129 or 250
|
||
|
||
digit keys. Nevertheless you can crack those huge encryption too,
|
||
|
||
using distributed processing of quadratic sieve equations (which
|
||
|
||
is far superior for cracking purpose to the sequential processing
|
||
|
||
methods) in order to break the key into prime numbers. To teach
|
||
|
||
you how to do this sort of "high" cracking is a little outside
|
||
|
||
the scope of my tutorial: you'll have to write a specific short
|
||
|
||
dedicated program, linking together more or less half a thousand
|
||
|
||
PC for a couple of hours, for a 250 bit key, this kind of things
|
||
|
||
have been done quite often on Internet, were you can also find
|
||
|
||
many sites that do untangle the mysteries (and vagaries) of such
|
||
|
||
techniques.
|
||
|
||
As References I would advocate the works of Lai Xueejia, those
|
||
|
||
swiss guys can crack *everything*. Begin with the following:
|
||
|
||
Xuejia Lai, James Massey, Sean Murphy, "Markov Ciphers and
|
||
|
||
Differential Cryptanalysis", Advances in Cryptology,
|
||
|
||
Eurocrypt 1991.
|
||
|
||
Xuejia Lai, "On the Design and Security of Block Ciphers",
|
||
|
||
Institute for Signal and Information Processing,
|
||
|
||
ETH-Zentrum, Zurich, Switzerland, 1992
|
||
|
||
Factoring and primality testing is obviously very important for
|
||
|
||
this kind of crack. The most comprehensive work I know of is:
|
||
|
||
(300 pages with lengthy bibliography!)
|
||
|
||
W. Bosma & M. van der Hulst
|
||
|
||
Primality Testing with Cyclotomy
|
||
|
||
Thesis, University of Amsterdam Press.
|
||
|
||
A very good old book you can incorporate in your probes to build
|
||
|
||
very effective crack programs (not only for BBS accesses :=) is
|
||
|
||
*the* "pomerance" catalog:
|
||
|
||
Pomerance, Selfridge, & Wagstaff Jr.
|
||
|
||
The pseudoprimes to 25*10^9
|
||
|
||
Math. Comp. Vol 35 1980 pp. 1003-1026
|
||
|
||
Anyway... make a good search with Lykos, and visit the relevant
|
||
|
||
sites... if encryption really interests you, you'll be back in
|
||
|
||
two or three (or thirty) years and you'll resume cracking with
|
||
|
||
deeper erudite knowledge.
|
||
|
||
[PATENTED PROTECTION SYSTEMS]
|
||
|
||
The study of the patented enciphering methods is also *quite*
|
||
|
||
interesting for our aims :=) Here are some interesting patents,
|
||
|
||
if you want to walk these paths get the complete texts:
|
||
|
||
[BEST] USPat 4168396 to Best discloses a microprocessor
|
||
|
||
for executing enciphered programs. Computer programs which have
|
||
|
||
been enciphered during manufacture to deter the execution of the
|
||
|
||
programs in unauthorized computers, must be decrypted before
|
||
|
||
execution. The disclosed microprocessor deciphers and executes
|
||
|
||
an enciphered program one instruction at a time, instead of on
|
||
|
||
a continuous basis, through a combination of substitutions,
|
||
|
||
transpositions, and exclusive OR additions, in which the address
|
||
|
||
of each instruction is combined with the instruction. Each unit
|
||
|
||
may use a unique set of substitutions so that a program which can
|
||
|
||
be executed on one microprocessor cannot be run on any other
|
||
|
||
microprocessor. Further, Best cannot accommodate a mixture of
|
||
|
||
encrypted and plain text programs.
|
||
|
||
[JOHNSTONE] USPat 4120030 to Johnstone describes a
|
||
|
||
computer in which the data portion of instructions are scrambled
|
||
|
||
and in which the data is of necessity stored in a separate
|
||
|
||
memory. There is no disclosure of operating with instructions
|
||
|
||
which are completely encrypted with both the operation code and
|
||
|
||
the data address portion being unreadable without a corresponding
|
||
|
||
key kernel.
|
||
|
||
[TWINPROGS] USPat 4183085 describes a technique for
|
||
|
||
protecting software by providing two separate program storages.
|
||
|
||
The first program storage is a secure storage and the second
|
||
|
||
program storage is a free storage. Security logic is provided to
|
||
|
||
check whether an output instruction has originated in the secure
|
||
|
||
store and to prevent operation of an output unit which receives
|
||
|
||
output instructions from the free storage. This makes it
|
||
|
||
difficult to produce information by loading a program into free
|
||
|
||
storage.
|
||
|
||
[AUTHENTICATOR] USPat 3996449 entitled "Operating System
|
||
|
||
Authenticator," discloses a technique for authenticating the
|
||
|
||
validity of a plain text program read into a computer, by
|
||
|
||
exclusive OR'ing the plain text of the program with a key to
|
||
|
||
generate a code word which must be a standard recognizable code
|
||
|
||
word which is successfully compared with a standard corresponding
|
||
|
||
code word stored in the computer. If there is a successful
|
||
|
||
compare, then the plain text program is considered to be
|
||
|
||
authenticated and is allowed to run, otherwise the program
|
||
|
||
is not allowed to run.
|
||
|
||
ELEMENTS OF [PGP] CRACKING
|
||
|
||
In order to try to crack PGP, you need to understand how these
|
||
|
||
public/private keys systems work. Cracking PGP seems extremely
|
||
|
||
difficult, though... I have a special dedicated "attack" computer
|
||
|
||
that runs 24 hours on 24 only to this aim and yet have only begun
|
||
|
||
to see the light at the famous other end of the tunnel. It's
|
||
|
||
hard, but good crackers never resign! We'll see... I publish here
|
||
|
||
the following only in the hope that somebody else will one day
|
||
|
||
be able to help...
|
||
|
||
In the public key cryptosystems, like PGP, each user has an
|
||
|
||
associated encryption key E=(e,n) and decryption key D=(d,n),
|
||
|
||
wherein the encryption keys for all users are available in a
|
||
|
||
public file, while the decryption keys for the users are only
|
||
|
||
known to the respective users. In order to maintain a high level
|
||
|
||
of security a user's decoding key is not determinable in a
|
||
|
||
practical manner from that user's encoding (public) key. Normally
|
||
|
||
in such systems, since
|
||
|
||
e.multidot.d.ident.1 (mod(1 cm((p-1),(q-1)))),
|
||
|
||
(where "1 cm((p-1),(q-1))" is the least common multiple of the
|
||
|
||
numbers p-1 and q-1)
|
||
|
||
d can be determined from e provided p and q are also known.
|
||
|
||
Accordingly, the security of the system is dependent upon the
|
||
|
||
ability to determine p and q which are the prime factors of n.
|
||
|
||
By selecting p and q to be large primes, the resultant composite
|
||
|
||
number n is also large, and correspondingly difficult to factor.
|
||
|
||
For example, using known computer-implemented factorization
|
||
|
||
methods, on the order of 10.sup.9 years is required to factor a
|
||
|
||
200 digit long number. Thus, as a practical matter, although a
|
||
|
||
user's encryption key E=(e,n) is public, the prime factors p and
|
||
|
||
q of n are effectively hidden from anyone due to the enormous
|
||
|
||
difficulty in factoring n. These aspects are described more fully
|
||
|
||
in the abundant publications on digital signatures and Public-Key
|
||
|
||
Cryptosystems. Most public/private systems relies on a message-
|
||
|
||
digest algorithm.
|
||
|
||
A message-digest algorithm maps a message of arbitrary length
|
||
|
||
to a "digest" of fixed length, and has three properties:
|
||
|
||
Computing the digest is easy, finding a message with a given
|
||
|
||
digest "inversion" is hard, and finding two messages with the
|
||
|
||
same digest "collision" is also hard. Message-digest algorithms
|
||
|
||
have many applications, not only digital signatures and message
|
||
|
||
authentication. RSA Data Security's MD5 message-digest algorithm,
|
||
|
||
developed by Ron Rivest, maps a message to a 128-bit message
|
||
|
||
digest. Computing the digest of a one-megabyte message takes as
|
||
|
||
little as a second. While no message-digest algorithm can yet
|
||
|
||
be secure, MD5 is believed to be at least as good as any other
|
||
|
||
that maps to a 128-bit digest.
|
||
|
||
As a final gift, I'll tell you that PGP relies on MD5 for a
|
||
|
||
secure one-way hash function. For PGP this is troublesome, to say
|
||
|
||
the least, coz an approximate relation exists between any four
|
||
|
||
consecutive additive constants. This means that one of the design
|
||
|
||
principles behind MD4 (and MD5), namely to design a collision
|
||
|
||
resistant function, is not satisfied. You can construct two
|
||
|
||
chaining variables (that only differ in the most significant bit
|
||
|
||
of every word) and a single message block that yield the same
|
||
|
||
hashcode. The attack takes a few minutes on a PC. From here you
|
||
|
||
should start, as I did.
|
||
|
||
[DOS 4GW] cracking - This is only a very provisory part of this
|
||
|
||
tutorial. DOS 4GW cracking will be much better described as soon
|
||
|
||
as [Lost soul] sends his stuff, if he ever does. For (parts of)
|
||
|
||
the following I thank [The Interrupt].
|
||
|
||
Most applications of every OS, and also of DOS 4GW, are
|
||
|
||
written in C language, coz as you'll have already learned or,
|
||
|
||
either, you'll learn, only C allows you to get the "guts" of a
|
||
|
||
program, almost approaching the effectiveness of assembler
|
||
|
||
language.
|
||
|
||
C is therefore the LANGUAGE OF CHOICE for crackers, when you
|
||
|
||
prepare your tools and do not directly use assembler routines.
|
||
|
||
Besides... you'll be able to find VERY GOOD books about C for
|
||
|
||
next to nothing in the second hand bookshops. All the lusers are
|
||
|
||
throwing money away in spades buying huge, coloured and
|
||
|
||
absolutely useless books on unproductive "bloated" languages like
|
||
|
||
Visual basic, C++ and Delphy. Good C new books are now rare
|
||
|
||
(books on assembler language have always been) and can be found
|
||
|
||
almost exclusively on the second hand market. Find them, buy
|
||
|
||
them, read them, use them for your/our aims. You can find a lot
|
||
|
||
of C tutorials and of C material on the Web, by all means DO IT!
|
||
|
||
Be a conscientious cracker... learn C! It's cheap, lean, mean and
|
||
|
||
very productive (and creative) :=)
|
||
|
||
Back to the point: most stuff is written in C and therefore
|
||
|
||
you need to find the "main" sub-routine inside the asm. With
|
||
|
||
DOS/4GW programs, search the exe file for "90 90 90 90", almost
|
||
|
||
always it'll be at the start of the compiled code. Now search for
|
||
|
||
an INT_21 executed with 4C in AH, the exec to dos code (if you
|
||
|
||
cannot "BPINT 21 AH=4C" with your tool, then search for the
|
||
|
||
sequence "b4 4c cd 21". This is the equivalent to [mov AH,4C &
|
||
|
||
int 21]: it's the most direct call, but as you'll have already
|
||
|
||
learned, there are half a dozen ways to put 4C in AX, try them
|
||
|
||
all in the order of their frequency).
|
||
|
||
A few bytes above the INT_21 service 4C, you'll find the
|
||
|
||
call to the "main" subroutine: "E8 xx xx". Now place a "CC" byte
|
||
|
||
a few bytes above the call in the exe and run the exe under a
|
||
|
||
debugger. When the computer tries to execute the instruction
|
||
|
||
you'll be throw back in the debugger coz the "CC" byte acts as
|
||
|
||
INT_01 instruction. Then proceed as usual.
|
||
|
||
[THE "STEGONATED" PASSWORD HIDEOUT]
|
||
|
||
A last, very nice trick should be explained to every wannabe
|
||
|
||
cracker, coz it would be embarrassing to search for passwords or
|
||
|
||
protection routines that (apparently) are not there. They may be
|
||
|
||
hidden INSIDE a picture (or a *.waw file for that matter). This
|
||
|
||
is steganography, a method of disguising messages within other
|
||
|
||
media.
|
||
|
||
Depending on how many shades of grey or hues of colour you want
|
||
|
||
to have, a pixel can be expressed using 8. 16, 32 or even more
|
||
|
||
bits. If the least significant bit is changed. the shade of the
|
||
|
||
pixel is altered only one-256th, one-65,OOOth or even less. No
|
||
|
||
human eye could tell the difference.
|
||
|
||
What the protectionist does, is hijack the least significant
|
||
|
||
bit in each pixel of a picture. It uses that bit to store one bit
|
||
|
||
of a protection, or of a password (or of a file, or of a secret
|
||
|
||
message). Because digitized pictures have lots of pixels, it's
|
||
|
||
possible to store lots of data in a single picture. A simple
|
||
|
||
algorithm will transfer them to the relevant parts of the program
|
||
|
||
when it needs be, and there we'll intercept them. You'll need to
|
||
|
||
learn very well the zen-cracking techniques to smell this kind
|
||
|
||
of stuff though (-> see lesson B).
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the OTHER missing lessons IF AND ONLY IF you
|
||
|
||
mail me back (via anon.penet.fi) with some tricks of the trade
|
||
|
||
I may not know that YOU discovered. Mostly I'll actually know
|
||
|
||
them already, but if they are really new you'll be given full
|
||
|
||
credit, and even if they are not, should I judge that you
|
||
|
||
"rediscovered" them with your work, or that you actually did good
|
||
|
||
work on them, I'll send you the remaining lessons nevertheless.
|
||
|
||
Your suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
an526164@anon.penet.fi (+ORC)
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 8.1: How to crack Windows, an approach
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[WINPGP.EXE]
|
||
|
||
--------------------------------------
|
||
|
||
--------------------------------------------------------
|
||
|
||
SPECIAL NOTE: Please excuse the somehow "unshaven"
|
||
|
||
character of the windows lessons... I'm cracking the
|
||
|
||
newest Windows '95 applications right now, therefore
|
||
|
||
at times I had to add "on the fly" some corrections to
|
||
|
||
the older Windows 3.1 and Windows NT findings.
|
||
|
||
"homines, dum docent, discunt".
|
||
|
||
---------------------------------------------------------
|
||
|
||
-> 1st THING TO REMEMBER
|
||
|
||
The NE format does give every windows executable the equivalent
|
||
|
||
of a debug symbol table: A CRACKER BLISS!
|
||
|
||
-> UNDOCUMENTED DEBUGGING
|
||
|
||
One of the many feature of Windows based on undocumented
|
||
|
||
foundations is the "ability to debug".
|
||
|
||
A word about undocumented functions in the MS-Operating Systems:
|
||
|
||
Microsoft manipulates its rule and domination of the operating
|
||
|
||
systems in use to day (MS-DOS, Windows, Windows '95) with two
|
||
|
||
main wicked aims:
|
||
|
||
1) getting the concurrence completely bankrupt (that's the
|
||
|
||
scope of all the using of undocumented functions and
|
||
|
||
CHANGING them as soon as the concurrence uses them). The
|
||
|
||
battle against Borland was fought in this way.
|
||
|
||
2) getting all future "programmers" to use windows as a "black
|
||
|
||
box" that only Microsoft engineers (if ever) can master, so
|
||
|
||
that everybody will have to sip the ill-cooked abominations
|
||
|
||
from Microsoft without ever having a chance to alter or
|
||
|
||
ameliorate them.
|
||
|
||
Strange as it may seem, only the sublime cracker community fights
|
||
|
||
against these intolerable plans. All stupid governments and
|
||
|
||
lobbies -on the contrary- hide behind the fig-leaf of the
|
||
|
||
"market" "freedom" in order to ALLOW such heinous developments
|
||
|
||
(I'm speaking as if they were capable to opposing them even if
|
||
|
||
they wanted, which they do not. Be assured, they couldn't anyway,
|
||
|
||
"Governments" are deliberately MADE to serve Gates and all the
|
||
|
||
remaining suckers, and lobbies are the shield of feudalism. You
|
||
|
||
can forget "democracy", the only rule existing is a malevolent
|
||
|
||
oligarchy based on money, personal connections, defect of
|
||
|
||
culture, lack of knowledge and dictatorship of bad taste through
|
||
|
||
television in order to keep the slaves tamed... enough now...)
|
||
|
||
The windows situation is particularly reminiscent of the older
|
||
|
||
situation in DOS, where for years the key "load but don't
|
||
|
||
execute" function, used by debuggers, such as [DEBUG], [SYMDEB]
|
||
|
||
and [CODEVIEW], was "reserved" by Microsoft.
|
||
|
||
The windows debugging library, WINDEBUG.DLL, a number of
|
||
|
||
undocumented functions and even the interface it provides are
|
||
|
||
undocumented! The WinDebug() function is used by all available
|
||
|
||
windows debuggers, including [CVW] (CodeView for Windows), [TDW]
|
||
|
||
(TurboDebugger for Windows), [Multiscope] and [Quick C for
|
||
|
||
Windows] (the last two are GUI, not text debuggers. The use of
|
||
|
||
WinDebug() doesn't show up in MAPWIN output 'coz debuggers link
|
||
|
||
to it at run-time via the amazing GetProcAddress() function.
|
||
|
||
WinDebug() is a hacked 32-bit version, for the old Windows
|
||
|
||
3.0, of the poorly documented DOSPTrace() function from OS/2 1.x
|
||
|
||
(study these older Operating Systems! Studying the past you'll
|
||
|
||
understand EVERYTHING! Sometime I think that the only way to hack
|
||
|
||
and crack correctly is to be more a software historian than a
|
||
|
||
programmer... fac sapias et liber eris!). DOSPTrace is, in turn,
|
||
|
||
based on the ptrace() function in Unix.
|
||
|
||
Like DosPTrace(), WinDebug() takes commands such as Go,
|
||
|
||
Single-Step, Write&Read Registers, Write&Read Memory. It returns
|
||
|
||
to its caller either when the command completes or when a
|
||
|
||
breakpoint occurs (or a DLL load). These commands and
|
||
|
||
notifications appear in a large structure whose address is passed
|
||
|
||
in WinDebug().
|
||
|
||
WinDebug() was renamed CVWIN.DLL (and TDWIN.DLL) for Windows
|
||
|
||
3.1., all crackers should study it and get the maximum possible
|
||
|
||
documentation about it. As you will see in the following, it is
|
||
|
||
worth to study also TOOLHELP.DLL (what Microsoft would like you
|
||
|
||
to fiddle with) and INT_41h (the real debugging interface).
|
||
|
||
Interrupt handling under Windows
|
||
|
||
Interrupt handling under Windows can be tricky: you need to
|
||
|
||
use Toolhelp (a rather scaring lobotomy for your programs) or to
|
||
|
||
have special code for Standard vs. Enhanced modes, because the
|
||
|
||
information on the stack of an interrupt or exception handler
|
||
|
||
differs between the two windows modes. In addition, some handlers
|
||
|
||
would be installed using INT_21h, while others are set up using
|
||
|
||
DPMI services. Toolhelp has quite a bit of internal code that
|
||
|
||
"cooks" the interrupts and sends them to you in an easily
|
||
|
||
digestible form.
|
||
|
||
Remember that Windows uses GP faults as a "hacker" method
|
||
|
||
of doing ring transitions that are not allowed with legal 80x86
|
||
|
||
instructions: the virtual memory system of Enhanced mode is
|
||
|
||
implemented via the page fault.
|
||
|
||
Some tools for cracking windows (-> see lesson 9)
|
||
|
||
----------------- DEBUGGERS
|
||
|
||
CVW and TDW (you have to know the function's
|
||
|
||
segment:offset address beforehand in order
|
||
|
||
to crack a function)
|
||
|
||
WCB [Windows Codeback] by Leslie Pusztai (it's
|
||
|
||
a really cool tool!)
|
||
|
||
WDEB386 Microsoft's WDEB386 (clumsy, and requires a
|
||
|
||
second monitor)
|
||
|
||
Soft-Ice/Windows best (BY FAR!) windows debugger! NuMega is
|
||
|
||
so good I am at times really sorry to crack
|
||
|
||
their products! [WINICE] is the single,
|
||
|
||
absolutely essential debugger and snooping
|
||
|
||
utility for windows crackers. Get it!
|
||
|
||
----------------- POST MORTEM INSPECTORS
|
||
|
||
CORONER, etc. (a lot of shareware)
|
||
|
||
MS-DrWatson Old and clumsy
|
||
|
||
Borland's Winspector THE BEST! It has the BUILDSYM utility
|
||
|
||
that allows the creation of a debug
|
||
|
||
.SYM file from an .EXE without debug
|
||
|
||
information.
|
||
|
||
----------------- INSPECTORS
|
||
|
||
MS-Spy Old
|
||
|
||
Borland's WinSight (Best one, select "Other")
|
||
|
||
MicroQuill's Windows DeMystifiers (from Jeff Richter):
|
||
|
||
VOYEUR (hold SHIFT picking Message Selection), COLONEL,
|
||
|
||
MECHANIC and ECOLOGIST
|
||
|
||
----------------- SNOOPERS
|
||
|
||
[INFSPY.EXE], 231.424 bytes, version 2.05 28/8/1994 by Dean
|
||
|
||
Software Design, may be the more complete one.
|
||
|
||
[SUPERSPY.EXE], 24.576 bytes, 10,6,1994, quite handy for quick
|
||
|
||
informations.
|
||
|
||
[WINVIEW.EXE], 30.832 bytes, Version 3.00 by Scott McCraw, MS(c)
|
||
|
||
1990-1992, this is the old MS-Spy, distributed by MS
|
||
|
||
[TPWSPY.EXE], 9.472 bytes, quite primitive, but you get the
|
||
|
||
pascal source code with it.
|
||
|
||
-> INSIDE A WINDOWS '95 DEBUGGER
|
||
|
||
You can debug a program at the assembly-language level
|
||
|
||
without any debugging information. The DOS [DEBUG] program does
|
||
|
||
that, allowing breakpoints and single-stepping, all of which
|
||
|
||
implies that the hardware must be cooperating. Back in the time
|
||
|
||
of the 4-MHz Z-80s, you used a debugger that plugged interrupt
|
||
|
||
op codes into the instruction stream to generate breakpoints.
|
||
|
||
Nothing has changed. That's how you debug a program on a
|
||
|
||
80586 (=Pentium). The x86 architecture includes software
|
||
|
||
interrupts. The 1-byte op code xCC is the INT_03 instruction,
|
||
|
||
reserved for debuggers. You can put the INT_03 op code in place
|
||
|
||
of the program instruction op code where the break is to occur
|
||
|
||
and replace the original op code at the time of the interrupt.
|
||
|
||
In the 80386 and later, you can set a register flag that tells
|
||
|
||
the processor to generate a not-intrusive INT_01 instruction for
|
||
|
||
every machine instruction executed. That device supports single
|
||
|
||
stepping.
|
||
|
||
The Win32SDK (Windows '95 software developer's kit) includes
|
||
|
||
functions that allow one program to launch another program and
|
||
|
||
debug it. The SDK's debug API takes care of how the interrupts
|
||
|
||
and interrupt vectors get managed. The logical consequence of
|
||
|
||
such an approach is that fewer and fewer people will be able to
|
||
|
||
know what's going on inside an application. The bulk of the
|
||
|
||
programmers -in few years time- will not be able any more to
|
||
|
||
reverse engineer an application, unless the few that will still
|
||
|
||
understand assembler-language do offer them the tools to do it.
|
||
|
||
Microsoft -it is evident- would like the programmers to use a
|
||
|
||
"black box" approach to programming, writing nice little "hallo
|
||
|
||
world" application and leaving to the engineers in Microsoft
|
||
|
||
alone the capacity to push forward (and sell) real programs that
|
||
|
||
are not toy application.
|
||
|
||
The Win32 documentation seems vast, almost luxurious, until
|
||
|
||
you begin serious work and you discover its shortcomings, like
|
||
|
||
the fact that extended error codes are not documented, and
|
||
|
||
numerous APIs are documented either incorrectly or so poorly that
|
||
|
||
you must burn precious time testing them. What we definitely need
|
||
|
||
is to find some secret fellows inside Microsoft (like good old
|
||
|
||
Prometeus) that smuggles to the outside the real documentation
|
||
|
||
that the Microsoft engineers have reserved for themselves. If you
|
||
|
||
are reading this and do work for Microsoft, consider the
|
||
|
||
possibility of double-crossing your masters for the sake of
|
||
|
||
humanity and smuggle us the secret information.
|
||
|
||
In windows '95 a debugger program launches a program to be
|
||
|
||
debugged by calling the _CreateProcess function, specifying in
|
||
|
||
an argument that the program is to be debugged. Then the debugger
|
||
|
||
program enters a loop to run the program. At the top of the loop
|
||
|
||
the debugger calls _WaitForDebugEvent.
|
||
|
||
Each time _WaitForDebugEvent returns it sets indicators that
|
||
|
||
tell about the vent that suspended the program being debugged.
|
||
|
||
This is where the debugger traps breakpoints and single-step
|
||
|
||
exceptions. _WaitForDebugEvent fills in an event structure that
|
||
|
||
contains among other things the address that was interrupted end
|
||
|
||
the event that caused the interrupt.
|
||
|
||
The debugger calls _GetThreadContext to get the running
|
||
|
||
context of the debugged program, including the contents of the
|
||
|
||
registers. The debugger can, as the result of cracker
|
||
|
||
interaction, modify these values and the contents of the debugged
|
||
|
||
program's memory.
|
||
|
||
The debugger sets breakpoints by saving the op code at the
|
||
|
||
instruction to be intercepted and putting the INT_03 op code at
|
||
|
||
its place, it's always the same old marmalade. When the
|
||
|
||
breakpoint occurs, the debugger replaces the original op code in
|
||
|
||
the program's instruction memory, and decrements the interrupted
|
||
|
||
program counter in the saved context so that execution resumes
|
||
|
||
at the instruction that was broken.
|
||
|
||
To single-step a program, the debugger sets a bit in the
|
||
|
||
context's flags register that tells the processor to generate an
|
||
|
||
INT_01 for every instruction cycle. When that interrupt occurs,
|
||
|
||
the debugger checks to see if the interrupted address is at a new
|
||
|
||
source-code line number. If not, the debugger continues
|
||
|
||
execution. Otherwise, the debugger displays the new line in the
|
||
|
||
IDE and waits for the cracker to take an action that resumes the
|
||
|
||
program.
|
||
|
||
While the debugged program is suspended, the debugger
|
||
|
||
interacts with the cracker and provides full access to the
|
||
|
||
debugged program's context and memory. This access permits the
|
||
|
||
cracker to examine and modify part of the code.
|
||
|
||
To resume the debugged program, the debugger resets the
|
||
|
||
program's context by calling _SetThreadContext and calls
|
||
|
||
_ContinueDebugEvent. Then, the debugger returns to the top of the
|
||
|
||
loop to call _WaitForDebugEvent again.
|
||
|
||
To extract debug information from a Win32 executable file,
|
||
|
||
you must understand the format of that file (best thing to do,
|
||
|
||
to practice yourself, would be to reverse engineer small
|
||
|
||
programs). The executable file has two sections not found in
|
||
|
||
other executable files: ".stab" and ".stabstr". How nice that
|
||
|
||
they used names that suggest their purpose (nomen est omen).
|
||
|
||
You'll find them inside a table of fixed-length entries that
|
||
|
||
include entries for .text, .bss, .data and .idata. Inside these
|
||
|
||
sections the compilers put different parts of a program.
|
||
|
||
There are several different formats for encoding debug
|
||
|
||
information in an executable file. Borland's Turbo Debugger one
|
||
|
||
format. Microsoft's CodeView another. The gnu-win32 port from
|
||
|
||
Cygnus the stab format, an acronym meaning "symbol table",
|
||
|
||
although the table contains much more than just symbol
|
||
|
||
information.
|
||
|
||
The .stab section in a portable executable file is a table
|
||
|
||
of fixed-length entries that represent debugging information in
|
||
|
||
the stab format. The .stabstr section contains variable-length,
|
||
|
||
null terminated strings into which the .stab table entries point.
|
||
|
||
The documentation for the stab format is available in text
|
||
|
||
format on the Cygnus ftp site (ftp.cygnus.com//pub/gnu-win32).
|
||
|
||
Stabs contain, in a most cryptic format, the names and
|
||
|
||
characteristics of all intrinsic and user-defined types, the
|
||
|
||
memory address of every symbol in external memory and on the
|
||
|
||
stack, the program counter address of every function, the program
|
||
|
||
counter address where every brace-surrounded statement block
|
||
|
||
starts and ends, the memory address of line numbers within
|
||
|
||
source-code files, and anything else that a debugger needs. The
|
||
|
||
format is complex and cryptic because it is intended to support
|
||
|
||
any source-code language. It is the responsibility of a debugger
|
||
|
||
program to translate the stab entries into something meaningful
|
||
|
||
to the debugger in the language being debugged.
|
||
|
||
Windows '95 invokes dozens of INT_21 services from 32-bit
|
||
|
||
code, including KERNEL32.DLL and possess Krn32Mutex, which
|
||
|
||
apparently controls access to certain parts of the kernel. Some
|
||
|
||
of the functions in KERNEL32 can be blocked by the Win16Mutex,
|
||
|
||
even though Microsoft says this isn't the case.
|
||
|
||
SO, I WANNA CRACK, WHAT SHOULD I DO?
|
||
|
||
I'll show you a simple windows crack, so easy it can be done
|
||
|
||
without WINICE: let's take [WINPGP4.1.] (front-end for PGPing in
|
||
|
||
windows, by Geib - I must thank "Q" for the idea to work on this
|
||
|
||
crack).
|
||
|
||
Using WCB you'll find out quickly that the "CONGRATULATIONS
|
||
|
||
your registration number is OK" and the "SORRY, your registration
|
||
|
||
number is not correct" data blocks are at the block starting at
|
||
|
||
36.38B8 (respectively at 36.38D5 and 36.3937), that relocs to
|
||
|
||
13.081B.
|
||
|
||
Looking at 13.0000 and following code, you'll find a push
|
||
|
||
38D5 (68D538) and a push 3937 (683739) at 13.064D and 13.06AE.
|
||
|
||
The road to the crack is now open, you just need to find and
|
||
|
||
"fool" the calling routines. You'll learn the exact procedures
|
||
|
||
for this kind of WINcracks in part 2 and 3 of -> Lesson 8. Let's
|
||
|
||
now have a look at the protection scheme (disassembly from WCB):
|
||
|
||
...
|
||
|
||
13.0E88 660FBF46F8 movsx eax, word ptr [bp-08]
|
||
|
||
13.0E8D 668946F4 mov [bp-0C], eax
|
||
|
||
13.0E91 668B46F4 mov eax, [bp-0C]
|
||
|
||
13.0E95 6669C00A000300 imul eax, 0003000A
|
||
|
||
13.0E9C 668946F0 mov [bp-10], eax
|
||
|
||
13.0EA0 668B4606 mov eax, [bp+06]
|
||
|
||
13.0EA4 663B46F0 cmp eax, [bp-10]
|
||
|
||
13.0EA8 7505 jne 0EAF <- beggar_off
|
||
|
||
13.0EAA B80100 mov ax, 0001 <- flag 1 = "Right!"
|
||
|
||
13.0EAD EB04 jmp 0EB3 <- and go on
|
||
|
||
beggar_off:
|
||
|
||
13.0EAF 33C0 xor ax,ax <- flag 0 = "Nope!"
|
||
|
||
13.0EB1 EB00 jmp 0EB3 <- and go on
|
||
|
||
I want you to have a good look at this protection scheme.
|
||
|
||
IT'S THE SAME OLD SOUP! You do remember lesson 3 and the
|
||
|
||
protection schemes of the old DOS stupid games of the '80s, don't
|
||
|
||
you? IT'S THE SAME OLD SOUP! In this "up-to-date" "new" windows
|
||
|
||
application, in WINPGP version 4.1 of 1995/1996, exactly the same
|
||
|
||
kind of protection is used to "conceal" the password!
|
||
|
||
A) compare user input with memory echo
|
||
|
||
B) beggar off if not equal with AX=0
|
||
|
||
C) go on if equal with AX=1... how boring!
|
||
|
||
Besides, look at all the mov eax, and eax, moves preceding
|
||
|
||
the compare! That's a typical pattern for these "number_password"
|
||
|
||
protections! I wrote (years ago) a little crack utility that
|
||
|
||
searches for code blocks with a "66" as first instruction_byte
|
||
|
||
repeating in four or more consecutive instructions and it still
|
||
|
||
allows me to crack more than half of these windows password smuts
|
||
|
||
in less than three seconds flat. The IMUL instruction creates the
|
||
|
||
"magic" number, and if you give a closer look at the mathematical
|
||
|
||
part of the "conceal" routine, it could help you to crack
|
||
|
||
analogous schemes used in order to protect the "Instant access"
|
||
|
||
(c) & (tm) time_crippled software :=)
|
||
|
||
Now you could crack the above code in 101 different ways,
|
||
|
||
the most elegant one would probably substitute je 0EAF (or jZ
|
||
|
||
0EAF, that's the same) to the jne 0EAF at 13.0EA8. You just write
|
||
|
||
a 74 at the place of the 75, like you did for the cracks in
|
||
|
||
1978... how boring: it's really the same old soup! (But you'll
|
||
|
||
see some new tricks in the next lessons).
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC 526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 8.2: How to crack Windows, a deepr approach
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[SNAP95] [WINZIP] [WINCAT]
|
||
|
||
--------------------------------------
|
||
|
||
SPECIAL NOTE: Please excuse the somehow "unshaven"
|
||
|
||
character of the windows lessons... I'm cracking the
|
||
|
||
newest Windows '95 applications right now, therefore
|
||
|
||
at times I had to add "on the fly" some corrections to
|
||
|
||
the older Windows 3.1 and Windows NT findings.
|
||
|
||
"homines, dum docent, discunt".
|
||
|
||
---------------------------------------------------------
|
||
|
||
-> 1st THING TO REMEMBER
|
||
|
||
If you thought that DOS was a mess, please notice that windows
|
||
|
||
3.1 is a ghastly chaos, and windows 95 a gruesome nightmare of
|
||
|
||
ill-cooked spaghetti code. Old Basic "GOTO" abominations were
|
||
|
||
quite elegant in comparison with this concoction... One thing is
|
||
|
||
sure: This OS will not last... it's way too messy organised,
|
||
|
||
impossible to consolidate, slow and neurotic (but I must warn
|
||
|
||
you... I thought exactly the same things about DOS in 1981).
|
||
|
||
The most striking thing about windows 95 is that it is neither
|
||
|
||
meat not fish: neither 16 nor 32... you could call it a "24 bit"
|
||
|
||
operating system.
|
||
|
||
We'll never damage Microsoft interests enough to compensate for
|
||
|
||
this moronic situation... where you have to wait three minutes
|
||
|
||
to get on screen a wordprocessor that older OS (and even old DOS)
|
||
|
||
kick up in 5 seconds. I decide therefore, hic et nunc, to add an
|
||
|
||
ADDENDUM to this tutorial: Addendum 1 will be dedicated to teach
|
||
|
||
everybody how to crack ALL Microsoft programs that do exist on
|
||
|
||
this planet. I'll write it this sommer and give it away between
|
||
|
||
the "allowed" lessons.
|
||
|
||
Anyway you can rely on good WINICE to crack everything, you'll
|
||
|
||
find it on the web for free, I use version 1.95, cracked by [The
|
||
|
||
Lexicon] (do not bother me for Warez, learn how to use the search
|
||
|
||
engines on the web and fish them out yourself). Learn how to use
|
||
|
||
this tool... read the whole manual! Resist the temptation to
|
||
|
||
crack immediatly everything in sight... you 'll regret pretty
|
||
|
||
soon that you did not wanted to learn how to use it properly.
|
||
|
||
A little tip: as Winice is intended more for software developers
|
||
|
||
than for crackers, we have to adapt it a little to our purposes,
|
||
|
||
in order to make it even more effective: a good idea is to have
|
||
|
||
in the *.DAT initialization file following lines:
|
||
|
||
INIT = "CODE ON; watchd es:di; watchd ds:si;"
|
||
|
||
TRA = 92
|
||
|
||
This way you'll always have the hexadecimal notation on, two very
|
||
|
||
useful watch windows for passwords deprotection and enough buffer
|
||
|
||
for your traces.
|
||
|
||
WINDOWS 3.1. basic cracking: [ALGEBRAIC PROTECTIONS]
|
||
|
||
The most used windows protections are "registration codes",
|
||
|
||
these must follow a special pattern: have a "-" or a "+" in a
|
||
|
||
predetermined position, have a particular number in particular
|
||
|
||
position... and so on.
|
||
|
||
For the program [SHEZ], for instance, the pattern is to have a
|
||
|
||
14 bytes long alphanumeric sequence containing CDCE1357 in the
|
||
|
||
first 8 bytes.
|
||
|
||
The second level of protection is to "connect" such a
|
||
|
||
pattern to the alphanumeric contents of the NAME of the user...
|
||
|
||
every user name will give a different "access key". This is the
|
||
|
||
most commonly used system.
|
||
|
||
As most of these protections have a "-" inside the answering
|
||
|
||
code, you do not need to go through the normal cracking procedure
|
||
|
||
(described in the next lesson):
|
||
|
||
* load WINICE
|
||
|
||
* hwnd [name_of_the_crackanda_module]
|
||
|
||
* choose the window Handle of the snap, i.e, the exact
|
||
|
||
"FIELD" where the code number input arrives... say 091C(2)
|
||
|
||
* BMSG 091C WM_GETTEXT
|
||
|
||
* Run anew
|
||
|
||
* Look at the memory location(s)
|
||
|
||
* Do the same for the "Username" input FIELD. (Sometimes
|
||
|
||
linked, sometimes not, does not change much, though)
|
||
|
||
* BPR (eventually with TRACE) on the memory locations (these
|
||
|
||
will be most of the time FOUR: two NUMBERCODES and two
|
||
|
||
USERNAMES). The two "mirrored" ones are the most important
|
||
|
||
for your crack. At times there will be a "5th" location,
|
||
|
||
where the algebraic play will go on...
|
||
|
||
* Look at the code that performs algebraic manipulations on
|
||
|
||
these locations and understand what it does...
|
||
|
||
* Disable the routine or jump over it, or reverse it, or
|
||
|
||
defeat it with your own code... there are thousand
|
||
|
||
possibilities...
|
||
|
||
* Reassemble everything.
|
||
|
||
Uff... quite a long cracking work just to crack some miserable
|
||
|
||
program... isn'there a quicker way? OF COURSE THERE IS! Actually
|
||
|
||
there are quite a lot of them (see also the crack of Wincat Pro
|
||
|
||
below): Look at the following code (taken from SNAP32, a screen
|
||
|
||
capture utility for Windows 95, that uses a pretty recent
|
||
|
||
protection scheme):
|
||
|
||
XOR EBX,EBX ; make sure EBX is zeroed
|
||
|
||
MOV BL, [ESI] ; load input char in BL
|
||
|
||
INC ESI ; point at the next character
|
||
|
||
MOV EDI,EBX ; save the input character in EDI
|
||
|
||
CMP EBX,+2D ; input char is a "-" ?
|
||
|
||
JZ ok_it's_a_+_or_a_-
|
||
|
||
CMP EBX,+2B ; input char is a "+" ?
|
||
|
||
JNZ Jesus_it's_neither_a_minus_nor_a_plus_let's_check_it
|
||
|
||
:ok_it's_a_+_or_a_-
|
||
|
||
XOR EBX,EBX ; EBX is zeroed
|
||
|
||
MOV BL,[ESI] ; recharge BL
|
||
|
||
INC ESI ; point to next char (do not check - or +)
|
||
|
||
:Jesus_it's_neither_a_minus_nor_a_plus_let's_check_it
|
||
|
||
XOR EBP,EBP ; zero EBP
|
||
|
||
CMP DWORD PTR [boguschecker], +01
|
||
|
||
...
|
||
|
||
even if you did not read all my precedent lessons, you do not
|
||
|
||
need much more explications... this is a part of the algebraic
|
||
|
||
check_procedure inside the SNAP32 module... you could also get
|
||
|
||
here through the usual
|
||
|
||
USER!BOZOSLIVEHERE
|
||
|
||
KERNEL!HMEMCPY
|
||
|
||
USER!GLOBALGETATOMNAME
|
||
|
||
Windows wretched and detestable APIs used for copy protections,
|
||
|
||
as usual with WINICE cracking, and as described elsewhere in my
|
||
|
||
tutorial.
|
||
|
||
The above code is the part of the routine that checks for the
|
||
|
||
presence of a "+" or a "-" inside the registration number (many
|
||
|
||
protections scheme requires them at a given position, other need
|
||
|
||
to jump over them).
|
||
|
||
Now sit down, make yourself comfortable and sip a good Martini-
|
||
|
||
Wodka (invariably very useful in order to crack... but be aware
|
||
|
||
that only Moskowskaia russian Wodka and a correct "Tumball" glass
|
||
|
||
will do, do not forget the lemon)... what does this "-" stuff
|
||
|
||
mean for us little crackers?
|
||
|
||
It means that we can search directly for the CMP EBX,+2B
|
||
|
||
sequence inside any file protected with these schemes... and
|
||
|
||
we'll land smack in the middle of the protection scheme! That's
|
||
|
||
amazing... but you will never underrate enough the commercial
|
||
|
||
programmers... the only really amazing thing is how simpleton the
|
||
|
||
protectionists are! You don't believe me? Try it... you 'll get
|
||
|
||
your crack at least 4 out of 5 times.
|
||
|
||
Yes I know, to find this code is not yet to crack it... but for
|
||
|
||
this kind of copy protection (that's the reason it is so
|
||
|
||
widespread) there is no single solution... each makes a slightly
|
||
|
||
different algebraic manipulation of the alphanumeric and of the
|
||
|
||
numeric data. It's up to you to crack the various schemes... here
|
||
|
||
you can only learn how to find them and circumvene them. I'll not
|
||
|
||
give you therefore a "debug" crack solution. You'll find it
|
||
|
||
yourself using my indications (see the crack of the Wincat Pro
|
||
|
||
program below).
|
||
|
||
WHERE ARE THE CODES? WHERE ARE THE MODIFIED FILES? WHERE DO THE
|
||
|
||
PROTECTIONS KEEP COUNT OF THE PASSING DAYS?
|
||
|
||
Most of the time the protection schemes use their own *.ini files
|
||
|
||
in the c:\WINDOWS directory for registration purposes... at time
|
||
|
||
they even use the "garbage sammler" win.ini file. Let's take as
|
||
|
||
example WINZIP (versions 5 and 5.5), a very widespread program,
|
||
|
||
you'll surely have one shareware copy of it somewhere between
|
||
|
||
your files.
|
||
|
||
In theory, winzip should be registered per post, in order to
|
||
|
||
get a "NEW" copy of it, a "registered" copy.
|
||
|
||
This scares most newby crackers, since if the copy you have
|
||
|
||
it's not full, there is no way to crack it and make it work,
|
||
|
||
unless you get the REAL stuff. The youngest among us do not
|
||
|
||
realize that the production of a real "downsized" demo copy is
|
||
|
||
a very expensive nightmare for the money-infatuated commercial
|
||
|
||
programmers, and that therefore almost nobody does it really...
|
||
|
||
nearly all "demos" and "trywares" are therefore CRIPPLED COMPLETE
|
||
|
||
PROGRAMS, and not "downsized" demos, independently of what the
|
||
|
||
programmers and the protectionists have written inside them.
|
||
|
||
Back to Winzip... all you need, to crack winzip, is to add a
|
||
|
||
few lines inside the win.ini file, under the heading [WinZip],
|
||
|
||
that has already been created with the demo version, before the
|
||
|
||
line with "version=5.0".
|
||
|
||
I will not help you any further with this... I'll leave it to
|
||
|
||
you to experiment with the correct sequences... inside win.ini
|
||
|
||
you must have following sequence (these are only template to
|
||
|
||
substitute for your tries inside WINICE... you'll get it, believe
|
||
|
||
me):
|
||
|
||
[WinZip]
|
||
|
||
name=Azert Qwerty
|
||
|
||
sn=########
|
||
|
||
version=5.5
|
||
|
||
The *important* thing is that this means that you DO NOT NEED
|
||
|
||
to have a "new registered version" shipped to you in order to
|
||
|
||
make it work, as the protectionist sellers would like you to
|
||
|
||
believe. The same applies most of the time... never believe what
|
||
|
||
you read in the read.me or in the registration files...
|
||
|
||
This brings me to a broader question: NEVER believe the
|
||
|
||
information they give you... never believe what television and/or
|
||
|
||
newspapers tell you... you can be sure that the only reason they
|
||
|
||
are notifying you something is to hinder you to read or
|
||
|
||
understand something else... this stupid_slaves_society can only
|
||
|
||
subsist if nobody thinks... if you are really interested in what
|
||
|
||
is going on, real information can be gathered, but surely not
|
||
|
||
through the "conventional" newspapers and/or news_agencies (and
|
||
|
||
definitely NEVER through television, that's really only for the
|
||
|
||
stupid slaves)... yes, some bit of information can be
|
||
|
||
(laboriously) gathered... it's a cracking work, though.
|
||
|
||
HOW TO CRACK INFORMATION [WHERE WHAT]
|
||
|
||
* INTERNET
|
||
|
||
In the middle of the hugest junk collection of the planet, some
|
||
|
||
real information can be laboriously gathered if you do learn how
|
||
|
||
to use well the search engines (or if you do build your ones...
|
||
|
||
my spiders are doing most of the work for me... get your robots
|
||
|
||
templates from "Harvest" or "Verify" and start your "spider
|
||
|
||
building" activity beginning from Martijn Koster's page). As
|
||
|
||
usual in our society, in the Internet the real point is exactly
|
||
|
||
the same point you'll have to confront all your life long: HOW
|
||
|
||
TO THROW AWAY TONS OF JUNK, HOW TO SECLUDE MYRIADS OF USELESS
|
||
|
||
INFORMATION and HOW TO FISH RARE USEFUL INFORMATION, a very
|
||
|
||
difficult art to learn per se. Internet offers some information,
|
||
|
||
though, mainly BECAUSE it's (still) unregulated. You want a
|
||
|
||
proof? You are reading it.
|
||
|
||
* SOME (RARE) NEWSPAPERS.
|
||
|
||
The newspaper of the real enemies, the economic powers that
|
||
|
||
rule this slaves world, are paradoxically most of the time the
|
||
|
||
only ones worth studying... somewhere even the real rulers have
|
||
|
||
to pass each other some bits of real information. The "Neue
|
||
|
||
Zuercher Zeitung", a newspaper of the Swiss industrials from
|
||
|
||
Zuerich, is possibly the best "not_conformist trend analyzer"
|
||
|
||
around that you can easily find (even on the web). These
|
||
|
||
swissuckers do not give a shit for ideology, nor preconcerted
|
||
|
||
petty ideas, the only thing they really want is to sell
|
||
|
||
everywhere their ubiquitous watches and their chocolates... in
|
||
|
||
order to do it, a land like Switzerland, with very high salaries
|
||
|
||
and a good (and expensive) social system, must use something
|
||
|
||
brilliant... they found it: a clear vision of the world... as a
|
||
|
||
consequence this newspaper is very often "against" the trend of
|
||
|
||
all the other medias in the world, the ones that are used only
|
||
|
||
in order to tame the slaves... If the only language you know is
|
||
|
||
english (poor guy) you could try your luck with the weekly
|
||
|
||
"Economist"... you'll have to work a lot with it, coz it has been
|
||
|
||
tailored for the "new riches" of the Tatcher disaster, but you
|
||
|
||
can (at times) fish something out of it... they do a lot of
|
||
|
||
idiotic propaganda, but are nevertheless compelled to write some
|
||
|
||
truth. American newspapers (at least the ones you can get here
|
||
|
||
in Europe) are absolute shit... one wonders where the hell do the
|
||
|
||
americans hyde the real information.
|
||
|
||
On the "non-capitalistic" side of information there is a
|
||
|
||
spanish newspaper "El Pais" that seems to know about what's going
|
||
|
||
on in South America, but it's so full of useless propaganda about
|
||
|
||
irrelevant Spanish politics that it's not really worth reading.
|
||
|
||
The monthly "Le Monde diplomatique" offers something too... this
|
||
|
||
one exaggerates a little on the pauperistic "third world" side,
|
||
|
||
but has a lot of useful information. See what you can do with all
|
||
|
||
this information (or disinformation?)
|
||
|
||
[BELIEVE THE COUNTRARY]
|
||
|
||
Another good rule of thumb in choosing your medias is the
|
||
|
||
following... if all medias around you assure, for instance, that
|
||
|
||
"the Serbians are evil"... the only logical consequence is that
|
||
|
||
the Serbians are not so evil at all and that "the Croats" or some
|
||
|
||
other Yugoslavian shits are the real culprits. This does not mean
|
||
|
||
at all that the Serbians are good, I warn you, it means only what
|
||
|
||
I say: something is surely hidden behind the concerted propaganda
|
||
|
||
you hear, the best reaction is to exaggerate in the other
|
||
|
||
direction and believe the few bit of information that do say the
|
||
|
||
countrary of the trend. This rule of thumb may be puerile, but
|
||
|
||
it works somehow most of the time... if somewhere everybody
|
||
|
||
writes that the commies are bad then THERE the commies must not
|
||
|
||
be so bad at all and, conversely, if everybody in another place
|
||
|
||
writes that the commies are all good and nice and perfect (like
|
||
|
||
the Soviet propaganda did) then THERE the commies are surely not
|
||
|
||
so good... it's a matter of perspective, much depends on where
|
||
|
||
you are, i.e. whose interests are really at stake. There is NEVER
|
||
|
||
real information in this society, only propaganda... if you still
|
||
|
||
do not believe me do yourself a little experiment... just read
|
||
|
||
the media description of a past event (say the Vietnam war) as
|
||
|
||
written AT THE MOMENT of the event and (say) as described 10
|
||
|
||
years later. You'll quickly realize how untrustworthy all
|
||
|
||
newspapers and medias are.
|
||
|
||
* SEMIOTICS You'll have to study it (as soon as you can) to
|
||
|
||
interpret what they let you believe, in order to get your
|
||
|
||
bearings. A passing knowledge of ancient RHETORIC can help quite
|
||
|
||
a lot. Rhetoric is the "Softice" debugger you need to read
|
||
|
||
through the propaganda medias: concentrate on Periphrasis,
|
||
|
||
Synecdoche, Antonomasia, Emphasis, Litotes and Hyperbole at the
|
||
|
||
beginning... you'll later crack higher with Annominatio,
|
||
|
||
Polyptoton, Isocolon and all the other lovely "figurae
|
||
|
||
sententiae".
|
||
|
||
Enough, back to software cracking.
|
||
|
||
HOW A REGISTRATION CODE WORKS [WINCAT]
|
||
|
||
Let's take as an example for the next crack, a Username-
|
||
|
||
algebraic registration code, WINCAT Pro, version 3.4., a 1994
|
||
|
||
shareware program by Mart Heubel. It's a good program, pretty
|
||
|
||
useful to catalogue the millions of files that you have on all
|
||
|
||
your cd-roms (and to find them when you need them).
|
||
|
||
The kind of protection Wincat Pro uses is the most utilized
|
||
|
||
around: the username string is manipulated with particular
|
||
|
||
algorithms, and the registration key will be made "ad hoc" and
|
||
|
||
depends on the name_string. It's a protection incredibly easy to
|
||
|
||
crack when you learn how the relevant procedures work.
|
||
|
||
[WINCAT Pro] is a good choice for cracking studies, coz you
|
||
|
||
can register "over your registration" one thousand times, and you
|
||
|
||
can herefore try for this crack different user_names to see all
|
||
|
||
the algebrical correspondences you may need to understand the
|
||
|
||
protection code.
|
||
|
||
In this program, when you select the option "register", you
|
||
|
||
get a window where you can input your name and your registration
|
||
|
||
number (that's what you would get, emailed, after registering
|
||
|
||
your copy). If you load winice and do your routinely hwnd to
|
||
|
||
individuate the nag window, and then breakpoint on the
|
||
|
||
appropriate memory ranges you'll peep in the working of the whole
|
||
|
||
bazaar (this is completely useless in order to crack these
|
||
|
||
schemes, but it'll teach you a lot for higher cracking, so you
|
||
|
||
better do it also with two or three other programs, even if it
|
||
|
||
is a little boring): a series of routines act on the input (the
|
||
|
||
name) of the user: the User_name_string (usn). First of all the
|
||
|
||
usn_length will be calculated (with a REPNZ SCASB and a following
|
||
|
||
STOSB). Then various routines store and move in memory the usn
|
||
|
||
and the registration_number (rn) and their relative lengths. In
|
||
|
||
order to compare their lengths and to check the correct
|
||
|
||
alphanumeric correspondence between usn and rn, the program first
|
||
|
||
uppercases the usn and strips all eventual spaces away.
|
||
|
||
Here the relevant code (when you see an instruction like
|
||
|
||
SUB AL,20 you should immediately realize that you are in a
|
||
|
||
uppercasing routine, which is important for us, since these are
|
||
|
||
mostly used for password comparisons)... here the relevant Winice
|
||
|
||
unassemble and my comments:
|
||
|
||
253F:00000260 AC LODSB <- get the usn chars
|
||
|
||
253F:00000261 08C0 OR AL,AL <- check if zero
|
||
|
||
253F:00000263 740F JZ 0274 <- 0: so usn finished
|
||
|
||
253F:00000265 3C61 CMP AL,61 <- x61 is "a", man
|
||
|
||
253F:00000267 72F7 JB 0260 <- not a lower, so loop
|
||
|
||
253F:00000269 3C7A CMP AL,7A <- x7A is "z", what else?
|
||
|
||
253F:0000026B 77F3 JA 0260 <- not a lower, so loop
|
||
|
||
253F:0000026D 2C20 SUB AL,20 <- upper it if it's lower
|
||
|
||
253F:0000026F 8844FF MOV [SI-01],AL<- and hyde it away
|
||
|
||
253F:00000272 EBEC JMP 0260 <- loop to next char
|
||
|
||
253F:00000274 93 XCHG AX,BX
|
||
|
||
...
|
||
|
||
The instruction MOV [SI-01],AL that you see here is important
|
||
|
||
at times, coz it points to the location of the "pre-digested"
|
||
|
||
usn, i.e. the usn formatted as it should be for the number
|
||
|
||
comparison that will happen later. In some more complicated
|
||
|
||
protection schemes the reasoning behind this formatting is the
|
||
|
||
following: "Stupid cracker will never get the relation algorhitm
|
||
|
||
usn <-> rn, coz he does not know that usn AND rn are slightly
|
||
|
||
changed before comparing, ah ah... no direct guessing is
|
||
|
||
possible". Here is only "polishing": you have to "polish" a
|
||
|
||
string before comparing it in order to concede some mistakes to
|
||
|
||
the legitimate user (too many spaces in the name, upper-lower
|
||
|
||
case mismatch, foreign accents in the name etc.) You just need
|
||
|
||
to know, for now, that this checking is usually still 5 or 6
|
||
|
||
calls ahead of the real checking (it's what we call a "green
|
||
|
||
light").
|
||
|
||
You should in general realize that the real checking of the
|
||
|
||
algebrical correspondence follows after a whole series of memory
|
||
|
||
operations, i.e.: cancelling (and erasing) the previous (if ever)
|
||
|
||
attempts; reduplicating the usn and the rn somewhere else in
|
||
|
||
memory; double checking the string lengths (and saving all these
|
||
|
||
values somewhere... be particularly attentive when you meet stack
|
||
|
||
pointers (for instance [BP+05]): most of the programs you'll find
|
||
|
||
have been written in C (what else?). C uses the stack (SS:SP) to
|
||
|
||
pass parameters or to create local variables for his procedures.
|
||
|
||
The passwords, in particular, are most of the time compared to
|
||
|
||
data contained within the stack. If inside a protection a BP
|
||
|
||
register points to the stack you have most of the time fished
|
||
|
||
something... remember it pupils: it will spare you hours of
|
||
|
||
useless cracking inside irrelevant routines. Back to our CATWIN:
|
||
|
||
another little check is about the "minimal" length allowed for
|
||
|
||
a user name, in our babe, for instance, the usn must have at
|
||
|
||
least 6 chars:
|
||
|
||
230F:00003483 3D0600 CMP AX,0006
|
||
|
||
230F:00003486 730F JAE 3497 <- go to nice_name
|
||
|
||
:too_short
|
||
|
||
230F:00003488 BF9245 MOV DI,4592 <- no good: short
|
||
|
||
After a lot of other winicing you'll finally come across
|
||
|
||
following section of the code:
|
||
|
||
2467:00000CA3 B90100 MOV CX,0001
|
||
|
||
2467:00000CA6 03F1 ADD SI,CX
|
||
|
||
2467:00000CA8 2BC1 SUB AX,CX
|
||
|
||
2467:00000CAA 7213 JB 0CBF
|
||
|
||
2467:00000CAC 40 INC AX
|
||
|
||
2467:00000CAD 368B4F04 MOV CX,SS:[BX+04] <- here
|
||
|
||
2467:00000CB1 0BC9 0R CX,CX
|
||
|
||
2467:00000CB3 7D02 JGE 0CB7
|
||
|
||
2467:00000CB5 33C9 XOR CX,CX
|
||
|
||
2467:00000CB7 3BC1 CMP AX,CX
|
||
|
||
2467:00000CB9 7606 JBE 0CC1
|
||
|
||
2467:00000CBB 8BC1 MOV AX,CX
|
||
|
||
2467:00000CBD EB02 JMP 0CC1
|
||
|
||
2467:00000CBF 33C0 XOR AX,AX
|
||
|
||
2467:00000CC1 AA STOSB <- and here
|
||
|
||
2467:00000CC2 8BC8 MOV CX,AX
|
||
|
||
2467:00000CC4 F3A4 REPZ MOVSB <- and here!
|
||
|
||
2467:00000CC6 8EDA MOV DS,DX
|
||
|
||
2467:00000CC8 FC RETF 0008
|
||
|
||
This is obviously the last part of the checking routine
|
||
|
||
(I'll not delve here with the mathematical tampering of it, if
|
||
|
||
you want to check its workings, by all means, go ahead, it's
|
||
|
||
quite interesting, albeit such study is NOT necessary to crack
|
||
|
||
these schemes). The important lines are obviously the MOV
|
||
|
||
CX,SS:[BX+04], the STOSB and the REPZ MOVSB (as usual in password
|
||
|
||
protection schemes, you do remember lesson 3, don't you?).
|
||
|
||
You should be enough crack-able :=) by now (if you have read
|
||
|
||
all the precedent lessons of my tutorial), to find out easily,
|
||
|
||
with these hints, how the working of the protection goes and
|
||
|
||
where dwells in memory the ECHO of the correct rn (passkey) that
|
||
|
||
matches the name you typed in. Remember that in these kind of
|
||
|
||
cracks the ECHO is present somewhere (90% of the cases). There
|
||
|
||
are obviously one thousand way to find such ECHOs directly,
|
||
|
||
without going through the verificayions routines... for instance
|
||
|
||
you could also find them with a couple of well placed
|
||
|
||
snap_compares, it's a "5 minutes" cracking, once you get the
|
||
|
||
working of it. I leave you to find, as interesting exercise, the
|
||
|
||
routine that checks for a "-" inside the rn, a very common
|
||
|
||
protection element.
|
||
|
||
In order to help you understand the working of the protection
|
||
|
||
code in [Wincat Pro] I'll give you another hint, though: if you
|
||
|
||
type "+ORC+ORC+ORC" as usn, you'll have to type 38108-37864 as
|
||
|
||
rn, if you usn as usn "+ORC+ORC" then the relative rn will be
|
||
|
||
14055-87593. But these are my personal cracks... I have offered
|
||
|
||
this information only to let you better explore the mathematical
|
||
|
||
tampering of this specific program... you'll better see the
|
||
|
||
snapping mechanism trying them out (going through the routines
|
||
|
||
inside Winice) alternatively with a correct and with a false
|
||
|
||
password. Do not crack Wincat with my combination! If you use a
|
||
|
||
different usn than your own name to crack a program you only show
|
||
|
||
that you are a miserable lamer... no better than the lamers that
|
||
|
||
believe to "crack" software using huge lists of serial numbers...
|
||
|
||
that is really software that they have stolen (Yeah: stolen, not
|
||
|
||
cracked). You should crack your programs, not steal them...
|
||
|
||
"Warez_kids" and "serial#_aficionados" are only useless zombies.
|
||
|
||
I bomb them as soon as I spot them. YOU ARE (gonna be) A CRACKER!
|
||
|
||
It makes a lot of a difference, believe me.
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
"If you give a man a crack he'll be hungry again
|
||
|
||
tomorrow, but if you teach him how to crack, he'll
|
||
|
||
never be hungry again"
|
||
|
||
E-mail +ORC
|
||
|
||
an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson 9 (1): How to crack Windows, Hands on
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[Winformant][Snap32]
|
||
|
||
--------------------------------------
|
||
|
||
THE [DATA_CONSTRAINT] TRICK - [WINFORMANT 4]
|
||
I have chosen an older windows application for Win 3.1.
|
||
(WIN4MANT.EXE, 562271 bytes, Version 1.10, by Joseph B. Albanese;
|
||
you'll find it searching the web with the usual tools, see how
|
||
to do it at the end of this lesson), in order to show you how to
|
||
use a nice little trick, at times really useful in cracking
|
||
password protected programs: [data_constraint]. Inside almost all
|
||
protection routines, as you have already learned, there is a
|
||
moment when on the stack the ECHO of the real, "correct"
|
||
passnumber or password appears. The location of this ECHO varies,
|
||
but most of the time it'll be in a range of +- 0x90 bytes from
|
||
one of the locations where the user input dwells. This is due to
|
||
datadump windows constraints inside the tools used by the
|
||
protectionists... but this use is bound to diminish... especially
|
||
after this lesson :=)
|
||
|
||
[WINFORMANT CRACKING]
|
||
This application is -per se- crappy, I doubt you'll ever use
|
||
it... but its curious (and pretty rare) "deactivate" mode is
|
||
nevertheless very interesting for us: you can "unregister"
|
||
Winformant on the fly if you feel the need to.
|
||
This feature is pretty useful for scholars that like to
|
||
investigate password algorithms with valid and invalid codes
|
||
without having to reinstall every time to delete a valid code.
|
||
For your cracking exercises choose programs that have
|
||
"REVERSIBLE" protections (rare) or that can be re-registered a
|
||
billion times (more frequent). Programs that keep the valid
|
||
registration on *.ini or special files will also do the job: you
|
||
just change a couple of lines to "unregister" them.
|
||
The trick of this lesson: [data_constraint], or "password
|
||
proximity", bases on the protectionist's need to keep an eye on
|
||
the protection "working" when he assembles it. He must "see" the
|
||
relationships between USER INPUT NUMBER, USER INPUT TRANSFORMED
|
||
and the CORRECT NUMBER ANSWER (in our jargon: the "Bingo"). These
|
||
relationships must be constantly checked In order to debug the
|
||
protection code. Mostly they will dwell TOGETHER inside a small
|
||
stack area, allowing them to be "seen" in the SAME watchwindow.
|
||
Most of the time, therefore, the "ECHO" will "materialize"
|
||
shortly not very far away from one of the locations of the USER
|
||
INPUT. Let's crack:
|
||
|
||
* Fire Winice and then Winformant
|
||
* Choose HELP and then choose REGISTRATION
|
||
* Fill the registration fields with "+ORC+ORC" as "Registrant"
|
||
and "12121212" as "Activation" code (use whatever you fancy).
|
||
CTRL+D ;switch to Winice
|
||
:task ;let's see what's the name of this crap
|
||
TaskName SS:SP StackTop StackBot StackLow TaskDB hQueue Events
|
||
WINWORD 1AD7:85F2 4A52 8670 7532 1247 122F 0000
|
||
PROGMAN 1737:200A 0936 2070 1392 066F 07F7 0000
|
||
DISKOMAT *2C5F:6634 1D3C 6AC6 5192 2CB7 2C9F 0000
|
||
|
||
:hwnd DISKOMAT ;which window is getting the input?
|
||
WinHandle Hqueue QOwner Class Name Window Procedure
|
||
0EB4(0) 2C9F DISKOMAT #32769 04A7:9E6B
|
||
0F34(1) 2C9F DISKOMAT #32768 USER!BEAR306
|
||
365C(1) 2C9F DISKOMAT #32770 2C3F:0BC6
|
||
36BC(2) 2C9F DISKOMAT Button 2C3F:1CEA
|
||
3710(2) 2C9F DISKOMAT Edit 2C3F:24BE
|
||
... and many more irrelevant windows.
|
||
|
||
Let's pinpoint the code, here the relevant window is the first
|
||
"Edit" one, for obvious reasons (more on this later).
|
||
:bmsg 3710 wm_gettext ;set breakpoint
|
||
CTRL+D ;run the babe until you get:
|
||
Break Due to BMSG 3710 WM_GETTEXT C=01
|
||
Hwnd=3710 wParam=0050 lParam=2C5F629A msg=000D WM_GETTEXT
|
||
2C3F:000024BE B82F2C MOV AX,2C2F
|
||
So! Now we have "pinpointed" the babe (more on "pinpointing"
|
||
later). Let's snoop around a little: look at the stack to fetch
|
||
your babe's last call (if it does not show immediately, just keep
|
||
pinpointing, for instance on GetWindowText() or do a BPRW
|
||
diskomat (very useful), and then try and retry the stack...
|
||
should this too fail to work, search for your input in memory (in
|
||
the 30:0 lffffffff selector, as usual) and breakpoint range on
|
||
it with ReadWrite, and then stack, stack, stack... until you get
|
||
the "real" list of calls coming from your babe's protection.
|
||
:stack ; let's see
|
||
USER(19) at 073F:124C [?] through 073F:1239
|
||
CTL3D(02) at 2C3F:0D53 [?] through 2C3F:0D53
|
||
DISKOMAT(01) at 2C97:20B9 [?] through 2C97:20B9
|
||
DISKOMAT(01) at 2C97:3D94 [?] through 2C97:3D94
|
||
DISKOMAT(01) at 2C97:49E2 [?] through 2C97:4918
|
||
DISKOMAT(04) at 2C7F:EA20 [?] through 2C7F:EA20
|
||
USER(01) at 04A7:19BE [?] through USER!GETWINDOWTEXT
|
||
== CTL3D(02) at 2C3F:24BE [?] through 04A7:3A3C<33>
|
||
|
||
Beautiful stack fishing! Do immediately a BPX on babe:EA20.
|
||
2C7F:EA35 9A25ABA704 CALL USER!GETWINDOWTEXT
|
||
2C7F:EA3A 8D46AE LEA AX,[BP-52] ;load ptr "+ORC+ORC"
|
||
2C7F:EA3D 16 PUSH SS ;save pointer segment
|
||
2C7F:EA3E 50 PUSH AX ;save pointer offset
|
||
2C7F:EA3F 9A768D872C CALL 2C87:8D76; get strlen "ORC+ORC"
|
||
2C7F:EA44 83C404 ADD SP,+04
|
||
2C7F:EA47 3D2800 CMP AX,0028
|
||
2C7F:EA4A 762C JBE EA78
|
||
...
|
||
2C7F:EA97 8D46AE LEA AX,[BP-52] ;load ptr "+ORC+ORC"
|
||
2C7F:EA9A 16 PUSH SS ;various algors on input
|
||
2C7F:EA9B 50 PUSH AX ;follow here, we do not
|
||
... ;need to care
|
||
2C7F:EAB2 0F851101 JNE EBC7
|
||
2C7F:EAB6 8D8E5CFF LEA CX,[BP+FF5C] ;ptr "12121212"
|
||
2C7F:EABA 16 PUSH SS
|
||
2C7F:EABB 51 PUSH CX
|
||
2C7F:EABC 9A768D872C CALL 2C87:8D76 ;get strlen "12121212"
|
||
2C7F:EAC1 83C404 ADD SP,+04
|
||
2C7F:EAC4 50 PUSH AX
|
||
2C7F:EAC5 8D865CFF LEA AX,[BP+FF5C] ;ptr "12121212" HERE!
|
||
2C7F:EAC9 16 PUSH SS
|
||
2C7F:EACA 50 PUSH AX
|
||
...etc, various algors on input follow here
|
||
|
||
OK, it's enough: now obviously follows the code that
|
||
"algorithmize" the number string, and then, somewhere, you'll
|
||
have the hideous compare that divides good guys and bad crackers.
|
||
You could examine, and crack, and search...
|
||
BUT NOW IT'S THE "MAGIC MOMENT" OF THE ECHO! We know and *feel*
|
||
it: The echo must be somewhere... how do we find it? Searching
|
||
"12121212" in memory fishes at least 10 different locations...
|
||
:s 30:0 lffffffff '12121212'
|
||
Pattern Found at 0030:0005AD6A
|
||
.... (7 more)
|
||
Pattern Found at 0030:80509D6A
|
||
Pattern Found at 0030:8145AD6A
|
||
Should we look for all occurrences of string '12121212',
|
||
starting with the two at 80000000, dumping +-0x90 around it...
|
||
until we find the echo? We could, and it would work, but that's
|
||
not zen... that's boring! In other protections these locations
|
||
could proliferate on purpose, to deter the casual cracker. There
|
||
must be some other way... And lo and behold! YES! There is a
|
||
quicker way... THE LAST loading of the numeric input string in
|
||
the code (the one after the strlen count) is the "right" one for
|
||
our cracking purposes, coz protections follow (mostly) this
|
||
pattern (remember: we are inside a "stack-heavy" section of the
|
||
code... if you want to crack higher I suggest you read some good
|
||
literature about stack working, stack tricks and stack magics
|
||
with the Intel processors):
|
||
LOAD NAMEString - COUNT NAMEStringLen
|
||
LOAD NAMEString - TRANSFORM NAMEString
|
||
LOAD CODEString - COUNT CODEStringLen
|
||
LOAD CODEString
|
||
*ECHO must be here*
|
||
TRANSFORM CODEString
|
||
*ECHO must be here*
|
||
COMPARE TRANSFORMED_NAMEString WITH TRANSFORMED_CODEString
|
||
|
||
This means that at line
|
||
2C7F:EAC5 8D865CFF LEA AX,[BP+FF5C] ;ptr "12121212"
|
||
you'll already have your echo somewhere... just dump the memory
|
||
around the pointer [BP+FF5C]:
|
||
:d 2c5f:61e8 ;these numbers will differ in your computer
|
||
02 62 2F 06 02 00 26 2E-A3 4E A3 4E 01 00 38 30 .b/...&..N.N..80
|
||
33 37 2D 36 34 36 2D 33-38 33 36 00 01 06 02 00 37-646-3836.....
|
||
2F 06 75 62 C3 2E B7 04-F2 24 2F 06 CE 6E 2F 06 /.ub.....$/..n/.
|
||
49 00 5A 00 01 00-04 2C 2F 06 AE 24 36 62 00 00 I.Z......,/..$6b
|
||
74 62 7A 2E B7 04 36 62-01 00 C2 62 2F 2C 26 2E tbz...6b...b/,&.
|
||
03 01 BA 0F AE 24 5F 02-C9 01 5E 02 BA 01 5F 02 .....$_...^..._.
|
||
31 32 31 32 31 32 31 32-00 0C 00 BC 02 00 00 00 12121212........
|
||
00 49 00 BA 0F-AE 24 F2 24 2F 06 00 00 00 00 00 ....I....$.$/...
|
||
AF 17 00 E2 5F-7A 62 FE FF 79 1B BA 0F 00 00 00 ......._zb..y...
|
||
96 0B 01 00 02 4E 00-37 01 8A 62 D2 0F 8F 17 00 .....N..7..b....
|
||
2F 06 00 37 01-98 62 20 10 16 03 2F 06 00 00 00 /.....7..b .../.
|
||
C2 62 2B 4F 52 43 2B 4F-52 43 00 0D AE 24 2F 06 .b+ORC+ORC......
|
||
|
||
Look at this dump: everybody is there! The stack pointers points
|
||
in the middle, at string "12121212". 0x50 bytes before it you'll
|
||
find our good old ECHO (i.e. the CORRECT passnumber) and 0x50
|
||
bytes afterwards you'll see your handle: here "+ORC+ORC".
|
||
It's cracked! The code for my "+ORC+ORC" is 8037-646-3836...
|
||
Now begin your assignments: if you rally want to learn cracking:
|
||
- "Unregister" and find anew your own code for your own
|
||
handle. *DO NOT* use serial numbers with any other name
|
||
that your own handle, that's miserable stealing, not
|
||
cracking. I'll begin to punish the serial#_aficionados on
|
||
the Web, coz I like real outlaws, but I detest stupid
|
||
pickpockets.
|
||
- Study the two coding algorithms, the one for the input name
|
||
and the one for the input number, this will be very useful
|
||
for your future cracking sessions.
|
||
- Find the "Compare", i.e. the code that sets the two usual
|
||
flags "good guy, you may move on" and "bad cracker, beggar
|
||
off", and
|
||
- Create a "real" crack for this protection, that will allow
|
||
anybody you think deserves it, with any name and any
|
||
password number, to get through.
|
||
|
||
[CRACKING SNAP 32]
|
||
Snap 32 (SNAP32.EXE 356.352 bytes, 24/11/95, Version 2.54,
|
||
by Greg Kochaniak) is a "snapshot" shareware program for Windows
|
||
95, that allows users to save the screen, parts of it, or a
|
||
single window. It's a very common 'try before you buy' program,
|
||
limited to 30 days use. You'll find it everywhere on the Web. If
|
||
you do not know how to search the Web (poor guy!), learn at the
|
||
end of this lesson the correct procedure to find all the files
|
||
you need on the Net and get them automatically emailed to you
|
||
(that's something you should learn: SEARCHING! It's even more
|
||
important than cracking!).
|
||
Snap32 is not very interesting (I don't think I used it more
|
||
than a couple of times), but its protection is: in order to (try
|
||
to) deter casual crackers it does not compare strings, it
|
||
compares a "magic" sum (from Namestring) with another magic sum
|
||
(from Numberstring). And:
|
||
* SUMS magics inside the GDI, not inside its own code;
|
||
* USES a look_up table for input validation instead of
|
||
"plain" code;
|
||
* COMPARES the "magic" manipulation from input NUMBER with
|
||
the "magic" manipulation from input NAME.
|
||
|
||
The cracking procedure for most of these windows programs is
|
||
pretty simple and relatively straightforward:
|
||
|
||
1) SEE THE NAME OF YOUR BABE AND ITS QUEUE SELECTOR
|
||
:task ;This is the Winice95 command you type after firing
|
||
snap32 and getting at the "Enter License" nag window:
|
||
|
||
TaskName SS:SP StckTp StckBt StckLw TaskDB Hqueue Events
|
||
Snap32 0000:0000 006 AC000 006B0000 270E D27 0000
|
||
|
||
OK, the babe is Snap32,it's HQUEUE is 0xD27, it's TaskDB is
|
||
0x27OE, orright.
|
||
|
||
2) SEE THE MODULES OF YOUR BABE:
|
||
:map32 snap32 ;Your command
|
||
Owner Obj Name Obj# Address Size Type
|
||
SNAP32 .text 0001 0137:00401000 00043000 CODE RO
|
||
SNAP32 .rdata 0002 013F:00444000 00002E00 IDATA RO
|
||
SNAP32 .data 0003 013F:00447000 00009000 IDATA RW
|
||
SNAP32 .idata 0004 013F:00471000 00001C00 IDATA RW
|
||
SNAP32 .rsrc 0005 013F:00473000 00001600 IDATA RO
|
||
SNAP32 .reloc 0006 013F:00475000 00004C00 IDATA RO
|
||
|
||
OK, so the code is in selector 137:(as usual), and you have there
|
||
43000 bytes of code from 401000 to 401000+43000; the DATA,
|
||
ReadWrite and ReadOnly, are in selector 13F: (as usual).
|
||
|
||
3) SEE THE HANDLE OF THE PROTECTION "NAG" WINDOW
|
||
:hwnd snap32 ;Your command
|
||
Window Handle Hqueue SZ Qowner Class Name Window Procedure
|
||
0350(1) 0D27 32 SNAP32 #02071 144F:0560
|
||
0354(2) 0D27 32 SNAP32 #02071 17CF:102E
|
||
... and many more windows that we do not care of.
|
||
|
||
OK, so, for our cracking purposes, it's Handle 0x350. Most of
|
||
the times the "nag" window you want to crack will be the first
|
||
one in the hwnd listing (coz it was the last one to appear).
|
||
Watch the number in parentheses that follows the Whandle: (1) is
|
||
a mother, (2) are "children" windows. At times you'll find under
|
||
"Class Name" something like "Edit" (see before the Winformant
|
||
cracking)... SNIFF THERE! At times the "Window Procedure" code
|
||
location in a list of more than twenty, will be slightly
|
||
different for one or two windows... SNIFF THERE!
|
||
|
||
4) BREAKPOINT MESSAGE WM_GETTEXT (or any other WM_ that you can
|
||
think of in order to "pinpoint" the code of our babe).
|
||
"Pinpointing" the code is extremely important in windows
|
||
cracking... this idiotic OS moves code, data and stack out and
|
||
inside the pages all the time... so you'll keep getting on
|
||
"INVALID" sections without a correct pinpointing. Good
|
||
Pinpointing points are in general:
|
||
BMSG xxxx WM_GETTEXT (good for passwords)
|
||
BMSG xxxx WM_COMMAND (good fro OK buttons)
|
||
BPRW *your babe* TW (good for tracking)
|
||
u USER!GETWINDOWTEXT (u and then BPX inside the code)
|
||
u GETDLGITEM (for the Hwnd of an Item inside a
|
||
Dialog Box)
|
||
CSIP NOT GDI (if you have too many interferences)
|
||
u USER!SHOWWINDOW (bpx with counter occurrence to get to
|
||
the "right" window)
|
||
u GETSYSTEMTIME (for "time-crippled" software)
|
||
and many others pinpointing points you'll learn. If you are
|
||
really desperate for pinpointing, just do a BMSG xxxx WM_MOVE and
|
||
then move the nag window, this will always work. Let's go on:
|
||
|
||
:bmsg 350 wm_gettext ;Your command
|
||
OK, so the code is ready to be pinpointed.
|
||
|
||
5)RUN THE PROGRAM TO THE BREAKPOINT:
|
||
CTRL+D ;Your command to exit Winice and run
|
||
until it pops out at breakpoint
|
||
OK, now you pop out inside Winice somewhere... (look at the stack
|
||
to know where) so the code has been pinpointed.
|
||
|
||
6) SEARCH THE DATA AREA for your input string (4 Gigabytes from
|
||
30:0... remember that DATA are *always* in 30:0 to 30:FFFFFFFF
|
||
and CODE is *always* in 28:0 to 28:FFFFFFFF). In most protection
|
||
the "registration_number" string must match the "username"
|
||
string, which cannot be constrained, in order to allow users to
|
||
choose whatever stupid name they fancy. Some protections requires
|
||
fixed symbols inside the "username" string, though... in these
|
||
rare eventualities, just apply to the "username" string what
|
||
we'll do here with the "registration_number" string. The point
|
||
to remember is: begin always with the protection fumbling your
|
||
number, crack only if necessary the protection that fumbles your
|
||
name. Let's search now.
|
||
|
||
:s 30:0 lffffffff '12121212' ;Your command
|
||
Pattern Found at 0030:80308612
|
||
|
||
80000000 is good. Lower era videos, mirrors and BIOS, higher
|
||
(around C0000000) you have the OS dustbins... the point to
|
||
remember is: investigate always FIRST the 80000000 locations.
|
||
|
||
7) BREAKPOINT ON MEMORY RANGE ON THIS STRING.
|
||
By the way: prepare a watch window dex 3 es:di, you'll soon see
|
||
how useful such an automated watchwindow is in password cracking.
|
||
|
||
:bpr 30:80308612 30:80308612+8 RW ;Your command
|
||
|
||
OK Now we'll begin to dig out the relevant parts of the code.
|
||
Remember that you must breakpoint *every* copy of the string that
|
||
protection generates. A typical copy routine, very frequently
|
||
used in windows copy protection schemes, dwells inside
|
||
KERNEL!HMEMCPY (+0076):
|
||
|
||
0117:9E8E 66C1E902 SHR ECX,02
|
||
0117:9E92 F36766A5 REPZ MOVSD ;makes a copy in es:di
|
||
0117:9E96 6659 POP ECX
|
||
0117:9E98 6683E103 AND ECX,+03
|
||
0117:9E9C F367A4 REPZ MOVSB
|
||
0117:9E9F 33D2 XOR DX,DX
|
||
|
||
In fact, this piece of copying code is so often used for password
|
||
verifications that sometimes you just need to bpx on 0117:9E92
|
||
to get the correct stack sequence... but let's, for now, continue
|
||
without such little tricks: just keep on BPRring (Breakpoint on
|
||
memory range) all copies that protection makes.
|
||
|
||
8) LET THE BABE RUN, it will breakpoint on all manipulations of
|
||
your input string. One of them will lead to the magic.
|
||
8.1.) VALIDATION phase
|
||
There are many routines that check and "validate" your inputs.
|
||
The most common ones check that your numbers ARE really numbers,
|
||
i.e. in the range 0x30-0x39. Usually this is done with:
|
||
CMP EAX,+30
|
||
JB no_number
|
||
CMP EAX,+39
|
||
JA no_number
|
||
At times the protectionists use TABLES instead... The number
|
||
itself is used as a pointer to a "ready made" table where the
|
||
relevant magic can be used as a protection. Imagine that a number
|
||
4 in your input points to a code section that throws you
|
||
immediately outside the validation routine... or imagine that a
|
||
number 7, if found in your input, fetches a magic code that
|
||
removes the whole program from your harddisk (or worse): "Ah, ah!
|
||
Stupid cracker will never know that he should not have used
|
||
number 4... and definitely not number 7! Next time he'll
|
||
learn..." Yes, tables have been used for such nasty tricks.
|
||
Here the relevant code for the "validation" part of our
|
||
protection (still checking my favourite input string '12121212'):
|
||
:check_if_valid
|
||
0137:4364AE 8A16 MOV DL,[ESI] ;load license number
|
||
0137:4364B0 33C0 XOR EAX,EAX ;zero AX
|
||
0137:4364B2 668B0451 MOV AX,[ECX+2*EDX] ;look table for 84
|
||
0137:4364B6 83E008 AND EAX,+08 ;OK if AND'S TO zero
|
||
0137:4364B9 85C0 TEST EAX,EAX ;and therefore
|
||
0137:4364BB 7403 JZ 004364C0 ;go on
|
||
0137:4364BD 46 INC ESI ; ready for next number
|
||
0137:4364BE EBCD JMP 0043648D
|
||
:strip_-_&_+_signs
|
||
0137:4364C0 33DB XOR EBX,EBX ;clean BX
|
||
0137:4364C2 8A1E MOV BL,[ESI] ;load license number
|
||
0137:4364C4 46 INC ESI ;ready for next
|
||
0137:4364C5 8BFB MOV EDI,EBX ;save copy
|
||
0137:4364C7 83FB2D CMP EBX,+2D ;is it a "-"?
|
||
0137:4364CA 7405 JZ 004364D1
|
||
0137:4364CC 83FB2B CMP EBX,+2B ;is it a "+"?
|
||
|
||
8.2.) MANIPULATION (summing magic numbers)
|
||
Your wisely set breakpoints on memory range for the occurrence
|
||
of the string "12121212" will pop you out, inter alia, inside
|
||
following piece of code (note how this part of protection dwells
|
||
inside GDI, and NOT inside the code selector of snap32):
|
||
0557:11BD 33C0 XOR EAX,EAX ;zero AX
|
||
0557:11BF 66648B06 MOV AX,FS:[ESI] ;load number
|
||
0557:11C3 83C602 ADD ESI,+02 ;point to next
|
||
0557:11C6 66833C4700 CMP WORD PTR [EDI+2*EAX],+00
|
||
0557:11CB 0F8424010000 JE 000012F5
|
||
0557:11D1 668B0442 MOV AX,[EDX+2*EAX] ;load from magic table
|
||
0557:11D5 03D8 ADD EBX,EAX ;save sum in EBX
|
||
0557:11D7 49 DEC ECX ;till we are done
|
||
0557:11D8 75E5 JNZ 000011BF ;loop along
|
||
|
||
Interesting, isn't it? Protection is using this GDI routine to
|
||
create a SUM (through pointers to another table) that depends on
|
||
your very input numbers. We are now very near to the crack... can
|
||
you *feel* it? If not, prepare yourself a good Martini Vodka!
|
||
This is the correct way to do it:
|
||
* Get a "highball" glass;
|
||
* Put some ice cubes inside it (2 or 3);
|
||
* Add Martini Dry (From Martini & Rossi). Fill to 1/3;
|
||
* Add Moskowskaja Wodka (the only real Vodka). Fill to 2/3;
|
||
* Add a zest of lemon (From Malta or Southern France);
|
||
* Add a green "sound" olive (from Italy or Israel);
|
||
* Add Schweppes Indian Tonic. Fill to the brim.
|
||
Sit deeper and relax, sip slowly and *feel* where the code of the
|
||
protection scheme you are cracking "moves"... It's like a
|
||
current... a slow tide. If you still do not believe me, just try
|
||
it.
|
||
|
||
We'll now find out where protection stores the "magic" sum (and
|
||
now you'll pop out inside the very own snap32 code, this is the
|
||
"real" protection part):
|
||
|
||
8.3.) The ludicrous "HIDING" of the magic sum
|
||
0137:40437E 83C404 ADD ESP,+04
|
||
0137:404381 8B4DE8 MOV ECX,[EBP-18]
|
||
0137:404384 8945F0 MOV [EBP-10],EAX ;***HERE!***
|
||
0137:404387 68FF000000 PUSH 000000FF
|
||
0137:40438C 8D8574FBFFFF LEA EAX,[EBP+FFFFFB74] ;load string
|
||
0137:404392 50 PUSH EAX ;push it
|
||
0137:404393 E886410100 CALL 0041851E ;manipulate
|
||
0137:404398 8D8574FBFFFF LEA EAX,[EBP+FFFFFB74] ;load string
|
||
0137:40439E 50 PUSH EAX ;push it
|
||
0137:40439F E88C210300 CALL 00436530 ;manipulate
|
||
|
||
As you can see, the protection is very simple: The "magic" sum
|
||
is hidden only two lines before the further manipulations of the
|
||
input string. We have found location 137:404384, here, in the
|
||
CORRECT way, through bprring of the string that has been
|
||
manipulated in the GDI, but actually, we could have found it
|
||
quickly just checking superficially what's happening "around" all
|
||
manipulations of the input string. Do we really need to follow
|
||
all manipulations of our registration_number and eventually also
|
||
all manipulation of our username? NO, not at all: we just set a
|
||
BPR on the stack location where protection hides the sum [EBP-10]
|
||
and we'll see what happens: 90% of these protections just create
|
||
two sums, a sum from your username and a sum from your
|
||
registration_number... somewhere there will be a compare that
|
||
must use this location (or a copy of it... we'll see).
|
||
|
||
8.4.) COMPARING THE MAGICS FROM THE TWO INPUT STRING
|
||
Breakpoint on memory range on the sum location [EBP-10] that you
|
||
saw in the previous code and you'll land at this piece of code:
|
||
0137:404412 E82F050000 CALL 00404946
|
||
0137:404417 83C40C ADD ESP,+0C
|
||
0137:40441A 3B45F0 CMP EAX,[EBP-10] ;comp AX & magicsum
|
||
0137:40441D 740F JZ 0040442E
|
||
0137:40441F 68C0874400 PUSH 004487C0
|
||
0137:404424 E8149E0000 CALL 0040E23D
|
||
0137:404429 83C404 ADD ESP,+04
|
||
0137:40442C EB5B JMP 00404489
|
||
0137:40442E 893DA0714400 MOV [004471A0],EDI
|
||
0137:404434 85FF TEST EDI,EDI
|
||
|
||
That's it, you have made it! We found the compare between the
|
||
"username" magic number (for my "+ORC+ORC" string that's here
|
||
0x7C25621B) in AX (we do not need to know how this landed
|
||
there... it's irrelevant!) and the "license_number" '12121212'
|
||
(whose magic is here 0x00B8F47C) stored in [pointer-10.] How do
|
||
we find now the correct INPUT number for +ORC+ORC? Well, it's
|
||
easy... the "magic number" must be the same... therefore:
|
||
|
||
Cracked=Dec(0x7C25621B)
|
||
Cracked=2082824731
|
||
|
||
That was it. Old Snap32 has been cracked. You could now
|
||
prepare a crack in order to distribute this program around
|
||
without its simple protection. Good cracked applications should
|
||
be given free (i.e. cracked) to all the people that NEED them and
|
||
do not have the money to buy them. Don't forget that in this
|
||
intolerable society the 0,5% of the citizens own the 56% of the
|
||
industrial capital and the 63% of the propaganda machines (data
|
||
from US researchers... therefore suspect... the real situation
|
||
is probably even worser) effectively conditioning the destiny of
|
||
millions of slaves, moronized by television watching. So crack
|
||
the applications and give them to the people you care and the
|
||
peolple that need them, but for the others... just EXPLAIN
|
||
everybody how you did it... this is real help: giving knowledge,
|
||
not wares. DO NOT use my handle and my codes to crack this
|
||
program, get yours, I gave you mine only as an help for this
|
||
cracking lesson. I have showed you the way enough... THIEFS, not
|
||
crackers, use the codes that others have found. You are (gonna
|
||
be) CRACKERS! Remember it, look straight ahead, crack accurately
|
||
and keep your tommy in.
|
||
|
||
HOW TO SEARCH THE INTERNET FOR FILES WITHOUT MOVING A FINGER
|
||
It's amazing: most of the people roaming around inside Internet
|
||
DO NOT know how to use effectively the web. I'll be very
|
||
altruistic and explain how to fetch the very example of Snap32,
|
||
the babe we cracked in this lesson.
|
||
|
||
1) Choose an archie from this list (I will not explain you what
|
||
an archie is, you should know it... if you do not, be ashamed):
|
||
archie.univie.ac.at 131.130.1.23 Austria
|
||
archie.belnet.be 193.190.248.18 Belgium
|
||
archie.funet.fi 128.214.6.102 Finland
|
||
archie.univ-rennes1.fr 129.20.254.2 France
|
||
archie.th-darmstadt.de 130.83.22.1 Germany
|
||
archie.ac.il 132.65.16.8 Israel
|
||
archie.unipi.it 131.114.21.10 Italy
|
||
archie.uninett.no 128.39.2.20 Norway
|
||
|
||
2) Email a message to your archie:
|
||
To: archie.univie.ac.at (for instance)
|
||
Subject: (nothing on this field)
|
||
Body: set search sub (substrings too)
|
||
set maxhits 140 (max 140 hits)
|
||
set maxhitspm 9 (not the same file all over)
|
||
find snap32 (we want this)
|
||
|
||
3) After a while you'll get (per email) your answer: Here the
|
||
answer from the Austrian archie
|
||
|
||
Host ftp.wu-wien.ac.at (137.208.8.6)
|
||
Last updated 17:48 9 Aug 1995
|
||
Location: /pub/systems/windows.32/misc
|
||
FILE -rw-r----- 128957 bytes 15:59 16 Jun 1995 snap32.zip
|
||
Host space.mit.edu (18.75.0.10)
|
||
Last updated 00:45 4 Mar 1996
|
||
Location: /pub/mydir
|
||
FILE -rw-r--r-- 407040 bytes 11:55 28 Nov 1995 snap32.exe
|
||
|
||
4) ftpmail your file (Browsing is no good: too busy and lame).
|
||
Again, I will not explain you what an FTPMAIL server is: learn
|
||
it by yourself... choose a good one from this list (there are
|
||
many more... you'll learn):
|
||
bitftp@vm.gmd.de (Germany)
|
||
ftpmail@ieunet.ie (Ireland)
|
||
bitftp@plearn.edu.pl (Poland)
|
||
ftpmail@ftp.sun.ac.za (South Africa)
|
||
ftpmail@ftp.sunet.se (Sweden)
|
||
ftpmail@ftp.luth.se (Sweden)
|
||
ftpmail@src.doc.ic.ac.uk (United Kingdom)
|
||
|
||
To: ftpmail@ftp.sun.ac.za. (for instance)
|
||
Subject: (leave blank)
|
||
Body: open space.mit.edu (the last occurrence that
|
||
the archie sent)
|
||
cd/pub/mydir (get the correct subdir)
|
||
bin (prepare for BINARY)
|
||
get snap32.exe (I want this)
|
||
quit (bye)
|
||
|
||
5) Your FTPMAIL server will first notice you a receipt:
|
||
|
||
FTP EMAIL response...
|
||
ftpmail has received the following job from you:
|
||
reply-to +ORC
|
||
open space.mit.edu +ORC@now.here
|
||
get snap32.exe
|
||
ftpmail has queued your job as: 1834131821.5514
|
||
Your priority is 1 (0 = highest, 9 = lowest)
|
||
Requests to sunsite.doc.ic.ac.uk will be done before other jobs.
|
||
There are 14 jobs ahead of this one in the queue.
|
||
4 ftpmail handlers available.
|
||
To remove send a message to ftpmail containing just:
|
||
delete 1834131821.5514
|
||
|
||
After a while you'll get a second message, with your file
|
||
uuencoded inside... everything has been done.
|
||
YESSIR! there is absolutely no need to loose time on the WWW,
|
||
"surfing" idiotically from a junk site to the next or waiting
|
||
hours to download some slow file from an instable server! Wasting
|
||
time of your own LIFE, that you could use to read poetry, to make
|
||
love, to look at the stars, to sail slowly between the Aegean
|
||
islands or to start a nice cracking session. What's the point of
|
||
wasting your time when machines can perform all the searches you
|
||
need better, more productively and faster than you ever could...
|
||
YESSIR! You can get *everything* on the Web, and without paying
|
||
your Internet provider more than a couple of dimes... Nice, isn't
|
||
it?
|
||
|
||
By now, if you have followed all my lessons, you should be able
|
||
to crack relatively quickly "normal" applications. There are some
|
||
new projects for 1997: a cracking "university", that will allow
|
||
us to prepare for the divine war against Microsoft repulsive
|
||
dominion. If you do not have already chosen your handle (your
|
||
"cracker" name, that's it), you may consider choosing an handle
|
||
with a "+" somewhere inside it or, eventually, add a "+" to your
|
||
handle. This sign is used by me and by friends that have studied
|
||
and/or contributed. But a "+" in your handle ("official +ORC
|
||
cracker") will mean even more:
|
||
1) allows support from me personally (on a "do ut des" basis)
|
||
2) allows pupils to identify each other (good for joining
|
||
forces)
|
||
3) will open you (eventually) the doors to the "higher"
|
||
cracking university I'll set up on the Web in 1997.
|
||
(I'm not getting megalomaniac... In reality I only need a "quick"
|
||
method to know on which (anonymous) people I can count on for the
|
||
next phase).
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
tutorial are on the Web.
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
already, but if they are really new you'll be given full credit,
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
them with your work, or that you actually did good work on them,
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
suggestions and critics on the whole crap I wrote are also
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
Lesson A.1: Advanced Cracking: Internet Cracking (Unix)
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
-------------> INTERNET CRACKING: FIREWALLS
|
||
|
||
With each new company that connects to the "Information
|
||
|
||
Superhighway" new frontiers are created for crackers to explore.
|
||
|
||
Site administrators (Siteads) have implemented various security
|
||
|
||
measures to protect their internal networks. One of these is
|
||
|
||
xinetd, covered later. A more general solution is to construct
|
||
|
||
a guarded gateway, called a [Firewall], that sits between a
|
||
|
||
site's internal network and the wild and woolly Internet where
|
||
|
||
we roam. In fact only one third of all Internet connected
|
||
|
||
machines are already behind firewalls. Most information services
|
||
|
||
have to deal with the same problem we have: getting OUT through
|
||
|
||
a local firewall or GETTING INTO a service through their
|
||
|
||
Firewall. There lays also the crack_solution.
|
||
|
||
------------> What is a Firewall?
|
||
|
||
The main purpose of a Firewall is to prevent unauthorized
|
||
|
||
access between networks. Generally this means protecting a site's
|
||
|
||
inner network from the Internet. If a site has a firewall,
|
||
|
||
decisions have been made as to what is allowed and disallowed
|
||
|
||
across the firewall. These decisions are always different and
|
||
|
||
always incomplete, given the multiplicity of Internet, there are
|
||
|
||
always loopholes where a cracker can capitalize on.
|
||
|
||
A firewall basically works by examining the IP packets that
|
||
|
||
travel between the server and the client. This provides a way to
|
||
|
||
control the information flow for each service by IP address, by
|
||
|
||
port and in each direction.
|
||
|
||
A firewall embodies a "stance". The stance of a firewall
|
||
|
||
describes the trade-off between security and ease-of-use. A
|
||
|
||
stance of the form "that which is not expressly permitted is
|
||
|
||
prohibited" requires that each new service be enabled
|
||
|
||
individually and is seldom used, coz very slow and annoying.
|
||
|
||
Conversely, the stance "that which is not expressly prohibited
|
||
|
||
is permitted" has traded a level of security for convenience. It
|
||
|
||
will be useful to guess the stance of the firewall you are
|
||
|
||
cracking when making probe decisions.
|
||
|
||
A firewall has some general responsibilities:
|
||
|
||
* First and foremost if a particular action is not allowed by
|
||
|
||
the policy of the site, the firewall must make sure that all
|
||
|
||
attempts to perform the action will fail.
|
||
|
||
* The firewall should log suspicious events
|
||
|
||
* The firewall should alert internal administration of all
|
||
|
||
cracking attempts
|
||
|
||
* Some firewall provide usage statistics as well.
|
||
|
||
------------> Types of Firewall
|
||
|
||
In order to avoid head-scratching, it's a good idea to know
|
||
|
||
the TOPOLOGY of "your" firewall -and its limitations- before
|
||
|
||
attempting to get through it. Discussed below are two popular
|
||
|
||
firewall topologies. Although other types exist, the two below
|
||
|
||
represent the basic forms; most other firewalls employ the same
|
||
|
||
concepts and thus have -luckily- the same limitations.
|
||
|
||
1) THE DUAL-HOMED GATEWAY
|
||
|
||
A dual-homed Gateway is a firewall composed of a single
|
||
|
||
system with at least two network interfaces. This system is
|
||
|
||
normally configured such that packets are not directly routed
|
||
|
||
from one network (the Internet) to the other (the internal net
|
||
|
||
you want to crack). Machines on the Internet can talk to the
|
||
|
||
gateway, as can machines on the internal network, but direct
|
||
|
||
traffic between nets is blocked.
|
||
|
||
In discussing firewalls, it's generally accepted that you
|
||
|
||
should think of the inner network as a medieval castle. The
|
||
|
||
"bastions" of a castle are the critical points where defence is
|
||
|
||
concentrated. In a dual-homed gateway topology, the dual-homed
|
||
|
||
host itself is called the [BASTION HOST].
|
||
|
||
The main disadvantage of a dual-homed gateway, from the
|
||
|
||
viewpoints of the users of the network and us crackers alike, is
|
||
|
||
the fact that it blocks direct IP traffic in both directions. Any
|
||
|
||
programs running on the inner network that require a routed path
|
||
|
||
to external machines will not function in this environment. The
|
||
|
||
services on the internal network don't have a routed path to the
|
||
|
||
clients outside. To resolve these difficulties, dual-homed
|
||
|
||
gateways run programs called [PROXIES] to forward application
|
||
|
||
packets between nets. A proxy controls the conversation between
|
||
|
||
client and server processes in a firewalled environment. Rather
|
||
|
||
than communicating directly, the client and the server both talk
|
||
|
||
to the proxy, which is usually running on the bastion host
|
||
|
||
itself. Normally the proxy is transparent to the users.
|
||
|
||
A proxy on the bastion host does not just allow free rein
|
||
|
||
for certain services. Most proxy software can be configured to
|
||
|
||
allow or deny forwarding based on source or destination addresses
|
||
|
||
or ports. Proxies may also require authentication of the
|
||
|
||
requester using encryption- or password-based systems.
|
||
|
||
The use of proxy software on the bastion host means that the
|
||
|
||
firewall administrator has to provide replacements for the
|
||
|
||
standard networking clients, a nightmare in heterogeneous
|
||
|
||
environments (sites with many different operating systems
|
||
|
||
platforms, PC, Sun, IBM, DEC, HP...) and a great burden for
|
||
|
||
administrator and users alike.
|
||
|
||
2) THE SCREENED HOST GATEWAY
|
||
|
||
A screened host gateway is a firewall consisting of at least
|
||
|
||
one router and a bastion host with a single network interface.
|
||
|
||
The router is typically configured to block (screen) all traffic
|
||
|
||
to the internal net such that the bastion host is the only
|
||
|
||
machine that can be reached from the outside. Unlike the dual-
|
||
|
||
homed gateway, a screened host gateway does not necessarily force
|
||
|
||
all traffic through the bastion host; through configuration of
|
||
|
||
the screening router, it's possible to open "holes" in the
|
||
|
||
firewall to the other machines on the internal net you want to
|
||
|
||
get into.
|
||
|
||
The bastion host in a screened host firewall is protected
|
||
|
||
from the outside net by the screening router. The router is
|
||
|
||
generally configured to only allow traffic FROM SPECIFIC PORTS
|
||
|
||
on the bastion host. Further, it may allow that traffic only FROM
|
||
|
||
SPECIFIC EXTERNAL HOSTS. For example the router may allow Usenet
|
||
|
||
news traffic to reach the bastion host ONLY if the traffic
|
||
|
||
originated from the site's news provider. This filtering can be
|
||
|
||
easily cracked: it is relying on the IP address of a remote
|
||
|
||
machine, which can be forged.
|
||
|
||
Most sites configure their router such that any connection
|
||
|
||
(or a set of allowed connections) initiated from the inside net
|
||
|
||
is allowed to pass. This is done by examining the SYN and ACK
|
||
|
||
bits of TCP packets. The "start of connection" packet will have
|
||
|
||
both bits set. If this packets source address is internal... or
|
||
|
||
seems to be internal :=) the packet is allowed to pass. This
|
||
|
||
allows users on the internal net to communicate with the internet
|
||
|
||
without a proxy service.
|
||
|
||
As mentioned, this design also allows "holes" to be opened
|
||
|
||
in the firewall for machines on the internal net. In this case
|
||
|
||
you can crack not only the bastion host, but also the inner
|
||
|
||
machine offering the service. Mostly this or these machine/s will
|
||
|
||
be far less secure than the bastion host.
|
||
|
||
New services, for instance recent WEB services, contain a
|
||
|
||
lot of back doors and bugs, that you'll find in the appropriate
|
||
|
||
usenet discussion groups, and that you could use at freedom to
|
||
|
||
crack inner machines with firewall holes. Sendmail is a good
|
||
|
||
example of how you could crack in this way, read the whole
|
||
|
||
related history... very instructive. The rule of thumb is "big
|
||
|
||
is good": the bigger the software package, the more chance that
|
||
|
||
we can find some security related bugs... and all packages are
|
||
|
||
huge nowadays, 'coz the lazy bunch of programmers uses
|
||
|
||
overbloated, buggy and fatty languages like Visual Basic or
|
||
|
||
Delphy!
|
||
|
||
Finally, remember that the logs are 'mostly) not on the bastion
|
||
|
||
host! Most administrators collect them on an internal machine not
|
||
|
||
accessible from the Internet. An automated process scan the logs
|
||
|
||
regularly and reports suspicious information.
|
||
|
||
|
||
|
||
3) OTHER FIREWALL TOPOLOGIES
|
||
|
||
The dual-homed gateway and the screened host are probably the
|
||
|
||
most popular, but by no mean the only firewall topologies. Other
|
||
|
||
configurations include the simple screening router (no bastion
|
||
|
||
host), the screened subnet (two screening routers and a bastion
|
||
|
||
host) as well as many commercial vendor solutions.
|
||
|
||
------------> Which software should we study?
|
||
|
||
Three popular unix software solutions allow clients inside a
|
||
|
||
firewall to communicate with server outside: CERN Web server in
|
||
|
||
proxy mode, SOCKS and the TIS Firewall toolkit.
|
||
|
||
1) The CERN Web server handles not only HTTP but also the other
|
||
|
||
protocols that Web clients use and makes the remote connections,
|
||
|
||
passing the information back to the client transparently. X-based
|
||
|
||
Mosaic can be configured for proxy mode simply by setting a few
|
||
|
||
environment variables.
|
||
|
||
2) The SOCKS package (available free for anonymous ftp from
|
||
|
||
ftp.nec.com in the file
|
||
|
||
/pub/security/socks.cstc/socks.cstc.4.2.tar.gz
|
||
|
||
includes a proxy server that runs on the bastion host of a
|
||
|
||
firewall. The package includes replacements for standard IP
|
||
|
||
socket calls such as connect(), getsockname(), bind(), accept(),
|
||
|
||
listen() and select(). In the package there is a library which
|
||
|
||
can be used to SOCKSify your crack probes.
|
||
|
||
3) The Firewall Toolkit
|
||
|
||
The toolkit contains many useful tools for cracking firewall and
|
||
|
||
proxy server. netacl can be used in inetd.conf to conceal
|
||
|
||
incoming requests against an access table before spawning ftpd,
|
||
|
||
httpd or other inetd-capable daemons. Mail will be stored in a
|
||
|
||
chroot()ed area of the bastion for processing (mostly by
|
||
|
||
sendmail).
|
||
|
||
The Firewall toolkit is available for free, in anonymous ftp from
|
||
|
||
ftp.tis.com in the file
|
||
|
||
/pub/firewalls/toolkit/fwtk.tar.Z
|
||
|
||
The popular PC firewall solution is the "PC Socks Pack", for MS-
|
||
|
||
Windows, available from ftp.nec.com It includes a winsock.dll
|
||
|
||
file.
|
||
|
||
The cracking attempts should concentrate on ftpd, normally
|
||
|
||
located on the bastion host. It's a huge application, necessary
|
||
|
||
to allow anonymous ftp on and from the inner net, and full of
|
||
|
||
bugs and back doors. Normally, on the bastion host, ftpd is
|
||
|
||
located in a chroot()ed area and runs as nonprivileged user. If
|
||
|
||
the protection is run from an internal machine (as opposing the
|
||
|
||
bastion host), you could take advantage of the special inner-net
|
||
|
||
privileges in hostp.equiv or .rhosts. If the internal machine
|
||
|
||
"trusts" the server machine, you'll be in pretty easily.
|
||
|
||
Another good method, that really works, is to locate your
|
||
|
||
PC physically somewhere along the route between network and
|
||
|
||
archie server and "spoof" the firewall into believing that you
|
||
|
||
are the archie server. You'll need the help of a fellow hacker
|
||
|
||
for this, though.
|
||
|
||
Remember that if you gain supervisor privileges on a machine
|
||
|
||
you can send packets from port 20, and that in a screened host
|
||
|
||
environment, unless FTP is being used in proxy mode, the access
|
||
|
||
filters allow often connections from any external host if the
|
||
|
||
source port is 20 and the destination port is greater than 1023!
|
||
|
||
remember that NCSA Mosaic uses several protocols, each on
|
||
|
||
a different port, and that -if on the firewall no proxy Web
|
||
|
||
server is operating- each protocol must be dealt with
|
||
|
||
individually, what lazy administrators seldom do.
|
||
|
||
Be careful for TRAPS: networking clients like telnet and ftp
|
||
|
||
are often viciously replaced with programs that APPEAR to execute
|
||
|
||
like their namesake, but actually email an administrator. A
|
||
|
||
fellow cracker was almost intercepted, once, by a command that
|
||
|
||
simulated network delays and spat out random error messages in
|
||
|
||
order to keep me interested long enough to catch me. Read the
|
||
|
||
(fictions) horror story from Bill Cheswick: "An evening with
|
||
|
||
Berferd in which a cracked is lured, endured and studied",
|
||
|
||
available from ftp.research.att.com in
|
||
|
||
/dist/internet_security/berferd.ps
|
||
|
||
As usual, all kind of traps can be located and uncovered by
|
||
|
||
correct zen-cracking: you must *FEEL* that some code (or that
|
||
|
||
some software behaviour) is not "genuine". Hope you believe me
|
||
|
||
and learn it before attempting this kind of cracks.
|
||
|
||
------------> How do I crack Firewalls?
|
||
|
||
Some suggestions have been given above, but teaching you how
|
||
|
||
to crack firewalls would take at least six complete tutorial
|
||
|
||
lessons for a relatively unimportant cracking sector, and you
|
||
|
||
would almost surely get snatched immediately, 'coz you would
|
||
|
||
believe you can crack it without knowing nothing at all. So, for
|
||
|
||
your sake, I'll teach you HOW TO LEARN IT, not HOW TO DO IT
|
||
|
||
(quite a fascinating difference): First Text, then the software
|
||
|
||
above. For text, start with Marcus Ranum's paper "Thinking about
|
||
|
||
Firewalls", available from ftp.tis.com in the file/pub/firewalls/firewalls.ps.Z
|
||
|
||
and do an archie search for newer literature.
|
||
|
||
Join the firewall discussion list sending a message to
|
||
|
||
majordomo@greatcircle.com, you'll get a message with
|
||
|
||
instructions, as usual, lurk only... never show yourself to the
|
||
|
||
others.
|
||
|
||
You can find for free on the web quite a lot of early
|
||
|
||
versions of proxy software. Study it, study it and then study it
|
||
|
||
again. The cracking efforts on your copies, and your machines,
|
||
|
||
before attempting anything serious, are MANDATORY if you do not
|
||
|
||
want to be immediately busted on the Internet. When you feel
|
||
|
||
ready to try serious cracking, you must OBLIGATORY start with a
|
||
|
||
small BBS which uses a firewall version you already studied very
|
||
|
||
well (sysops are not firewall administrators, and many of them
|
||
|
||
do not know nothing about the software they use). As soon as you
|
||
|
||
gain access to the bastion host, remember to subvert entirely the
|
||
|
||
firewall itself before entering the inner net.
|
||
|
||
If you feel ready and everything went well so far, if your zen-
|
||
|
||
cracking abilities are working well... then take a moment for
|
||
|
||
yourself... prepare yourself a good Martini-Wodka (you should
|
||
|
||
only use Moskovskaia), take a deep breath and by all means go
|
||
|
||
ahead! You will then be able to try your luck on the Cyberspace
|
||
|
||
and get quickly busted (if you did not follow my admonitions and
|
||
|
||
if you cannot zen-crack) or, may be, fish quite a lot of
|
||
|
||
jewels... :=)
|
||
|
||
-------------> INTERNET CRACKING: XINETD
|
||
|
||
[Xinetd] a freely available enhanced replacement for the
|
||
|
||
internet service daemon inetd, allows just those particular users
|
||
|
||
to have FTP or Telnet access, without opening up access to the
|
||
|
||
world. Xinetd can only protect the system from intrusion by
|
||
|
||
controlling INITIAL access to most system services and by logging
|
||
|
||
activities so that you can detect break-in attempts. However,
|
||
|
||
once a connection has been allowed to a service, xinetd is out
|
||
|
||
of the picture. It cannot protect against a server program that
|
||
|
||
has security problems internally. For example, the finger server
|
||
|
||
had a bug several years ago that allowed a particularly clever
|
||
|
||
person to overwrite part of its memory. This was used to gain
|
||
|
||
access to many systems. Even placing finger under the control of
|
||
|
||
xinetd wouldn't have helped.
|
||
|
||
Think of the secured firewall system as a fortress wall:
|
||
|
||
each service that is enabled for incoming connections can be
|
||
|
||
viewed as a door or window in the walls. Not all these doors have
|
||
|
||
secure and reliable locks. The more openings are available, the
|
||
|
||
more opportunities are open for us.
|
||
|
||
-------------> What xinetd does
|
||
|
||
Xinetd listens to all enabled service ports and permits only
|
||
|
||
those incoming connection request that meet authorization
|
||
|
||
criteria.
|
||
|
||
- Accept connections from only certain IP addresses
|
||
|
||
- Accept connections only from authorized users
|
||
|
||
- Reject connections outside of aithorized hours
|
||
|
||
- Log selected service when connections are accepted or
|
||
|
||
rejected, capturing following informations:
|
||
|
||
* Remote Host Address
|
||
|
||
* User ID of remote user (in some cases)
|
||
|
||
* Entry and Exit time
|
||
|
||
* Terminal type
|
||
|
||
Support login, shell, exec and finger
|
||
|
||
-------------> SERVICES TO CRACK &
|
||
|
||
UNWITTING INSIDE COMPLICES
|
||
|
||
In this order the easy services:
|
||
|
||
FTP TELNET LOGIN (rlogin) SHELL (rcmd) EXEC
|
||
|
||
In this order the more difficult ones:
|
||
|
||
MOUNT TFT FINGER NFS(Network File System)
|
||
|
||
DNS(Domain Name Service)
|
||
|
||
Remember that sendmail (SMTP), by default, accepts a message from
|
||
|
||
any incoming connection. The "sender" of such a message can
|
||
|
||
appear to have originated anywhere, therefore your claim of
|
||
|
||
identity will be accepted! Thus you can forge a message's
|
||
|
||
originator. Most of the recipients inside the protected
|
||
|
||
(firewalled) net will take your claim at face value and send you
|
||
|
||
(to the "return address" you provide) all the sensitive
|
||
|
||
information you need to crack the system. Finding unwitting
|
||
|
||
inside complices is most of the time pretty easy.
|
||
|
||
By far the best method, for entering xinetd, is to get the
|
||
|
||
real version from panos@cs.colorado.edu, modify the system files
|
||
|
||
in order to have some backdoors, and then distribute them to the
|
||
|
||
mirror servers on the WEB. Each time a new administrator will
|
||
|
||
download "your" version of xinetd, you'll have an easy access to
|
||
|
||
the "protected" system.
|
||
|
||
On the Nets, it's important to conceal your identity (they
|
||
|
||
will find you out pretty quickly if you do not). The best method
|
||
|
||
is to obtain the IP address of a legitimate workstation during
|
||
|
||
normal hours. Then, late at night, when the workstation is known
|
||
|
||
to be powered-off or disconnected from a dialup PPP link, a
|
||
|
||
different node on the network can be configured to use the
|
||
|
||
counterfeit IP address. To everyone on the network, it will
|
||
|
||
appear that the "legitimate" user is active. If you follow this
|
||
|
||
strategy, you may want to crack somehow more negligently... the
|
||
|
||
search for the cracker will go on -later- in the false confidence
|
||
|
||
that a sloppy novice (the legitimate user) is at work, this will
|
||
|
||
muddle the waters a little more.
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
|
||
already, but if they are really new you'll be given full credit,
|
||
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
|
||
them with your work, or that you actually did good work on them,
|
||
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
|
||
suggestions and critics on the whole crap I wrote are also
|
||
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
LESSON C (1) - How to crack, Cracking as an art
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[BARCODES] [INSTANT ACCESS]
|
||
|
||
--------------------------------------
|
||
|
||
[BARCODES]
|
||
First of all, let me stress the importance of cracking in
|
||
our everyday life. Cracking it's not just about software, it's
|
||
about information, about all patterns of life. To crack is to
|
||
refuse to be controlled and used by others, to crack is to be
|
||
free. But you must also be yourself free from petty conventions
|
||
in order to crack properly.
|
||
You must learn to discerne cracking possibilities all around
|
||
yourself, and believe me, the development of this ghastly society
|
||
brings every day new codes, protections and concealing
|
||
mechanismes.
|
||
All around us grows a world of codes and secret and not so
|
||
secret patterns. Codes that are at times so familiar and common
|
||
that we do not even notice them any more... and yet they are
|
||
there to fool us, and yet they offer marvellous cracking
|
||
possibilities.
|
||
Let's take as an striking example BARCODES... those little
|
||
lines that you see on any book you buy, on any bottle you get,
|
||
on any item around you... do you know how they work? If you do
|
||
not you may be excused, but you cannot be excused if you never
|
||
had the impulse to understand them... crackers are curious by
|
||
nature... heirs of an almost extinct race of researchers that has
|
||
nothing in common with the television slaves and the publicity
|
||
and trend zombies around us. Cracker should always be capable of
|
||
going beyond the obvious, seek knowledge where others do not see
|
||
and do not venture.
|
||
|
||
[BARCODE HISTORY]
|
||
Let's begin with a little history. Universal Product Code
|
||
(UPC) was adopted for commercial use by the grocery industry in
|
||
the USA. Among the advantages were a rapid, accurate and reliable
|
||
way of entering stock information into a computer and the
|
||
possibility to sack a lot of workers and to do more profit. The
|
||
early success led to the development of the European Article
|
||
Numbering System (EAN), a symbology similar to UPC, that is
|
||
widely used in Europe and in the rest of the World. I'll teach
|
||
you to crack this one, since I do not -fortunately- live in the
|
||
States. Keep in mind, anyway, that there are different barcode
|
||
symbologies, each with its own particular pattern of bars. The
|
||
UPC/EAN code used on retail products is an all-numeric code; so
|
||
is the Interleaved 2 of 5 Code. Code 39 includes upper case
|
||
letters, digits, and a few symbols. Code 128 includes every
|
||
printable and unprintable ASCII character code. The most new one
|
||
is a 2-D code. These are special rectangular codes, called
|
||
stacked barcodes or matrix codes. They can store considerably
|
||
more information than a standard barcode. They require special
|
||
readers which cost more than a standard scanner. The practical
|
||
limit for a standard barcode depends on a number of factors, but
|
||
20 to 25 characters is an approximate maximum. For applications
|
||
that need more data, matrix codes are used. For example, the next
|
||
time you receive a package from United Parcel Service look for
|
||
a small square label with a pattern of dots and a small bullseye
|
||
in the centre. This is a MaxiCode label, and it is used by UPS
|
||
for automatic destination sortition.
|
||
The manufacturer's ID number on the barcode uniquely
|
||
identifies products. These numbers are managed by the Uniform
|
||
Code Council in Dayton, Ohio for the States and Canada and by the
|
||
EAN authority (Internationale Article Numbering Association) in
|
||
Bruxelles, for Europe and the rest of the World. The
|
||
manufacturer's ID number accounts for some digits of the code,
|
||
which leaves other digits to be assigned in any way the producer
|
||
wants. He provides retail outlets with a list of his products and
|
||
their assigned codes so that they can be entered in the cash
|
||
register system. Many codes are NOT on the products and are added
|
||
by the supermarkets on the fly, using an internal code schema
|
||
that may be non standard. Now it's enough... let's crack.
|
||
BARCODES are the only thing an automated casher needs to see
|
||
on a product to calculate its price and automatically catalogate
|
||
the sold merchandise... imagine (just imagine it :=) coz it would
|
||
be extremely illegal to act in this way) somebody would fasten
|
||
an adhesive home-made codebar label direct on the top of the
|
||
supermarket/mall/retail store label, say on a bottle of Pomerol
|
||
(that's a very good but unfortunately very expensive french
|
||
wine).
|
||
The new label would mean for the casher something like
|
||
"cheap wine from Bordeaux, France, cost so and so, everything
|
||
it's OK, do not worry"... do you think that anybody would come
|
||
to the idea that there is something wrong with the label, with
|
||
the bottle or with you? I have been codebaring for years and had
|
||
only once a problem, coz my printer was running out of ink and
|
||
the scanner in the supermarket could not read it... so what? Act
|
||
uninterested, always wear jackets of the utmost quality, shetland
|
||
pullovers and beautiful expensive shoes... (all articles that you
|
||
may codebar too, by the way), in this society appearance and look
|
||
count much more than substance and knowledge... LET'S USE THIS
|
||
TO OUR ADVANTAGE! Nobody will ever come to the idea that you may
|
||
actually really know the working of the scheme... coz codebar is
|
||
pretty complicated and not exactly exceptionally public. On the
|
||
Web there are a lot information about it, but most of them are
|
||
useless, unless you know how to search most of the time you'll
|
||
find only sentences like this one:
|
||
"The calculated check digit is the twelfth and final
|
||
digit in the U.P.C.code. It is calculated based on a
|
||
specific algorithm, and is necessary to ensure that
|
||
the number is read or key-entered correctly."
|
||
|
||
But good +ORC will now explain you everything you need to crack:
|
||
|
||
[THE 13 BAR "CODES"]
|
||
Each barcode label has 13 values, from #0 to #12 (that's the EAN
|
||
code, the UPC american one has only 12, from #0 to #11).
|
||
#0 and #1 indicate the origin of the product.
|
||
#2 to #11 give the article code
|
||
#12 (the last and 13th one) is a checksum value, that
|
||
verifies the validity of all the other numbers.
|
||
How is it calculated? #12 is calculated in 4 steps
|
||
VALUE A: You sum odd position numbers (#0+#2+#4+#6+#8+#10)
|
||
VALUE B: You sum even position numbers and multiply by 3
|
||
((#1+#3+#5+#7+#9+#11)*3)
|
||
VALUE C: You sum value A and value B
|
||
VALUE D: You mod value C (you divide by 10 and only keep
|
||
the remaining units, a very widespread checking scheme as
|
||
you'll see in the software part of this lesson)
|
||
If the result is not zero, you subtract it from 10.
|
||
Now look at a barcode label, get some books or other barcoded
|
||
items and *watch* it...
|
||
Bar codes are supposed to have "quiet zones" on either side of
|
||
the symbol. Quiet zones are blank areas, free of any printing or
|
||
marks,typically 10 times the width of the narrowest bar or space
|
||
in the bar code. Failure to allow adequate space on either side
|
||
of the symbol for quiet zones can make it impossible to read the
|
||
bar code.
|
||
On the barcode there are two "borders", left and right, and a
|
||
"middle" longer line. These three lines are longer than the
|
||
others and are used to "regulate" the scanner to whatever
|
||
dimension has been used for the barcode.
|
||
#0 dwells left of the first (left) border and has a special
|
||
meaning, the other 12 numbers are written "inside" the code and
|
||
are divided in two "groups" by the middle bar.
|
||
Each value is coded through SEVEN bars: black=1 and White=0.
|
||
These form two couples of "optic" bars of different widths.
|
||
We come now to the "magic" part: In order to bluff the
|
||
simpletons, barcode uses three different SETS of characters to
|
||
represent the values 0-9. This should make it impossible for you
|
||
to understand what's going on, as usual, in this society, slaves
|
||
should not need to worry with the real functioning of things.
|
||
Here are the graphic codes of the three graphic sets:
|
||
|
||
CODE A CODE B (XOR C) CODE C (NOT A)
|
||
0: 0001101 (13) 0100111 (39) 1110010 (114)
|
||
1: 0011001 (25) 0110011 (51) 1100110 (102)
|
||
2: 0010011 (19) 0011011 (27) 1101100 (108)
|
||
3: 0111101 (61) 0100001 (33) 1000010 (066)
|
||
4: 0100011 (35) 0011101 (29) 1011100 (092)
|
||
5: 0110001 (49) 0111001 (57) 1001110 (078)
|
||
6: 0101111 (47) 0000101 (05) 1010000 (080)
|
||
7: 0111011 (59) 0010001 (17) 1000100 (068)
|
||
8: 0110111 (55) 0001001 (09) 1001000 (072)
|
||
9: 0001011 (11) 0010111 (23) 1110100 (116)
|
||
|
||
Borders: 101
|
||
Centre: 01010
|
||
|
||
- The C graphic set is a "NOT A" graphic set.
|
||
- The B graphic set is a "XOR C" graphic set.
|
||
- each value has two couples of bars with different widths
|
||
|
||
Now watch some labels yourself... see the difference between the
|
||
numbers left and the numbers right? The first "half" of the
|
||
barcode is coded using sets A and B, the second "half" using set
|
||
C. As if that were not enough, A and B are used inside the first
|
||
"half" in a combination that varies and depends from value #0,
|
||
following 10 different patterns:
|
||
#1 #2 #3 #4 #5 #6
|
||
0 A A A A A A
|
||
1 A A B A B B
|
||
2 A A B B A B
|
||
3 A A B B B A
|
||
4 A B A A B B
|
||
5 A B B A A B
|
||
6 A B B B A A
|
||
7 A B A B A B
|
||
8 A B A B B A
|
||
9 A B B A B A
|
||
|
||
"Ah! Stupid buyer will never understand why the same values gives
|
||
different bars! Nothing is as reliable as barcodes!" :=)
|
||
|
||
Let's take as example the codebar for Martini Dry:
|
||
BARCODE: 8 0 00570 00425 7
|
||
Let's see: we have a 8 0 0 = booze
|
||
Then a 000570 as ABABBA and a 004257 as C
|
||
"Even" sum: 8+0+5+0+0+2 = 15 (even sum)
|
||
Then a 0+0+7+0+4+5= 16 and 16 *3 = 48 (odd sum)
|
||
Then a 15+48=63
|
||
63 === 3
|
||
10 - 3 = 7 = checksum
|
||
Pattern = 8 = ABABBA CCCCCC
|
||
|
||
OK, one more example: Osborne Windows programming series Volume
|
||
2 General purpose API functions (always here on my table)...
|
||
BARCODE: 9 7 80078 81991 9
|
||
Let's see: we have a 9 7 8 = book
|
||
Then a 780078 as ABBABA and a 819919 as C
|
||
"Even" sum: 9+8+5+8+8+4 = 42 (even sum)
|
||
Then a 7+1+5+2+4+4= 23 and 23 * 3 = 69 (odd sum)
|
||
Then a 42+69=111
|
||
111 === 1
|
||
10 - 1 = 9 = checksum
|
||
Pattern = 9 = ABBABA
|
||
|
||
Well... what's the point of all this?
|
||
The point, my pupils, is that who DOES NOT KNOW is taken along
|
||
on a boat ride, who KNOWS and LEARNS can use his knowledge in
|
||
order to try to beat blue and black the loathsome consumistic
|
||
oligarchy where we are compelled to live. Try it out for
|
||
yourself... if you crack correctly and wisely your supermarket,
|
||
mall and library bills will be cut to almost zero.
|
||
Write a small program to print whichever codebar you fancy
|
||
(or whichever your mall uses) in whichever size on whichever sort
|
||
of label you (or better your targets) fancy... it's quickly done
|
||
with Visualbasic or Delphy... but you'll not find much on the Web
|
||
Alternatively you could also write, as I did long ago, a short
|
||
c program in dos, using a modified upper char set... and there
|
||
you are, have labels... see the world.
|
||
A small word of caution... crack only ONE item at time and
|
||
try it out first with the SAME label for the same product... i.e.
|
||
the correct code for that item, but on your own label. If it goes
|
||
through your program works good, if not, nobody will ever be able
|
||
to harm you. Anyway it never happens anything, never: the bar
|
||
code reading equipments have great tolerance, coz the scanners
|
||
must be able to recognize barcodes that have been printed on many
|
||
different medias. You should choose labels similar to the ones
|
||
effectively used only in order not to arise human suspects, coz
|
||
for all the scanner itself cares, your label could be pink with
|
||
green stripes and with orange hand-written, numbers. Mind you,
|
||
we are still just academically imagining hypothetical situations,
|
||
coz it would be extremely illegal to act in such an inconsiderate
|
||
manner.
|
||
CRACKING POWER! It's true for barcodes, for Telecom bills,
|
||
for Compuserve accounts, for Amexco cards, for banking cheques
|
||
(do you know what MICR is? Magnetic Ink Character Recognition...
|
||
the stylized little printing on the lower left of new cheques...
|
||
there is a whole cracking school working on it), for registration
|
||
numbers... you name it, they develope it, we crack it...
|
||
Begin with barcodes: it's easy, nice and pretty useful! Live
|
||
in opulence, with the dignity and affluence that should always
|
||
distinguish real crackers. Besides... you should see the
|
||
assortment of 'Pomerols' in my "Cave-a-vin" :=)
|
||
|
||
[INSTANT ACCESS]
|
||
The (c) Instant access routines are a commercial protection
|
||
scheme used to "unlock" complete commercial applications that
|
||
have been encrypted on CD-
|
||
ROMs which are distributed (mostly) through reviews.
|
||
This is an ideal cracking target: it's commercial software,
|
||
complete, uncrippled and of (relatively) prominent quality, that
|
||
you can get in tons for the price of a coke. Obviously this kind
|
||
of protection represents an ideal subject for our lessons. This
|
||
fairly intricate protection scheme has not yet been cracked by
|
||
anybody that I am aware of, anyway not publicly, therefore it's
|
||
an ideal candidate for a "strainer" to my university. I'll teach
|
||
you here how to crack it in three lessons, C.1, C.2 and C.3. I warn
|
||
you... it's a difficult cracking session, and this protection
|
||
represents quite an intellectual challenge. But if you are
|
||
seriously interested in our trade you will enjoy these lessons
|
||
more than anything else.
|
||
This cracking is intended as an "assignment" for my +HCU
|
||
"cracking university": you'll find inside lessons C.1 and C.2 a
|
||
relatively deep "introduction" to Instant access cracking. This
|
||
will teach you a lot anyway, and spare you hours of useless
|
||
roaming around, bringing you straight to the cracking point. But
|
||
I'll release the third part of this session, with the complete
|
||
solution (lesson C.3) on the Web only in october 1996, not a day
|
||
before. All the students that would like to apply to the Higher
|
||
Cracking University, opening on the web 01/01/1997, should work
|
||
in July, August and September (three months is more than enough
|
||
time) on this assignment. They should crack completely the
|
||
instant access scheme and send me their solutions, with a good
|
||
documentation of their cracking sessions, before 30/09/1996
|
||
(WATCH IT! You can crack this scheme in -at least- three
|
||
different paths, be careful and choose the *best* one. WATCH IT!
|
||
Some of the informations) in lesson C.1 and C.2 are slightly incorrect:
|
||
check it!).
|
||
There are four possibilities:
|
||
1) The candidate has not found the crack or his solution is
|
||
not enough documented or not enough viable... the candidate
|
||
is therefore not (yet) crack-able, he will not be admitted
|
||
to the +HCU 1997 curses, better luck in 1998;
|
||
2) The cracking solution proposed by the candidate is not as
|
||
good as mine (you'll judge for yourself in october) but it
|
||
works nevertheless... he'll be admitted at the 1997
|
||
courses;
|
||
3) The cracking solution of the candidate is more or less
|
||
equal to mine, he'll be admitted, personally monitored, and
|
||
he'll get all the material he needs to crack on higher
|
||
paths;
|
||
4) The cracking solution of the candidate is better than mine,
|
||
he'll be admitted, get all the material he wishes and asked
|
||
to teach us as well as study with us: "homines, dum docent,
|
||
discunt".
|
||
|
||
[Cracking Instant access]
|
||
The user that wants to "unlock" a software application
|
||
protected with (c) Instant Access must enter first of all a
|
||
REGISTRATION number string, which through a series of
|
||
mathematical manipulations gives birth to a special "product"
|
||
code. On the basis of this "product code" the user is asked to
|
||
phone the commercial protectors (and pay) in order to get a
|
||
special "unlock code" that will allow him to decrypt the relevant
|
||
software.
|
||
This kind of "passnumber" protection routines are widely
|
||
used for software unlocking, BBS access, server access, backdoor
|
||
opening and many other protection schemes. We have already seen
|
||
password cracks in different lessons of this tutorial (in
|
||
particular Lessons 3.1 and 3.2 for DOS and Lessons 8.1, 8.2 and
|
||
9.1 for WIN) albeit on a more simplistic scale: there it did
|
||
mostly not matter very much *HOW* you passed the protection: once
|
||
passed, you could have access to the application. This is not the
|
||
case with (c) Instant Access. Face it: it's a little boring, but
|
||
important that you learn how to defeat intricate protection
|
||
routines (you'll meet them often in the next years) and I believe
|
||
that the following example will give you a "feeling" for the
|
||
right cracking approach.
|
||
In this case we must not only "crack" this protection scheme
|
||
but also study it thoroughly in order to achieve our blessed
|
||
aims. This is a very good exercise: reverse disassembling will
|
||
teach you a lot of little tricks that you'll be able to use in
|
||
your other future cracking sessions.
|
||
Instant access (c) is a exceptionally widespread protection
|
||
scheme, and it should be relatively easy for you to gather some
|
||
encrypted software that has been protected with this method...
|
||
*DO IT QUICKLY!!* After the Web publishing of this lessons (I am
|
||
sending C.1 to 8 pages and 4 usenet groups on 25/06/1996) this
|
||
protection is obviously as dead as a Dodo. The "Accessors" guys
|
||
will have to conceive something smarter if they want to keep
|
||
selling "protections" to the lamer producers of "big" software.
|
||
BTW, if you are reading this and are working for some
|
||
commercial "protection" company, consider the possibility to
|
||
double cross your masters! Deliver me anonymously all the future
|
||
projects you are working on! That will amuse me, speed up the
|
||
advent of a true altruistic society and earn you the respect of
|
||
the better part of humanity.
|
||
As I said, many "huge" application are still protected with
|
||
this "Instant access" system. I have personally bought at least
|
||
7 or 8 "second hand" CD-ROMs packed full with Microsoft, Lotus,
|
||
Norton, Symantec, you name it, applications all "protected"
|
||
through this crap. The cost of this bunch of CD-ROMs was the
|
||
equivalent of a bottle of Dry Martini, maybe less. The same
|
||
software is sold, unlocked, to zombies and lusers for ludicrous
|
||
amounts of money.
|
||
Never buy CD-ROMs magazines when they appear! Be cool! Buy
|
||
them two or three months after the publishing date! Buy
|
||
"remainders" or "second hand" CD-ROM magazines "at kilo price"...
|
||
Come to think of it, never buy *anything* when it appears or when
|
||
some (paid) advertiser tells you to... remember that "trends",
|
||
"vogues", "fashions" and "modes" are only different names for the
|
||
whips that drill and chain the dull-witted slaves of this
|
||
loathsome society: "clever crackers consider cool, crack cheap,
|
||
cheat customary culture" (a rhetorical figure: an "Alliteration".
|
||
To defend yourself learn rhetoric... it's a more powerful and
|
||
more useful weapon than Kung-fu).
|
||
The "triple" password protection routine in (c) Instant
|
||
Access is very interesting from a cracker point of view. It's a
|
||
relatively complex scheme: I'll teach you to crack it in two
|
||
phases: First of all you must find the "allowed" registration
|
||
code, the one that "ignites" the "product code". We must crack
|
||
and understand this re_code first if we want to crack the rest.
|
||
Just for the records, I am cracking here (c) Action Instant
|
||
access version 1.0 (CD-ROM found on a old copy of "Personal
|
||
Computer World" of August 1994, packed full with encrypted Lotus,
|
||
Symantec, Claris and Wordperfect applications. Just to be sure
|
||
I crosschecked my results with another CD-ROM which also has
|
||
applications protected with (c) Instant Access: Paragon
|
||
Publishing's PC OFFICE: the protection scheme remains the same).
|
||
I am focusing for this lesson on the cracking of the specific
|
||
protection for the encrypted Symantec's Norton Utilities v.8.0.
|
||
Please refer to the previous lessons for the basic
|
||
techniques used in order to find the protection routine inside
|
||
our babe... for "low" cracking purposes you -basically- type a
|
||
number (in this case, where the input gets 10 numbers, we'll use
|
||
"1212-1212-12"), do your search inside the memory (s 30:0
|
||
lffffffff "your_string") and then set memory breakpoints on all
|
||
the relevant memory locations till winice pops (I know, I know,
|
||
buddies... there are more effective ways... but hold your mouth:
|
||
for now we'll keep them among us: let's make things a little
|
||
harder for the protectionists who read this... Besides: the old
|
||
approach works here flawlessly). After getting the Registration
|
||
window on screen the Winice standard procedure is:
|
||
:task ; how
|
||
:heap IABROWSE ; where & what
|
||
:hwnd IABROWSE ; get the Winhandle
|
||
:bpx [winhandle] WM_GETTEXT ; pinpoint code
|
||
:bpx GetProcAddress ; in case of funny routines
|
||
:dex 0 ds:dx ; let's see their name
|
||
:gdt ; sniff the selectors
|
||
:s 30:0 lffffffff "Your_input_string" ; search in 4 giga data
|
||
:bpr [all memory ranges for your string that are above 80000000]
|
||
and so on. (continued in lesson C.2)
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
tutorial are on the Web.
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
me back (via anon.penet.fi) with some tricks of the trade I may
|
||
not know that YOU discovered. Mostly I'll actually know them
|
||
already, but if they are really new you'll be given full credit,
|
||
and even if they are not, should I judge that you rediscovered them
|
||
with your work, or that you actually did good work on them,
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
suggestions and critics on the whole crap I wrote are also
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
LESSON C (2) - How to crack, Cracking as an art
|
||
|
||
---------------------------------------------------------------------------
|
||
|
||
[INSTANT ACCESS]
|
||
|
||
--------------------------------------
|
||
|
||
cracking Instant Access (2) - strainer for the +HCU
|
||
|
||
[SEE LESSON C.1 for the first part of this cracking session]
|
||
Here follow the relevant protection routines for the first
|
||
(The "Registration") number_code of Instant Access, with my
|
||
comments: you have to investigate a little the following code.
|
||
Later, when you'll crack on your own, try to recognize the
|
||
many routines that fiddle with input BEFORE the relevant (real
|
||
protection) one. In this case, for instance, a routine checks the
|
||
correctness of the numbers of your input:
|
||
|
||
This_loop_checks_that_numbers_are_numbers:
|
||
1B0F:2B00 C45E06 LES BX,[BP+06] ; set/reset pointer
|
||
1B0F:2B03 03DF ADD BX,DI
|
||
1B0F:2B05 268A07 MOV AL,ES:[BX] ; get number
|
||
1B0F:2B08 8846FD MOV [BP-03],AL ; store
|
||
1B0F:2B0B 807EFD30 CMP BYTE PTR [BP-03],30
|
||
1B0F:2B0F 7C06 JL 2B17 ; less than zero?
|
||
1B0F:2B11 807EFD39 CMP BYTE PTR [BP-03],39
|
||
1B0F:2B15 7E05 JLE 2B1C ; between 0 & 9?
|
||
1B0F:2B17 B80100 MOV AX,0001 ; no, set flag=1
|
||
1B0F:2B1A EB02 JMP 2B1E ; keep flag
|
||
1B0F:2B1C 33C0 XOR AX,AX ; flag=0
|
||
1B0F:2B1E 0BC0 OR AX,AX ; is it zero?
|
||
1B0F:2B20 7507 JNZ 2B29 ; flag NO jumps away
|
||
1B0F:2B22 8A46FD MOV AL,[BP-03] ; Ok, get number
|
||
1B0F:2B25 8842CC MOV [BP+SI-34],AL ; Ok, store number
|
||
1B0F:2B28 46 INC SI ; inc storespace
|
||
1B0F:2B29 47 INC DI ; inc counter
|
||
1B0F:2B2A C45E06 LES BX,[BP+06] ; reset pointer
|
||
1B0F:2B2D 03DF ADD BX,DI ; point next number
|
||
1B0F:2B2F 26803F00 CMP BYTE PTR ES:[BX],00 ; input end?
|
||
1B0F:2B33 75CB JNZ 2B00 ; no:loop next num
|
||
|
||
You now obviously understand that the "real" string is
|
||
stored inside memory location [BP+SI-34]... set a memory
|
||
breakpoint on this area to get the next block of code that
|
||
fiddles with the transformed input. Notice how this routine
|
||
"normalizes" the input, strips the "-" off and puts the 10
|
||
numbers together:
|
||
user input: 1 2 1 2 1 2 1 2 1 2 End
|
||
1E7F:92E2 31 32 31 32 31 32 31 32 31 32 00 45 AF 1F 70 9B
|
||
Stack ptr: 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||
Let's now look at the "real" protection routine: the one
|
||
that checks these numbers and throw you out if they are not
|
||
"sound". Please pay attention to the following block of code:
|
||
|
||
check_if_sum_other_9_numbers_=_remainder_of_the_third_number:
|
||
:4B79 8CD0 MOV AX,SS ; we'll work inside the stack...
|
||
:4B7B 90 NOP
|
||
:4B7C 45 INC BP
|
||
:4B7D 55 PUSH BP ; save real BP
|
||
:4B7E 8BEC MOV BP,SP ; BP = stackpointer
|
||
:4B80 1E PUSH DS ; save real Datasegment
|
||
:4B81 8ED8 MOV DS,AX ; Datasegment = stacksegment
|
||
:4B83 83EC04 SUB SP,+04
|
||
:4B86 C45E06 LES BX,[BP+06] ; BX points input_start
|
||
:4B89 268A07 MOV AL,ES:[BX] ; load first number
|
||
:4B8C 98 CBW ; care only for low
|
||
:4B8D C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4B90 50 PUSH AX ; save 1st number
|
||
:4B91 268A4701 MOV AL,ES:[BX+01] ; load 2nd number
|
||
:4B95 98 CBW ; only low
|
||
:4B96 8BD0 MOV DX,AX ; 2nd number in DX
|
||
:4B98 58 POP AX ; get 1st number
|
||
:4B99 03C2 ADD AX,DX ; sum with second
|
||
:4B9B C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4B9E 50 PUSH AX ; save sum
|
||
:4B9F 268A4707 MOV AL,ES:[BX+07] ; load 8th number
|
||
:4BA3 98 CBW ; only low
|
||
:4BA4 8BD0 MOV DX,AX ; 8th number in DX
|
||
:4BA6 58 POP AX ; old sum is back
|
||
:4BA7 03C2 ADD AX,DX ; sum 1+2+8
|
||
:4BA9 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BAC 50 PUSH AX ; save sum
|
||
:4BAD 268A4703 MOV AL,ES:[BX+03] ; load 4rd number
|
||
:4BB1 98 CBW ; only low
|
||
:4BB2 8BD0 MOV DX,AX ; #4 in DX
|
||
:4BB4 58 POP AX ; sum is back
|
||
:4BB5 03C2 ADD AX,DX ; sum 1+2+8+4
|
||
:4BB7 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BBA 50 PUSH AX ; save sum
|
||
:4BBB 268A4704 MOV AL,ES:[BX+04] ; load 5th number
|
||
:4BBF 98 CBW ; only low
|
||
:4BC0 8BD0 MOV DX,AX ; #5 in DX
|
||
:4BC2 58 POP AX ; sum is back
|
||
:4BC3 03C2 ADD AX,DX ; 1+2+8+4+5
|
||
:4BC5 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BC8 50 PUSH AX ; save sum
|
||
:4BC9 268A4705 MOV AL,ES:[BX+05] ; load 6th number
|
||
:4BCD 98 CBW ; only low
|
||
:4BCE 8BD0 MOV DX,AX ; #6 in DX
|
||
:4BD0 58 POP AX ; sum is back
|
||
:4BD1 03C2 ADD AX,DX ; 1+2+8+4+5+6
|
||
:4BD3 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BD6 50 PUSH AX ; save sum
|
||
:4BD7 268A4706 MOV AL,ES:[BX+06] ; load 7th number
|
||
:4BDB 98 CBW ; only low
|
||
:4BDC 8BD0 MOV DX,AX ; #7 in DX
|
||
:4BDE 58 POP AX ; sum is back
|
||
:4BDF 03C2 ADD AX,DX ; 1+2+8+4+5+6+7
|
||
:4BE1 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BE4 50 PUSH AX ; save sum
|
||
:4BE5 268A4708 MOV AL,ES:[BX+08] ; load 9th number
|
||
:4BE9 98 CBW ; only low
|
||
:4BEA 8BD0 MOV DX,AX ; #9 in DX
|
||
:4BEC 58 POP AX ; sum is back
|
||
:4BED 03C2 ADD AX,DX ; 1+2+8+4+5+6+7+9
|
||
:4BEF C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4BF2 50 PUSH AX ; save sum
|
||
:4BF3 268A4709 MOV AL,ES:[BX+09] ; load 10th #
|
||
:4BF7 98 CBW ; only low
|
||
:4BF8 8BD0 MOV DX,AX ; #10 in DX
|
||
:4BFA 58 POP AX ; sum is back
|
||
:4BFB 03C2 ADD AX,DX ; 1+2+8+4+5+6+7+9+10
|
||
:4BFD 0550FE ADD AX,FE50 ; clean sum to 0-51
|
||
:4C00 BB0A00 MOV BX,000A ; BX holds 10
|
||
:4C03 99 CWD ; only AL
|
||
:4C04 F7FB IDIV BX ; remainder in DX
|
||
:4C06 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4C09 268A4702 MOV AL,ES:[BX+02] ; load now # 3
|
||
:4C0D 98 CBW ; only low
|
||
:4C0E 05D0FF ADD AX,FFD0 ; clean # 3 to 0-9
|
||
:4C11 3BD0 CMP DX,AX ; remainder = pampered #3?
|
||
:4C13 7407 JZ 4C1C ; yes, go on good guy
|
||
:4C15 33D2 XOR DX,DX ; no! beggar off! Zero DX
|
||
:4C17 33C0 XOR AX,AX ; and FLAG_AX = FALSE
|
||
:4C19 E91701 JMP 4D33 ; go to EXIT
|
||
let's_go_on_if_first_check_passed:
|
||
:4C1C C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4C1F 268A4701 MOV AL,ES:[BX+01] ; now load #2 anew
|
||
:4C23 98 CBW ; only low
|
||
:4C24 05D7FF ADD AX,FFD7 ; pamper adding +3
|
||
:4C27 A38D5E MOV [5E8D],AX ; save SEC_+3
|
||
:4C2A 3D0900 CMP AX,0009 ; was it < 9? (no A-F)
|
||
:4C2D 7E05 JLE 4C34 ; ok, no 0xletter
|
||
:4C2F 832E8D5E0A SUB WORD PTR [5E8D],+0A ; 0-5 if A-F
|
||
:4C34 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4C37 268A07 MOV AL,ES:[BX] ; load 1st input number
|
||
:4C3A 98 CBW ; only low
|
||
:4C3B 05C9FF ADD AX,FFC9 ; pamper adding +7
|
||
:4C3E A38F5E MOV [5E8F],AX ; save it in FIR_+7
|
||
:4C41 0BC0 OR AX,AX ; if #1 > 7
|
||
:4C43 7D05 JGE 4C4A ; no need to add 0xA
|
||
:4C45 83068F5E0A ADD WORD PTR [5E8F],+0A ; FIR_+7 + 0xA
|
||
now_we_have_the_sliders_let's_prepare_for_loop:
|
||
:4C4A C45E0E LES BX,[BP+0E] ; Set pointer to E
|
||
:4C4D 26C747020000 MOV WORD PTR ES:[BX+02],0000 ; 0 flag
|
||
:4C53 26C7070000 MOV WORD PTR ES:[BX],0000 ; 0 flag
|
||
:4C58 C706975E0900 MOV WORD PTR [5E97],0009 ; counter=9
|
||
:4C5E E99500 JMP 4CF6 ; Jmp check_counter
|
||
loop_8_times:
|
||
:4C61 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4C64 031E975E ADD BX,[5E97] ; add running counter
|
||
:4C68 268A07 MOV AL,ES:[BX] ; load # counter+1
|
||
:4C6B 98 CBW ; only low
|
||
:4C6C 50 PUSH AX ; save 10th number
|
||
:4C6D A18D5E MOV AX,[5E8D] ; ld SEC_+3 down_slider
|
||
:4C70 BA0A00 MOV DX,000A ; BX holds 0xA
|
||
:4C73 F7EA IMUL DX ; SEC_+3 * 0xA
|
||
:4C75 03068F5E ADD AX,[5E8F] ; plus FIR_+7 up_slider
|
||
:4C79 BAA71E MOV DX,1EA7 ; fixed segment
|
||
:4C7C 8BD8 MOV BX,AX ; BX = Lkup_val=(SEC_+3*10+FIR_+7)
|
||
:4C7E 8EC2 MOV ES,DX ; ES = 1EA7
|
||
:4C80 268A870000 MOV AL,ES:[BX+0000] ; ld 1EA7:[Lkup_val]
|
||
:4C85 98 CBW ; only low: KEY_PAR
|
||
:4C86 8BD0 MOV DX,AX ; save KEY_PAR in DX
|
||
:4C88 58 POP AX ; repops 10th number
|
||
:4C89 03C2 ADD AX,DX ; RE_SULT=KEY_PAR+#10
|
||
:4C8B 05D0FF ADD AX,FFD0 ; polish RE_SULT
|
||
:4C8E 99 CWD ; only low: RE_SULT
|
||
:4C8F 8956FC MOV [BP-04],DX ; save here KEY_PAR [9548]
|
||
:4C92 8946FA MOV [BP-06],AX ; save here RE_SULT [9546]
|
||
:4C95 0BD2 OR DX,DX ; KEY_PAR < 0?
|
||
:4C97 7C0F JL 4CA8 ; yes: KEY_PAR < 0
|
||
:4C99 7F05 JG 4CA0 ; no: KEY_PAR > 0
|
||
:4C9B 3D0900 CMP AX,0009 ; KEY_PAR = 0
|
||
:4C9E 7608 JBE 4CA8 ; no pampering if RE_SULT < 9
|
||
:4CA0 836EFA0A SUB WORD PTR [BP-06],+0A ; else pamper
|
||
:4CA4 835EFC00 SBB WORD PTR [BP-04],+00 ; and SBB [9548]
|
||
:4CA8 C45E0E LES BX,[BP+0E] ; reset pointer to E
|
||
:4CAB 268B4F02 MOV CX,ES:[BX+02] ; charge CX [958C]
|
||
:4CAF 268B1F MOV BX,ES:[BX] ; charge BX slider [958A]
|
||
:4CB2 33D2 XOR DX,DX ; clear DX to zero
|
||
:4CB4 B80A00 MOV AX,000A ; 10 in AX
|
||
:4CB7 9A930D2720 CALL 2027:0D93 ; call following RO_routine
|
||
|
||
This is the only routine called from our protection, inside the
|
||
loop (therefore 8 times), disassembly from WCB. Examining this
|
||
code please remember that we entered here with following
|
||
configuration: DX=0, AX=0xA, CX=[958C] and BX=[958A]...
|
||
1.0D93 56 push si ; save si
|
||
1.0D94 96 xchg ax, si ; ax=si, si=0xA
|
||
1.0D95 92 xchg ax, dx ; dx=0xA ax=dx
|
||
1.0D96 85C0 test ax, ax ; TEST this zero
|
||
1.0D98 7402 je 0D9C ; zero only 1st time
|
||
1.0D9A F7E3 mul bx ; BX slider! 0/9/5E/3B2...
|
||
1.0D9C >E305 jcxz 0DA3 ; cx=0? don't multiply!
|
||
1.0D9E 91 xchg ax, cx ; cx !=0? cx = ax & ax = cx
|
||
1.0D9F F7E6 mul si ; ax*0xA in ax
|
||
1.0DA1 03C1 add ax, cx ; ax= ax*0xA+cx = M_ULT
|
||
1.0DA3 >96 xchg ax, si ; ax=0xA; si evtl. holds M_ULT
|
||
1.0DA4 F7E3 mul bx ; ax= bx*0xA
|
||
1.0DA6 03D6 add dx, si ; dx= dx_add
|
||
1.0DA8 5E pop si ; restore si
|
||
1.0DA9 CB retf ; back to caller with two
|
||
parameters: DX and AX
|
||
Back_to_main_protection_loop_from_RO_routine:
|
||
:4CBC C45E0E LES BX,[BP+0E] ; reset pointer
|
||
:4CBF 26895702 MOV ES:[BX+02],DX ; save R_DX par [958C]
|
||
:4CC3 268907 MOV ES:[BX],AX ; save R_AX par [958A]
|
||
:4CC6 0346FA ADD AX,[BP-06] ; add to AX RE_SULT [9546]
|
||
:4CC9 1356FC ADC DX,[BP-04] ; add to DX KEY_PAR [9548]
|
||
:4CCC C45E0E LES BX,[BP+0E] ; reset pointer
|
||
:4CCF 26895702 MOV ES:[BX+02],DX ; save R_DX+KEY_PAR [958C]
|
||
:4CD3 268907 MOV ES:[BX],AX ; save R_AX+RE_SULT [958A]
|
||
:4CD6 FF0E8D5E DEC WORD PTR [5E8D] ; down_slide SEC_+3
|
||
:4CDA 7D05 JGE 4CE1 ; no need to add
|
||
:4CDC 83068D5E0A ADD WORD PTR [5E8D],+0A ; pamper adding 10
|
||
:4CE1 FF068F5E INC WORD PTR [5E8F] ; up_slide FIR_+7
|
||
:4CE5 A18F5E MOV AX,[5E8F] ; save upslided FIR_+7 in AX
|
||
:4CE8 3D0900 CMP AX,0009 ; is it over 9?
|
||
:4CEB 7E05 JLE 4CF2 ; no, go on
|
||
:4CED 832E8F5E0A SUB WORD PTR [5E8F],+0A ; yes, pamper -10
|
||
:4CF2 FF0E975E DEC WORD PTR [5E97] ; decrease loop counter
|
||
check_loop_counter:
|
||
:4CF6 833E975E03 CMP WORD PTR [5E97],+03 ; counter = 3?
|
||
:4CFB 7C03 JL 4D00 ; finish if counter under 3
|
||
:4CFD E961FF JMP 4C61 ; not yet, loop_next_count
|
||
loop_is_ended:
|
||
:4D00 C45E06 LES BX,[BP+06] ; reset pointer to input
|
||
:4D03 268A4701 MOV AL,ES:[BX+01] ; load 2nd number (2)
|
||
:4D07 98 CBW ; only low
|
||
:4D08 05D0FF ADD AX,FFD0 ; clean it
|
||
:4D0B BA0A00 MOV DX,000A ; DX = 10
|
||
:4D0E F7EA IMUL DX ; AX = SEC_*10 = 14
|
||
:4D10 C45E06 LES BX,[BP+06] ; reset pointer
|
||
:4D13 50 PUSH AX ; save SEC_*10
|
||
:4D14 268A07 MOV AL,ES:[BX] ; load 1st number (1)
|
||
:4D17 98 CBW ; only low
|
||
:4D18 8BD0 MOV DX,AX ; save in DX
|
||
:4D1A 58 POP AX ; get SEC_*10
|
||
:4D1B 03C2 ADD AX,DX ; sum SEC_*10+1st number
|
||
:4D1D 05D0FF ADD AX,FFD0 ; clean it
|
||
:4D20 99 CWD ; only low
|
||
:4D21 C45E0A LES BX,[BP+0A] ; get pointer to [9582]
|
||
:4D24 26895702 MOV ES:[BX+02],DX ; save 1st (1) in [9584]
|
||
:4D28 268907 MOV ES:[BX],AX ; save FINAL_SUM (15) [9582]
|
||
:4D2B 33D2 XOR DX,DX ; DX = 0
|
||
:4D2D B80100 MOV AX,0001 ; FLAG TRUE !
|
||
:4D30 E9E6FE JMP 4C19 ; OK, you_are_a_nice_guy
|
||
EXIT:
|
||
:4D33 59 POP CX ; pop everything and
|
||
:4D34 59 POP CX ; return with flag
|
||
:4D35 1F POP DS ; AX=TRUE if RegNum OK
|
||
:4D36 5D POP BP ; with 1st # in [9584]
|
||
:4D37 4D DEC BP ; with FINAL_SUM in [9582]
|
||
:4D38 CB RETF
|
||
|
||
Let's translate the preceding code: first of all the pointers:
|
||
At line :4B86 we have the first of a long list of stack ptrs:
|
||
LES BX,[BP+06]
|
||
This stack pointer points to the beginning of the input string,
|
||
which, once polished from the "-", has now a length of 10 bytes,
|
||
concluded by a 00 fence. At the beginning, before the main loop,
|
||
9 out of our 10 numbers are added, all but the third one.
|
||
Notice that protection has jumped # 3 (and added # 8 out of the
|
||
line). The rest is straightforward. Now, at line :4BFD we have
|
||
our first "cleaning" instruction. You see: the numbers are
|
||
hexadecimal represented by the codes 0x30 to 0x39. If you add
|
||
FE50 to the minimum sum you can get adding 9 numbers (0x30*9 =
|
||
0x160) You get 0. The maximum you could have adding 9 numbers,
|
||
on the contrary is (0x39*9=0x201), which, added to FE50 gives
|
||
0x51. So we'll have a "magic" number between 0x0 and 0x51 instead
|
||
of a number between 0x160 and 0x201. Protection pampers this
|
||
result, and retains only the last ciffer: 0-9. Then protection
|
||
divides this number through 0xA, and what happens? DX get's the
|
||
REMAINDER of it.
|
||
If we sum the hexcodes of our (1212-1212-12) we get 0x1BE (we
|
||
sum only 9 out of then numbers: the third "1" -i.e. "31"- does
|
||
not comes into our count); 0x1BE, cleaned and pampered gives E.
|
||
Therefore (0xE/0xA = 1) We get 1 with a remainder of 4.
|
||
You may observe that of all possible answers, only sums
|
||
finishing with A, B, C, D, E or F give 1 (and rem=0,1,2,3,4 or
|
||
5). Sums finishing 0 1 2 3 4 5 6 7 8 or 9 give 0 as result and
|
||
themselves as reminder. The chance of getting a 0,1,2,3 or 4 are
|
||
therefore bigger as the chance of getting a 5, 6, 7, 8 or 9. We
|
||
are just observing... we do not know yet if this should play a
|
||
role or not.
|
||
Now this remainder is compared at :4C11 with the third number
|
||
polished from 0x30-0x39 to 0-9. This is the only protection check
|
||
for the registration number input: If your third number does not
|
||
match with the remainder of the sum of all the 9 others numbers
|
||
of your input you are immediately thrown out with FLAG AX=FALSE
|
||
(i.e. zero).
|
||
To crack the protection you now have to MODIFY your input string
|
||
accordingly. Our new input string will from now on be "1242-1212-
|
||
12": we have changed our third number (originally a "2") to a "4"
|
||
to get through this first strainer in the correct way. Only now
|
||
protection starts its mathematical part (We do not know yet why
|
||
it does it... in order to seed the random product number? To
|
||
provide a check for the registration number you'll input at the
|
||
end? We'll see).
|
||
- Protection saves the second number of your input (cleaned
|
||
with FFD7) in SEC_+3 [5E8D], pampering it if it is bigger
|
||
than 9 (i.e. if it is 0xA-0xF). Here you'll have therefore
|
||
following correspondence: 0=7 1=8 2=9 3=0 4=1 5=2 6=3 7=4
|
||
8=5 9=6. The second number of your input has got added +3.
|
||
This is value SEC_+3. In (lengthy) C it would look like
|
||
this:
|
||
If (RegString(2)is lower than 7) RegString(2) = RegString(2)+3
|
||
Else Regstring(2) = ((RegString(2)-10)+3)
|
||
- Protection saves your first number in FIR_+7 [5E8F] with a
|
||
different cleaning parameter (FFC9). The next pampering
|
||
adds 0xA if it was not 7/8/9 therefore you have here
|
||
following correspondence 7=0 8=1 9=2 0=3 1=4 2=5 3=6 4=7
|
||
5=8 6=9). This is value FIR_+7. In (lengthy) C it would
|
||
look like this:
|
||
If (RegString(1) is lower than 3) RegString(1) = RegString(1)+7
|
||
Else Regstring(1) = ((RegString(1)-10)+7)
|
||
So protection has "transformed" and stored in [5E8D] and [5E8F]
|
||
the two numbers 1 and 2. In our RegString: 1242-1212-12 the first
|
||
two numbers "12" are now stored as "94". These will be used as
|
||
"slider" parameters inside the main loop, as you will see.
|
||
Only now does protection begin its main loop, starting from the
|
||
LAST number, because the counter has been set to 9 (i.e. the
|
||
tenth number of RegString). The loop, as you'll see, handles only
|
||
the numbers from 10 to 3: it's an 8-times loop that ends without
|
||
handling the first and second number. What happens in this
|
||
loop?... Well, quite a lot: Protection begins the loop loading
|
||
the number (counter+1) from the RegString. Protection then loads
|
||
the SEC_+3 down_slider parameter (which began its life as second
|
||
number "transformed"), multiplies it with 0xA and then adds the
|
||
up_slider parameter FIR_+7 (at the beginning it was the first
|
||
number transformed).
|
||
This sum is used as "lookup pointer" to find a parameter
|
||
inside a table of parameters in memory, which are all numbers
|
||
between 0 and 9. Let's call this value Lkup_val.
|
||
Protection looks for data in 1EA7:[Lkup_val]. In our case (we
|
||
entered 1242-1212-12, therefore the first SEC_+3 value is 9 and
|
||
the first FIR_+7 value is 4): [Lkup_val] = 9*0xA+4; 0x5A+4 =
|
||
0x5E. At line :4C80 therefore AL would load the byte at 1EA7:005E
|
||
(let's call it KEY_PAR), which now would be ADDED to the #
|
||
counter+1 of this loop. In our case KEY_PAR at 1EA7:005E it's a
|
||
"7" and is added to the pampered 0x32=2, giving 9.
|
||
Let's establish first of all which KEY_PAR can possibly get
|
||
fetched: the maximum is 0x63 and the minimum is 0x0. The possible
|
||
KEY_PARs do therefore dwell in memory between 1EA7: and
|
||
1EA7:0063. Let's have a look at the relative table in memory,
|
||
where these KEY_PARs are stored ("our" first 0x5Eth byte is
|
||
underlined):
|
||
1EA7:0000 01 03 03 01 09 02 03 00-09 00 04 03 08 07 04 04
|
||
1EA7:0010 05 02 09 00 02 04 01 05-06 06 03 02 00 08 05 06
|
||
1EA7:0020 08 09 05 00 04 06 07 07-02 00 08 00 06 02 04 07
|
||
1EA7:0030 04 04 09 05 09 06 00 06-08 07 00 03 05 09 00 08
|
||
1EA7:0040 03 07 07 06 08 09 01 05-07 04 06 01 04 02 07 01
|
||
1EA7:0050 03 01 08 01 05 03 03 01-02 08 02 01 06 05 07 02
|
||
1EA7:0060 05 09 09 08 02 09 03 00-00 04 05 01 01 03 08 06
|
||
1EA7:0070 01 01 09 00 02 05 05 05-01 07 01 05 08 07 01 09
|
||
1EA7:0080 08 07 07 04 04 08 03 00-06 01 09 08 08 04 09 09
|
||
1EA7:0090 00 07 05 02 03 01 03 08-06 05 07 06 03 07 06 07
|
||
1EA7:00A0 04 02 02 05 02 04 06 02-06 09 09 01 05 02 03 04
|
||
1EA7:00B0 04 00 03 05 00 03 08 07-06 04 08 08 02 00 03 06
|
||
1EA7:00C0 09 00 00 06 09 04 07 02-00 01 01 01 01 00 01 FF
|
||
1EA7:00D0 00 FF FF FF FF 00 FF 01-00 00 00 00 00 00 00 00
|
||
|
||
An interesting table, where all the correspondences are
|
||
between 0 and 9... are we getting some "secret" number here? But,
|
||
hey, look there... funny, isn't it? Instead of only 0-0x63 bytes
|
||
we have roughly the DOUBLE here: 0-0xC8 bytes (the 01 sequence
|
||
starting at CA "feels" like a fence). We'll see later how
|
||
important this is. At the moment you should only "perceive" that
|
||
something must be going on with a table that's two time what she
|
||
should be.
|
||
As I said the result of KEY_PAR + input number is polished
|
||
(with a FFDO) and pampered (subtracting, if necessary, 0xA).
|
||
Therefore the result will be the (counter+1) input number +
|
||
KEY_PAR (let's call it RE_SULT], in our case, (at the beginning
|
||
of the loop) a 9. Now (DX=0 because of the CWD instruction) DX
|
||
will be saved in [9548] and RE_SULT in [9546].
|
||
Now Protection prepares for the RO_routine: resets its pointer
|
||
and charges CX and BX from [958C] and from [958A] respectively,
|
||
charges AX with 0xA and sets DX to zero.
|
||
The routine performs various operations on AX and DX and saves
|
||
the results in the above mentioned locations [958A] and [958C].
|
||
Now KEY_PAR and RE_SULT are added respectively to the DX and AX
|
||
value we got back from the RO_routine call, and saved once more
|
||
in the last two locations: AX+RE_SULT in [958A] and DX+KEY_PAR
|
||
in [958C]
|
||
Now the value in SEC_+3 is diminished by 1 (if it was 9 it's now
|
||
8, if it was zero it will be pampered to 9). It's a "slider"
|
||
parameter (in this case a down_slider), typically used in
|
||
relatively complicated protections to give a "random" impression
|
||
to the casual observer. The value in FIR_+7, on the contrary, is
|
||
augmented by one, from 4 to 5... up_sliding also.
|
||
Protection now handles the next number of your input for the
|
||
loop. In our case this loop uses following protection
|
||
configuration with our "sliding" parameters:
|
||
Input # pamp_2nd pamp_1st Lookup value KEY_PAR # RE_SULT
|
||
# 10 = 2, SEC_+3= 9, FIR_+7= 4, Lkup_val = 0x5E, KEY=7 +2 = 9
|
||
# 9 = 1, SEC_+3= 8, FIR_+7= 5, Lkup_val = 0x55, KEY=3 +1 = 4
|
||
# 8 = 2, SEC_+3= 7, FIR_+7= 6, Lkup_val = 0x4C, KEY=4 +2 = 6
|
||
# 7 = 1, SEC_+3= 6, FIR_+7= 7, Lkup_val = 0x43, KEY=7 +1 = 7
|
||
# 6 = 2, SEC_+3= 5, FIR_+7= 8, Lkup_val = 0x3A, KEY=0 +2 = 2
|
||
# 5 = 1, SEC_+3= 4, FIR_+7= 9, Lkup_val = 0x31, KEY=4 +1 = 5
|
||
# 4 = 2, SEC_+3= 3, FIR_+7= 0, Lkup_val = 0x1E, KEY=5 +2 = 7
|
||
# 3 = 4, SEC_+3= 2, FIR_+7= 1, Lkup_val = 0x15, KEY=2 +4 = 5
|
||
Notice how our "regular" input 21212124 has given an "irregular"
|
||
94672575.
|
||
You may legitimately ask yourself what should all this mean:
|
||
what are these RE_SULTs used for? Well they are used to slide
|
||
another parameter: this one inside the called routine... this is
|
||
what happens to AX and DX inside the routine, and the lines after
|
||
the called routine:
|
||
:4CBF 26895702 MOV ES:[BX+02],DX ; save R_DX par [958C]
|
||
:4CC3 268907 MOV ES:[BX],AX ; save R_AX par [958A]
|
||
:4CC6 0346FA ADD AX,[BP-06] ; add to AX RE_SULT [9546]
|
||
:4CC9 1356FC ADC DX,[BP-04] ; add to DX KEY_PAR [9548]
|
||
:4CCC C45E0E LES BX,[BP+0E] ; reset pointer to E
|
||
:4CCF 26895702 MOV ES:[BX+02],DX ; save R_DX+KEY_PAR [958C]
|
||
:4CD3 268907 MOV ES:[BX],AX ; save R_AX+RE_SULT [958A]
|
||
|
||
:4CC6 :4CC9 :4CCF Odd_DX :4CD3 slider_sum
|
||
RE_SULT [958A] [958C] [958C] [958A]
|
||
0 0 0 0 0
|
||
9 5A 0 0 9
|
||
4 3AC 0 0 5E
|
||
6 24F4 0 0 3B2
|
||
7 71CE 1 1 24FB
|
||
2 7220 4 E 71D0
|
||
5 7572 4 90 7225
|
||
7579
|
||
|
||
Now the loops ends, having handled the input numbers from tenth
|
||
to third. Protection loads the second number and multiplies it
|
||
by 10 (let's call this result SEC_*10), in our case 2*0xA=14.
|
||
Protection loads the first number and adds it to the
|
||
multiplication, in our case 1+0x14=0x15 (FINAL_SUM].
|
||
Now everything will be added to FFDO to "clean" it.
|
||
Pointer will now be set to the end of the input number.
|
||
DX, zeroed by CDW, will be saved as parameter in [9584] and the
|
||
cleaned and pampered sum will be saved in [9582].
|
||
FLAG is set to true and this routine is finished! No parameter
|
||
are passed and the only interesting thing is what actually
|
||
happens in the locations [9582], [9584], [958A] and [958C], i.e.:
|
||
FINAL_SUM, 0, slider_sum, odd_dx.
|
||
In the next lesson we'll crack everything, but I'll give you
|
||
already some hints here, in case you would like to go ahead on
|
||
your own: we'll see how the scheme used for the third (the
|
||
registration) number show analogies and differences with the
|
||
scheme we have studied (and cracked) here for the first number.
|
||
Our 3434-3434-3434-3434-34 input string for the registration
|
||
number will be transformed in the magic string
|
||
141593384841547431, but this will not work because the "magic"
|
||
12th number: "1" will not correspond to the remainder calculated
|
||
inside this check through the previous locations of the other
|
||
checks.
|
||
Here the things are more complicated because every little
|
||
change in your input string transforms COMPLETELY the "magic"
|
||
string... therefore in order to pass the strainer you'll have to
|
||
change 3434-3434-3434-3434-34 in (for instance) 7434-3434-3434-
|
||
3434-96. The "magic" string 219702960974498056 that this
|
||
registration input gives will go through the protection strainer.
|
||
Only then we'll be able to step over and finally crack the whole
|
||
protection... it's a pretty complicated one as I said. Now crack
|
||
it pupils... you have three months time. From this crack depends
|
||
your admission to the Uni, there will be no other admission text
|
||
till summer 1997 (it's a hell of work to prepare this crap)...
|
||
work well.
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
tutorial are on the Web.
|
||
You 'll obtain the missing lessons IF AND ONLY IF you mail
|
||
me back (via anon.penet.fi) some tricks of the trade I may not
|
||
know but YOU've discovered. I'll probably know most of them
|
||
already, but if they are really new you'll be given full credit,
|
||
and even if they are not, should I judge that you "rediscovered"
|
||
them with your work, or that you actually did good work on them,
|
||
I'll send you the remaining lessons nevertheless. Your
|
||
suggestions and critics on the whole crap I wrote are also
|
||
welcomed.
|
||
|
||
E-mail +ORC
|
||
|
||
+ORC an526164@anon.penet.fi
|