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
|