1513 lines
58 KiB
Plaintext
1513 lines
58 KiB
Plaintext
![]() |
--------------------------------------------------------
|
|||
|
LESSON C (3) - How to crack Windows, cracking as anArt:
|
|||
|
Web trends, Instant Access (end) and the proximity trick
|
|||
|
--------------------------------------------------------
|
|||
|
I. [WEB TRENDS]
|
|||
|
It's really amazing: I began this tutorial in february 1996...
|
|||
|
the year is not yet finished but many things have already
|
|||
|
changed, and how! First of all the Web proves to be even more
|
|||
|
significant that I would ever have thought: it's -de facto- an
|
|||
|
ANTI-ESTABLISHMENT and ANTI-CONSUME "permanent" tool... more than
|
|||
|
that: it's an EVOLVING and SHARP tool!
|
|||
|
I do not know if you will agree with me, but it seems to me that
|
|||
|
it is now NOT ANY MORE NECESSARY to buy any of the following
|
|||
|
things (and this is a quite incomplete list:
|
|||
|
|
|||
|
1) Newspapers Are almost all on the Web for free
|
|||
|
2) Magazines Are almost all on the Web for free
|
|||
|
3) Software All on the Web for free
|
|||
|
4) Books on the Web (even the *images* inside the
|
|||
|
books you would have bought are somewhere)
|
|||
|
5) Post_stamps e-mail is free and ubiquitous
|
|||
|
6) Hard_disks free megabytes everywhere on the Web (for
|
|||
|
pages and/or software, quite a lot of
|
|||
|
offering (at the moment, middle november
|
|||
|
1996 you can get -for free- about 80
|
|||
|
megabytes for each email address you have).
|
|||
|
Should you do not deem this space enough,
|
|||
|
you may multiply them -ad libitum- using one
|
|||
|
of the many free "alias e-mail addresses"
|
|||
|
generators or, as a brilliant scholar of
|
|||
|
mine (re)discovered, you may easily "caper"
|
|||
|
(the passwords of) pages established by the
|
|||
|
lusers.
|
|||
|
|
|||
|
I assure you that I used to spend quite a lot of money
|
|||
|
buying all the preceding items. The case of the CD-ROM magazines
|
|||
|
(and of software in general) seems to me to be the most relevant.
|
|||
|
In my earlier lessons I advised you to buy CD-ROM software at
|
|||
|
"kilo" prices in second hand shops (obviously never when the
|
|||
|
magazines themselves do appear)... even this trick is now
|
|||
|
useless: there is NO software that you cannot find on the Web
|
|||
|
(I'll bet that the CD-ROM mags are not making any easy money any
|
|||
|
more now). This truth may be difficult to slurp until you learn
|
|||
|
HOW to search effectively on the Web, a very difficult art -per
|
|||
|
se-, that all real crackers should master. A little tip: if you
|
|||
|
are in a hurry do your searches using your own search engines
|
|||
|
instead of using only the ubiquitous AltaVista, FTP and
|
|||
|
Webcrawler (which you SHOULD use, of course, but not alone).
|
|||
|
And loo! Good old Internet, made by governments and
|
|||
|
universities with public money and no private partecipation
|
|||
|
whatsoever reveals itself to be the most striking revolution of
|
|||
|
the last years in spite of the continuous blah blah about free
|
|||
|
markets and private initiative... quite funny, isn't it?
|
|||
|
New promising patterns are emerging: it is clear (to me)
|
|||
|
that the future of cracking lays in JavaScript applets: Netscape
|
|||
|
has opened quite a Pandora Box... now everybody is scrambling to
|
|||
|
close it... TOO LATE! Find the relevant documentation, tutorials,
|
|||
|
software, tools, examples... even teachers! Everything is there
|
|||
|
for free on the Web! Study it, and when you are ready study it
|
|||
|
again... take it easy: we have a long cracking future before
|
|||
|
us...
|
|||
|
Here is a nice example (by LaDue) of an interesting applet:
|
|||
|
this one forges an e-mail from the browsers of your page sending
|
|||
|
it to the address contained in the string "toMe". The browser of
|
|||
|
your page initiates the mail by connecting (involuntarily) to
|
|||
|
port 25 (int mailPort=25).
|
|||
|
Now, let's just academically imagine... you would put your
|
|||
|
own address (faked email address but working depot when you need
|
|||
|
to fetch the messages, as usual) in the string "toMe"... well,
|
|||
|
scanning incoming mail you could get the full e-mail address,
|
|||
|
including the user name, of many people who have seen your page.
|
|||
|
See LaDue example at:
|
|||
|
http://www.math.gatech.edu/~mladue/PenPal.java
|
|||
|
|
|||
|
JavaScript and Java are two completely different things: The
|
|||
|
coincidence in the name is only a stupid marketing move from
|
|||
|
Netscape. JavaScript is so easy it's a shame, and this makes it
|
|||
|
the ideal weapon for masscracking (Java on the countrary is a
|
|||
|
"real" programming language). The implications of easy Javascript
|
|||
|
use, of internet growth and of the "on the fly" JavaScript
|
|||
|
workings for the drafting of much more interesting applets are
|
|||
|
obvious, I'll let them to the intuition (and fantasy) of my
|
|||
|
cleverest readers.
|
|||
|
|
|||
|
II.[INSTANT ACCESS] End
|
|||
|
I'll admit it: I am a little deceived: the +HCU strainer
|
|||
|
(Instant access protection scheme) has been solved only by very
|
|||
|
few (pretty competent) crackers. The amount of people that has
|
|||
|
NOT cracked instant access (and that as relentlessy asked for
|
|||
|
more "clues") stood in no sound relation to the very few that
|
|||
|
solved it. I intended to give my complete solution in this lesson
|
|||
|
C3 to allow everybody to have (good) software for free... but too
|
|||
|
few worked hard on it to let you all lazy ones deserve a "ready-
|
|||
|
made" solution... I will therefore publish here one of the
|
|||
|
"incomplete" (albeit very good) solutions.
|
|||
|
The solution cracks the scheme but requires a little work
|
|||
|
of your part to accomplish it... what I mean is this: studying
|
|||
|
the following you'll be able to crack every Instant access
|
|||
|
protected code in a couple of hours, not immediatly... this is
|
|||
|
good, will make the lazy lurkers work (at least a little :=)
|
|||
|
Here it is (C++ code of the solution and admission letter),
|
|||
|
I only took off the name of the candidate:
|
|||
|
|
|||
|
Cracking Instant Access_____________
|
|||
|
by xxxxxxxx
|
|||
|
Application for 1996 Higher Cracking University
|
|||
|
|
|||
|
This is my solution to the strainer for admittance into your
|
|||
|
HCU. While I was successful in bypassing the protection (and
|
|||
|
hence now have a nice collection of software for free) I am the
|
|||
|
first to admit that my solution is not the best. However, I am
|
|||
|
very proud of the work I have done on this project and it is by
|
|||
|
far the most difficult crack I've ever done. In the past I've
|
|||
|
traced programs, and when they did something I did not like, I
|
|||
|
looked at the jumps immediately before that and reversed them.
|
|||
|
Because of idiot programming this worked about 60% of the
|
|||
|
time, however in many programs I was just stuck. With the hints
|
|||
|
you provided in your tutors I was able to actually disassemble
|
|||
|
the program and understand why it did things. Believe me this is
|
|||
|
a big jump. Anyway, here is my solution.
|
|||
|
I have dozens of handwritten notes and pages of code that
|
|||
|
I copied out of soft-ice, and any that are important I will type
|
|||
|
into this report, however most turned out to be unimportant. I
|
|||
|
have also created a "Magic" number generator and a reverse
|
|||
|
generator. I am very proud that I was able to create these,
|
|||
|
because the "Magic" number seemed so mysterious at first, and now
|
|||
|
I have complete mastery of it, a great feeling of power.
|
|||
|
I began the project by following the introductory steps in
|
|||
|
lessons C1 and C2. I got lost somewhere in C2, but I kept going.
|
|||
|
I got to the end with a vague understanding of what was happening
|
|||
|
and decided that I needed to understand this fully before I could
|
|||
|
do anything useful towards cracking it.
|
|||
|
I left my computer alone and read through the code again,
|
|||
|
making notes and explanations for my own use. About the third
|
|||
|
time through everything clicked, it was like a light bulb going
|
|||
|
off in my head. You mentioned that not everything in Lesson C1
|
|||
|
was correct.
|
|||
|
Here is a list of what I found to be incorrect.
|
|||
|
1. The offsets in the code were not the same. (this is a good
|
|||
|
idea to keep people from cheating when pinpointing the correct
|
|||
|
code)
|
|||
|
2. The pointers to where things are saved in memory were not the
|
|||
|
same.
|
|||
|
3. You wrote that the 1st digit plus 7 was saved and then you
|
|||
|
wrote that the 2nd plus 3 was saved. It is the other way around!
|
|||
|
1st plus 3 and 2nd plus 7. (just checking if we are paying
|
|||
|
attention huh?)
|
|||
|
I think that's all of the one's I found although there were
|
|||
|
many specific instances of each one. So here's what I did.
|
|||
|
I did a search on the 18 digit code I typed in. I found it
|
|||
|
at 30:8xxxxx and did a bpr on it. I let it run, and looked each
|
|||
|
time something accessed that area. Eventually I found code that
|
|||
|
checked if the digits were between 30 and 39 and copied them to
|
|||
|
DS:8CD8. So there lies the code with the "-" 's stripped off of
|
|||
|
it. I did a bpr on this area. It copied itself to DS:8CB8, and
|
|||
|
I bpr'ed that as well. I discovered that what was going on was,
|
|||
|
it copied itself, then that copy was transformed into the "Magic"
|
|||
|
number.
|
|||
|
So I did a little stack fishing, and found a CALL at offset
|
|||
|
5C04 which copies the code from 8CB8 and converts it into the
|
|||
|
"Magic" number. At this point I traced into the call and got
|
|||
|
really fucking lost, so I stepped back had a sip of Vodka and
|
|||
|
thought. I don't care HOW the "magic" gets there, only that it
|
|||
|
is there. I figured once I figured out what "magic" I needed I
|
|||
|
could trace over the call that put it there, and then put in
|
|||
|
whatever "magic" I wanted. So I traced on to see what happened
|
|||
|
to the "magic" number that had been produced. I had a bpr on the
|
|||
|
"magic" and it stopped on the first line of code below.
|
|||
|
The code is copied from my handwritten notes, so not
|
|||
|
everything is accurate (I only wrote down what I thought was
|
|||
|
important)
|
|||
|
2b67:2598 mov al, es:[bx] ; 12th digit of magic
|
|||
|
mov [bp-03], al ; ??????
|
|||
|
mov al, [bp-03] ; maybe an inefficient compiler
|
|||
|
result
|
|||
|
add al, d0 ; clean it
|
|||
|
mov [bp-04], al ; save it in [8ca6]
|
|||
|
les bx, bp+06
|
|||
|
add bx, si ; point to 12th again
|
|||
|
mov byte ptr es:bx, 30 ; make it a '0'
|
|||
|
push then more crap and then
|
|||
|
:253d mov al, es:bx ; 1st digit
|
|||
|
mov ah, 00 add ax,ffd0 ; clean it
|
|||
|
cwd
|
|||
|
add [bp-06], ax ; [8c90] is zero to start
|
|||
|
this loop repeats 18 times, summing up the "magic" number, with
|
|||
|
the 12th set to 0
|
|||
|
|
|||
|
:256e mov [bp-07], al ; save remainder of sum/a in [8c8f]
|
|||
|
cmp [al, bp-05] ; is 12th (in al) save as remainder
|
|||
|
of sum/a ? Aha!, this is what you were talking about at the end
|
|||
|
of C2, where the remainder doesn't match the 12th number.
|
|||
|
I knew I was on the right track. I could feel it.
|
|||
|
I traced down farther after the remainder check (I used
|
|||
|
8888-8888-8888-8888-88 as my code from then on because it passed
|
|||
|
this check and was easy to remember) and I found code which
|
|||
|
compared the value at ds:8D00 with the value at ds:8D0C and if
|
|||
|
it did not match jumped to beggar off.
|
|||
|
Then it checks if ds:8D06 is equal to ds:8D0E and if not
|
|||
|
equal jumps to beggar off. So I knew that 8D00 must equal 8D0C
|
|||
|
and that 8D06 must equal 8D0E.
|
|||
|
All I needed to do was figure out where these came from. I
|
|||
|
bpr'ed on 8D0C and found code which wrote the number to it.
|
|||
|
I did not copy the ASM down, but this is what I wrote:
|
|||
|
move 15th of "Magic" into AX fix it to 0-9 by +- A
|
|||
|
put it in SI
|
|||
|
mov 16th into AX
|
|||
|
mul si by A
|
|||
|
add ax to si
|
|||
|
mov 17th to AX
|
|||
|
mul si by A
|
|||
|
add ax to it
|
|||
|
put 18th in AX
|
|||
|
mul si by A
|
|||
|
add AX to it ; This is ds:8D0C !!!!
|
|||
|
So now I knew where this came from, the last 4 digits of the
|
|||
|
"magic" I bpr'ed on 8D0E and found out quickly that the first
|
|||
|
digit of the "magic" was put into ds:8D0E.
|
|||
|
Things were looking good. However, I was unable to figure out how
|
|||
|
ds:8D06 and ds:8D00 were created. I know they are related to the
|
|||
|
product code because they only change when it does. But they are
|
|||
|
put there by a MOVSW command and I cannot figure out how to
|
|||
|
predict where they are copied from, because it is only done once
|
|||
|
and it is never from the same place, so all my attempts to bpr
|
|||
|
on the spot they are copied from failed because it copies from
|
|||
|
a new spot each time.
|
|||
|
I felt dejected. I could not figure it out, even after days
|
|||
|
of pointless tracing.
|
|||
|
I stepped back and thought, and drank a can of Coke at 2
|
|||
|
a.m...
|
|||
|
|
|||
|
(note from +ORC: Coke is dangerous for your health and your cracking
|
|||
|
purposes... drink only Martini-Wodka and use by all means only russian
|
|||
|
Wodka)
|
|||
|
|
|||
|
...I still had not figured out how the "magic" worked. I
|
|||
|
decided to do that and come back to the problem of the numbers
|
|||
|
generated from the Product Code.
|
|||
|
I knew the call at cs:5C04 completely generated the "magic"
|
|||
|
so I started there. I traced through it several times and found
|
|||
|
that it made a CALL 3517 three times, then looped 6 times. So it
|
|||
|
called 3517 a total of 18 times. I also noticed that the CALL
|
|||
|
changed the number, but nothing else did, it just set up the
|
|||
|
calls.
|
|||
|
So I traced into CALL 3517 and came up with this:
|
|||
|
mov ax,ss
|
|||
|
nop inc bp
|
|||
|
push bp
|
|||
|
mov bp,sp
|
|||
|
push ds
|
|||
|
mov ds,ax
|
|||
|
xor ax a bunch more unimportant stuff
|
|||
|
:356b mov al,es:[bx} ; al = 18th digit
|
|||
|
cbw push ax
|
|||
|
mov ax, A
|
|||
|
sub ax,[5dad] ; subtract 6 from a to get 4
|
|||
|
imul [5db1] pop dx ; 18th digit
|
|||
|
add dx,ax add dx, -30 ;clean it
|
|||
|
mov [5db5], dx ;save it then fix [5db5] to be
|
|||
|
between 0 and 9
|
|||
|
mov al, es:[bx] ; load 18th again
|
|||
|
cbw push ax
|
|||
|
mov ax,a
|
|||
|
sub ax,[5dad]
|
|||
|
imul [5db3]
|
|||
|
pop dx ; 18th digit
|
|||
|
add dx, ax
|
|||
|
add dx, -30 ;clean it
|
|||
|
:35bb mov [5db7], dx ;save it.
|
|||
|
:35d9 mov bx,[5dad]
|
|||
|
mov es, bp+1a
|
|||
|
add bx,[bp+18]
|
|||
|
mov al,es:[bx-1] ; al = 6th digit
|
|||
|
mov [5dc3], al ; save it
|
|||
|
mov bx,[5dad]
|
|||
|
mov es,[bp+1e]
|
|||
|
add bx,[bp+1c]
|
|||
|
mov al,es:[bx-1] ; 12th digit
|
|||
|
mov [5dc4], al ; save it more junk then
|
|||
|
3605: mov bx,[5dbf] ; this is the beginning of a loop
|
|||
|
mov es,[bp+1a]
|
|||
|
add bx,[bp+18]
|
|||
|
mov al,es:[bx-1] ; 5th digit
|
|||
|
push ax ; save it
|
|||
|
mov ax,[5db5] ; [5db5] created above using 18th digit
|
|||
|
mov dx,A
|
|||
|
imul dx ;[5db] *A
|
|||
|
les bx,[bp+0c]
|
|||
|
add bx,ax
|
|||
|
add bx,[5db7] ; created using 18th
|
|||
|
pop ax ;5th digit
|
|||
|
sub al,es:[bx};subtract a value from the lookup table
|
|||
|
les bx add bx,[5dbf]
|
|||
|
mov es:[bx],al ; Put new value in 6th spot fix it
|
|||
|
so that it's between 0 and 9 by +- A
|
|||
|
:3656 mov bx,[5dbf]
|
|||
|
mov es,[bp+1e]
|
|||
|
add bx,[bp+1c]
|
|||
|
mov al,es:[bx-1] ; 11th digit
|
|||
|
push ax mov ax,[5db5]
|
|||
|
mov dx,a
|
|||
|
imul dx
|
|||
|
les bx
|
|||
|
add bx,ax
|
|||
|
add bx,[5db7]
|
|||
|
pop ax ;11th digit
|
|||
|
sub al,es:[bx] ; subtract a value from lookup
|
|||
|
table
|
|||
|
les bx, [bp+1c]
|
|||
|
add bx,[5db7]
|
|||
|
mov es:[bx],al ;put it in 12th spot fix it to be
|
|||
|
between 0 and 9 The loop above repeats doing the same thing,
|
|||
|
changing 2 numbers, but not always the same two. The next time
|
|||
|
through it changes 5th and 11th, after that the 4th and 10th, 3rd
|
|||
|
and 9th then the 2nd and 8th using this same pattern. After the
|
|||
|
loop it changes the 1st and 7th using the values of the original
|
|||
|
6th and 12th which were saved in [5dc3] and [5dc4] using the same
|
|||
|
pattern. I quickly wrote a program in C which would produce this
|
|||
|
number, and it worked fine.
|
|||
|
I traced into the second call of 3517 and found that the
|
|||
|
parameters passed to it changed which values where used to create
|
|||
|
[5db5] and [5db7], whether they increment or decrement, whether
|
|||
|
you add 0 or 64 to your index for the lookup and the digits which
|
|||
|
are changed. All three calls to 3517 have a different
|
|||
|
arrangement, but the their arrangement is the same each time they
|
|||
|
are called. For instance, the three calls are looped over 6
|
|||
|
times, on each instance that the 1st call is executed it will
|
|||
|
change the 6th,12th,5th, 11th, etc. So I modified my C program
|
|||
|
to mimic the behaviour of each call and looped it six times,
|
|||
|
expecting this to be the "magic" number. To my surprise it was
|
|||
|
not right.
|
|||
|
So I followed the code until after the 3 CALL 3517's had
|
|||
|
been made, this was the number my generator had given me, so it
|
|||
|
must do something more afterwards.
|
|||
|
I found the following code, still within the cs:5c04 call
|
|||
|
:44C1 mov al,es:[bx+si-2] ; 17th digit
|
|||
|
add al,d0 ;clean it
|
|||
|
mov [5dc1], al ;save it
|
|||
|
les bx
|
|||
|
mov al,es:[bx+si-2] ; 18th digit
|
|||
|
add al,d0 ;clean it
|
|||
|
mov [5dc2],al ;save it
|
|||
|
mov [5dbf],0
|
|||
|
jmp 455f :44df
|
|||
|
les bx
|
|||
|
add bx,[5dbf]
|
|||
|
mov al,[5dc1] ;17th cleaned
|
|||
|
sub es:[bx],al ;1st digit has 17th cleaned
|
|||
|
subtracted from it fix it between 0 and 9
|
|||
|
mov al,[5dc2] ;18th cleaned 4520
|
|||
|
sub es:[bx],al ;7th - 18th cleaned is put in 7th
|
|||
|
spot fix it between 0 and 9
|
|||
|
:455b inc word ptr [5dbf]
|
|||
|
mov ax,[5dbf]
|
|||
|
cmp ax,[5dad] ; run six times
|
|||
|
jge 456b
|
|||
|
jmp 44df 456b: blah blah continue on.
|
|||
|
This loop executes six times each time incrementing the digit to
|
|||
|
be changed by one so that the first change changes the 1st digit,
|
|||
|
and the next time through the loop the 2nd then the 3rd.....till
|
|||
|
the sixth. The second change alters the 7th through the 12th
|
|||
|
digits. I added code to do this at the end of my Generator, and
|
|||
|
I now had a "Magic" number generator. However this did not do me
|
|||
|
much good in itself. The breakthrough was reversing this program
|
|||
|
(it wasn't hard, but getting all the bugs out was really tough)
|
|||
|
so that it takes a "magic" number as input and tells you what
|
|||
|
registration number will produce it. I have included the source
|
|||
|
code for both programs to prove that they are my own work. The
|
|||
|
coding is not the best, they are my own crude tools, and they do
|
|||
|
the job I need them for. But now I am home free. Even without
|
|||
|
knowing how the product code is manipulated to come up with
|
|||
|
ds:8D00 and ds:8d06 I can crack it. Here's what I did.
|
|||
|
The product code given me was 3850-0118-6260-1057-23 I
|
|||
|
traced to where ds:8D00 and ds:8D06 are placed they were:
|
|||
|
ds:8D00 = E03 ds:8D06 = 3 I knew the last 4 digits when added,
|
|||
|
and multiplied as explained above must be E03 so this is what I
|
|||
|
wrote down, using my calculator
|
|||
|
DFC + 7 =E03
|
|||
|
This is the final answer, but I need to work backwards from here
|
|||
|
166 * A = DFC
|
|||
|
15E + 8 = 166
|
|||
|
23 * A = 15E
|
|||
|
1E +5 = 23
|
|||
|
3 * A = 1E
|
|||
|
Just working things backwards from the way the program did it I
|
|||
|
figured out the last 4 digits of the magic code need to be 3587
|
|||
|
in order for it to produce E03 as a result. I also know that the
|
|||
|
first digit must be equal to ds:8d06 which is 3 so I now have:
|
|||
|
3___-____-____-__35-87
|
|||
|
as a "magic" number and I fill it in with 1's
|
|||
|
3111-1111-111X-1135-87
|
|||
|
I left the 12th number as an X because I remember that the
|
|||
|
remainder of the sum of all the digits except the 12th must be
|
|||
|
equal to the 12th.
|
|||
|
3+1+1+1+1+1+1+1+1+1+1+1+1+3+5+8+7 = 26 26/A
|
|||
|
26 26/A = 3 with a remainder of 8,
|
|||
|
so the 12th digit is an 8!
|
|||
|
My "magic" number should be 3111-1111-1118-1135-87
|
|||
|
So I run my UNINSTAN program, which tells me that in order to get
|
|||
|
that "magic" I need to enter the following registration code:
|
|||
|
4798-8540-6989-6899-53 I enter this in, the "Retrieve" button is
|
|||
|
enabled and I install Norton Utilities without a hassle! I used
|
|||
|
the same method to install Wine Select (I've been interested in
|
|||
|
wine since reading about your Pomerol), Labels Unlimited (which
|
|||
|
I use for what else? Barcodes!), Harvard Graphics, and Lotus Ami
|
|||
|
Pro, which I'm using to write this report on!
|
|||
|
Well, that's it. That is how I cracked Instant Access. As
|
|||
|
I mentioned above it is not the best way, but I gave everything
|
|||
|
I had and it's the best I could do.
|
|||
|
I have succeeded because I have beaten the protection, and
|
|||
|
because I taught myself a lot along the way. I'm sure you already
|
|||
|
have a "magic" number generator of your own, but I included mine
|
|||
|
so you could see it. If I just knew how the product code produces
|
|||
|
those 2 numbers I could create a product code to registration
|
|||
|
number converter, which I assume is what the operators at Instant
|
|||
|
Access have when you call them to buy stuff.
|
|||
|
One last note about this assignment. I know that you have
|
|||
|
realized that Instant Access was hard to find. I want to tell you
|
|||
|
how I got it, a bit a social engineering in itself. After
|
|||
|
searching every library and book/magazine store in the city I got
|
|||
|
on the Internet and asked. Nobody had it.
|
|||
|
So I found the Instant Access homepage. ...
|
|||
|
|
|||
|
(this will not be published, coz I, +ORC, do not want to expose my crackers,
|
|||
|
but the way this guy got hold of the protection scheme is in itself worth
|
|||
|
is access to the +HCU)
|
|||
|
|
|||
|
...So as you can see, I have gone to great lengths for admittance
|
|||
|
into your University, and I hope I have earned it. I am proud to
|
|||
|
wear my +
|
|||
|
|
|||
|
...address follows
|
|||
|
And here are the two C++ programs:
|
|||
|
|
|||
|
INSTANT.CPP-----------------------------------
|
|||
|
// Template for byte patch files
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
|
|||
|
|
|||
|
void main()
|
|||
|
{
|
|||
|
char fix(char x);
|
|||
|
|
|||
|
char *t; //*stopstring
|
|||
|
int save1, save2,fdbf,fdbs, i;
|
|||
|
static int table[208] = {1,3,3,1,9,2,3,0, 9,0,4,3,8,7,4,4,
|
|||
|
5,2,9,0,2,4,1,5, 6,6,3,2,0,8,5,6,
|
|||
|
8,9,5,0,4,6,7,7, 2,0,8,0,6,2,4,7,
|
|||
|
4,4,9,5,9,6,0,6, 8,7,0,3,5,9,0,8,
|
|||
|
3,7,7,6,8,9,1,5, 7,4,6,1,4,2,7,1,
|
|||
|
3,1,8,1,5,3,3,1, 2,8,2,1,6,5,7,2,
|
|||
|
5,9,9,8,2,9,3,0, 0,4,5,1,1,3,8,6,
|
|||
|
1,1,9,0,2,5,5,5, 1,7,1,5,8,7,1,9,
|
|||
|
8,7,7,4,4,8,3,0, 6,1,9,8,8,4,9,9,
|
|||
|
0,7,5,2,3,1,3,8, 6,5,7,6,3,7,6,7,
|
|||
|
4,2,2,5,2,4,6,2, 6,9,9,1,5,2,3,4,
|
|||
|
4,0,3,5,0,3,8,7, 6,4,8,8,2,0,3,6,
|
|||
|
9,0,0,6,9,4,7,2, 0,1,1,1,1,0,1} ;
|
|||
|
|
|||
|
|
|||
|
//_clearscreen(_GCLEARSCREEN);
|
|||
|
printf("Enter the 18 digit Reg code: ");
|
|||
|
gets(t);
|
|||
|
|
|||
|
for (i=1; i<=6 ; i++)
|
|||
|
{
|
|||
|
save1 = t[5]; // save the sixth digit
|
|||
|
save2 = t[11]; // save the twelfth digit
|
|||
|
|
|||
|
fdbf = 0xFFC+t[17]-0x1000-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
fdbs = fdbf; // and [5db7]
|
|||
|
|
|||
|
t[5] = t[4] - table[fdbf*0xA+fdbs] ; // sixth number
|
|||
|
t[5] = fix(t[5]);
|
|||
|
|
|||
|
t[11] = t[10] - table[fdbf*0xA+fdbs+0x64]; // 12th
|
|||
|
number
|
|||
|
t[11] = fix(t[11]);
|
|||
|
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[4] = t[3] - table[fdbf*0xA+fdbs] ; // 5th number
|
|||
|
t[4] = fix(t[4]);
|
|||
|
|
|||
|
t[10] = t[9] - table[fdbf*0xA+fdbs+0x64]; // 11th
|
|||
|
number
|
|||
|
t[10] = fix(t[10]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[3] = t[2] - table[fdbf*0xA+fdbs] ; // 4th number
|
|||
|
t[3] = fix(t[3]);
|
|||
|
|
|||
|
t[9] = t[8] - table[fdbf*0xA+fdbs+0x64]; // 10th number
|
|||
|
t[9] = fix(t[9]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[2] = t[1] - table[fdbf*0xA+fdbs] ; // 3rd number
|
|||
|
t[2] = fix(t[2]);
|
|||
|
|
|||
|
t[8] = t[7] - table[fdbf*0xA+fdbs+0x64]; // 9th number
|
|||
|
t[8] = fix(t[8]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[1] = t[0] - table[fdbf*0xA+fdbs] ; // 2nd number
|
|||
|
t[1] = fix(t[1]);
|
|||
|
|
|||
|
t[7] = t[6] - table[fdbf*0xA+fdbs+0x64]; // 8th number
|
|||
|
t[7] = fix(t[7]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[0] = save1 - table[fdbf*0xA+fdbs]; // first digit
|
|||
|
t[0] = fix(t[0]);
|
|||
|
t[6] = save2 - table[fdbf*0xA+fdbs+0x64]; // 7th digit
|
|||
|
t[6] = fix(t[6]);
|
|||
|
|
|||
|
//puts(t);
|
|||
|
// end of first call
|
|||
|
////////////////////////////////////////////////
|
|||
|
|
|||
|
save1 = t[5]; // save the sixth digit
|
|||
|
save2 = t[17]; // save the 18th digit
|
|||
|
|
|||
|
fdbf = t[10]+0x4-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
|
|||
|
fdbs = t[9]+0x4-0x30; // and [5db7]
|
|||
|
if (fdbs < 0x0)
|
|||
|
fdbs += 0xA; // fix it if necessary
|
|||
|
else if (fdbs >= 0xA)
|
|||
|
fdbs -= 0xA;
|
|||
|
|
|||
|
|
|||
|
t[5] = t[4] - table[fdbf*0xA+fdbs] ; // sixth number
|
|||
|
t[5] = fix(t[5]);
|
|||
|
|
|||
|
t[17] = t[16] - table[fdbf*0xA+fdbs+0x64]; // 18th
|
|||
|
number
|
|||
|
t[17] = fix(t[17]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[4] = t[3] - table[fdbf*0xA+fdbs] ; // 5th number
|
|||
|
t[4] = fix(t[4]);
|
|||
|
|
|||
|
t[16] = t[15] - table[fdbf*0xA+fdbs+0x64]; // 17th
|
|||
|
number
|
|||
|
t[16] = fix(t[16]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[3] = t[2] - table[fdbf*0xA+fdbs] ; // 4th number
|
|||
|
t[3] = fix(t[3]);
|
|||
|
|
|||
|
t[15] = t[14] - table[fdbf*0xA+fdbs+0x64]; // 16th
|
|||
|
number
|
|||
|
t[15] = fix(t[15]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[2] = t[1] - table[fdbf*0xA+fdbs] ; // 3rd number
|
|||
|
t[2] = fix(t[2]);
|
|||
|
|
|||
|
t[14] = t[13] - table[fdbf*0xA+fdbs+0x64]; // 15th
|
|||
|
number
|
|||
|
t[14] = fix(t[14]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[1] = t[0] - table[fdbf*0xA+fdbs] ; // 2nd number
|
|||
|
t[1] = fix(t[1]);
|
|||
|
|
|||
|
t[13] = t[12] - table[fdbf*0xA+fdbs+0x64]; // 14th
|
|||
|
number
|
|||
|
t[13] = fix(t[13]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[0] = save1 - table[fdbf*0xA+fdbs]; // first digit
|
|||
|
t[0] = fix(t[0]);
|
|||
|
t[12] = save2 - table[fdbf*0xA+fdbs+0x64]; // 13th
|
|||
|
digit
|
|||
|
t[12] = fix(t[12]);
|
|||
|
|
|||
|
//puts(t);
|
|||
|
// end of second call
|
|||
|
////////////////////////////////////////////////
|
|||
|
|
|||
|
|
|||
|
save1 = t[11]; // save the 12th digit
|
|||
|
save2 = t[17]; // save the 18th digit
|
|||
|
|
|||
|
fdbf = t[1]+0x4-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
|
|||
|
fdbs = t[2]+0x4-0x30; // and [5db7]
|
|||
|
if (fdbs < 0x0)
|
|||
|
fdbs += 0xA; // fix it if necessary
|
|||
|
else if (fdbs >= 0xA)
|
|||
|
fdbs -= 0xA;
|
|||
|
|
|||
|
|
|||
|
t[17] = t[16] - table[fdbf*0xA+fdbs] ; // 18th number
|
|||
|
t[17] = fix(t[17]);
|
|||
|
|
|||
|
t[11] = t[10] - table[fdbf*0xA+fdbs+0x64]; // 12th
|
|||
|
number
|
|||
|
t[11] = fix(t[11]);
|
|||
|
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[16] = t[15] - table[fdbf*0xA+fdbs] ; // 17th number
|
|||
|
t[16] = fix(t[16]);
|
|||
|
|
|||
|
t[10] = t[9] - table[fdbf*0xA+fdbs+0x64]; // 11th
|
|||
|
number
|
|||
|
t[10] = fix(t[10]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[15] = t[14] - table[fdbf*0xA+fdbs] ; // 16th number
|
|||
|
t[15] = fix(t[15]);
|
|||
|
|
|||
|
t[9] = t[8] - table[fdbf*0xA+fdbs+0x64]; // 10th number
|
|||
|
t[9] = fix(t[9]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[14] = t[13] - table[fdbf*0xA+fdbs] ; // 15th number
|
|||
|
t[14] = fix(t[14]);
|
|||
|
|
|||
|
t[8] = t[7] - table[fdbf*0xA+fdbs+0x64]; // 9th number
|
|||
|
t[8] = fix(t[8]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[13] = t[12] - table[fdbf*0xA+fdbs] ; // 14th number
|
|||
|
t[13] = fix(t[13]);
|
|||
|
|
|||
|
t[7] = t[6] - table[fdbf*0xA+fdbs+0x64]; // 8th number
|
|||
|
t[7] = fix(t[7]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[12] = save2 - table[fdbf*0xA+fdbs]; // 13th digit
|
|||
|
t[12] = fix(t[12]);
|
|||
|
|
|||
|
t[6] = save1 - table[fdbf*0xA+fdbs+0x64]; // 7th digit
|
|||
|
t[6] = fix(t[6]);
|
|||
|
|
|||
|
|
|||
|
// end of third call
|
|||
|
////////////////////////////////////////////////
|
|||
|
|
|||
|
|
|||
|
} // end of for loop
|
|||
|
|
|||
|
// Now we finish it up
|
|||
|
save1 = t[16] + 0xD0 - 0x100; // [5dc1]
|
|||
|
save2 = t[17] + 0xD0 - 0x100; // [5dc2]
|
|||
|
|
|||
|
for (i=0; i<6; i++)
|
|||
|
{
|
|||
|
t[i] = t[i] - save1;
|
|||
|
t[i] = fix(t[i]);
|
|||
|
|
|||
|
t[i+6] = t[i+6] - save2;
|
|||
|
t[i+6] = fix(t[i+6]);
|
|||
|
}
|
|||
|
|
|||
|
printf("'Magic' code is: ");
|
|||
|
for (i=0; i<18 ;i++) // output the string (only first 18)
|
|||
|
putc(t[i], stdout);
|
|||
|
printf("\n\n Created by xxxxx for +Orc's HCU 1996");
|
|||
|
|
|||
|
} // end of main()
|
|||
|
|
|||
|
|
|||
|
char fix(char x)
|
|||
|
{
|
|||
|
if (x < '0')
|
|||
|
x = x+0xA;
|
|||
|
|
|||
|
else if (x > 0x39)
|
|||
|
x -= 0xA;
|
|||
|
|
|||
|
return x;
|
|||
|
}
|
|||
|
|
|||
|
---------------------------------------------------
|
|||
|
UNINSTANT.CPP
|
|||
|
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
#include
|
|||
|
|
|||
|
|
|||
|
void main()
|
|||
|
{
|
|||
|
char fix(char x);
|
|||
|
|
|||
|
char *t;
|
|||
|
int save1, save2,fdbf,fdbs, i,q, fdbssave,fdbfsave;
|
|||
|
static int table[208] = {1,3,3,1,9,2,3,0, 9,0,4,3,8,7,4,4,
|
|||
|
5,2,9,0,2,4,1,5, 6,6,3,2,0,8,5,6,
|
|||
|
8,9,5,0,4,6,7,7, 2,0,8,0,6,2,4,7,
|
|||
|
4,4,9,5,9,6,0,6, 8,7,0,3,5,9,0,8,
|
|||
|
3,7,7,6,8,9,1,5, 7,4,6,1,4,2,7,1,
|
|||
|
3,1,8,1,5,3,3,1, 2,8,2,1,6,5,7,2,
|
|||
|
5,9,9,8,2,9,3,0, 0,4,5,1,1,3,8,6,
|
|||
|
1,1,9,0,2,5,5,5, 1,7,1,5,8,7,1,9,
|
|||
|
8,7,7,4,4,8,3,0, 6,1,9,8,8,4,9,9,
|
|||
|
0,7,5,2,3,1,3,8, 6,5,7,6,3,7,6,7,
|
|||
|
4,2,2,5,2,4,6,2, 6,9,9,1,5,2,3,4,
|
|||
|
4,0,3,5,0,3,8,7, 6,4,8,8,2,0,3,6,
|
|||
|
9,0,0,6,9,4,7,2, 0,1,1,1,1,0,1} ;
|
|||
|
|
|||
|
printf("Enter the 18 digit 'Magic' code: ");
|
|||
|
gets(t);
|
|||
|
|
|||
|
save1 = t[16] + 0xD0 - 0x100; // [5dc1]
|
|||
|
save2 = t[17] + 0xD0 - 0x100; // [5dc2]
|
|||
|
|
|||
|
for (i=5; i>=0 ; i--) // fix it before main loop
|
|||
|
{
|
|||
|
t[i] = t[i] +save1;
|
|||
|
t[i] = fix(t[i]);
|
|||
|
|
|||
|
t[i+6] = t[i+6] + save2;
|
|||
|
t[i+6] = fix(t[i+6]);
|
|||
|
}
|
|||
|
|
|||
|
for (i=1; i<=6 ; i++)
|
|||
|
{
|
|||
|
// begin third call
|
|||
|
fdbf = 0x4+t[1]-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
fdbs = 0x4+t[2]-0x30 ; // create [5db7]
|
|||
|
if (fdbs < 0x0)
|
|||
|
fdbs += 0xA; // fix it if necessary
|
|||
|
else if (fdbs >= 0xA)
|
|||
|
fdbs -= 0xA;
|
|||
|
|
|||
|
|
|||
|
save1 = t[6]; //save 7th
|
|||
|
save2 = t[12]; // and 13th
|
|||
|
|
|||
|
for (q=1; q<=5; q++) // put [ ]'s where they were at end
|
|||
|
of loop
|
|||
|
{
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
}
|
|||
|
fdbssave = fdbs;
|
|||
|
fdbfsave = fdbf;
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[6] = t[7] + table[fdbf*0xA+fdbs+0x64]; // 7th digit
|
|||
|
t[6] = fix(t[6]);
|
|||
|
|
|||
|
t[12] = t[13] + table[fdbf*0xA+fdbs]; // 13th digit
|
|||
|
t[12] = fix(t[12]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[7] = t[8] + table[fdbf*0xA+fdbs+0x64]; // 8th digit
|
|||
|
t[7] = fix(t[7]);
|
|||
|
|
|||
|
t[13] = t[14] + table[fdbf*0xA+fdbs]; // 14th digit
|
|||
|
t[13] = fix(t[13]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[8] = t[9] + table[fdbf*0xA+fdbs+0x64]; // 9th digit
|
|||
|
t[8] = fix(t[8]);
|
|||
|
|
|||
|
t[14] = t[15] + table[fdbf*0xA+fdbs]; // 15th digit
|
|||
|
t[14] = fix(t[14]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
|
|||
|
t[9] = t[10] + table[fdbf*0xA+fdbs+0x64]; // 10th digit
|
|||
|
t[9] = fix(t[9]);
|
|||
|
|
|||
|
t[15] = t[16] + table[fdbf*0xA+fdbs]; // 16th digit
|
|||
|
t[15] = fix(t[15]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[10] = t[11] + table[fdbf*0xA+fdbs+0x64]; // 11th
|
|||
|
digit
|
|||
|
t[10] = fix(t[10]);
|
|||
|
|
|||
|
t[16] = t[17] + table[fdbf*0xA+fdbs]; // 17th digit
|
|||
|
t[16] = fix(t[16]);
|
|||
|
|
|||
|
t[11] = save1 + table[fdbfsave*0xA+fdbssave+0x64]; //
|
|||
|
12th digit
|
|||
|
t[11] = fix(t[11]);
|
|||
|
|
|||
|
t[17] = save2 + table[fdbfsave*0xA+fdbssave]; // 18th digit
|
|||
|
t[17] = fix(t[17]);
|
|||
|
|
|||
|
// end of third call
|
|||
|
|
|||
|
|
|||
|
// begin second call
|
|||
|
fdbf = 0x4+t[10]-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
fdbs = 0x4+t[9]-0x30 ; // create [5db7]
|
|||
|
if (fdbs < 0x0)
|
|||
|
fdbs += 0xA; // fix it if necessary
|
|||
|
else if (fdbs >= 0xA)
|
|||
|
fdbs -= 0xA;
|
|||
|
|
|||
|
|
|||
|
save1 = t[0]; //save first
|
|||
|
save2 = t[12]; // and 13th
|
|||
|
|
|||
|
for (q=1; q<=5; q++) // put [ ]'s where they were at end
|
|||
|
of loop
|
|||
|
{
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
}
|
|||
|
fdbssave = fdbs;
|
|||
|
fdbfsave = fdbf;
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[0] = t[1] + table[fdbf*0xA+fdbs]; // 1st digit
|
|||
|
t[0] = fix(t[0]);
|
|||
|
|
|||
|
t[12] = t[13] + table[fdbf*0xA+fdbs+0x64]; // 13th digit
|
|||
|
t[12] = fix(t[12]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[1] = t[2] + table[fdbf*0xA+fdbs]; // 2nd digit
|
|||
|
t[1] = fix(t[1]);
|
|||
|
|
|||
|
t[13] = t[14] + table[fdbf*0xA+fdbs+0x64]; // 14th digit
|
|||
|
t[13] = fix(t[13]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[2] = t[3] + table[fdbf*0xA+fdbs]; // 3rd digit
|
|||
|
t[2] = fix(t[2]);
|
|||
|
|
|||
|
t[14] = t[15] + table[fdbf*0xA+fdbs+0x64]; // 15th digit
|
|||
|
t[14] = fix(t[14]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
|
|||
|
t[3] = t[4] + table[fdbf*0xA+fdbs]; // 4th digit
|
|||
|
t[3] = fix(t[3]);
|
|||
|
|
|||
|
t[15] = t[16] + table[fdbf*0xA+fdbs+0x64]; // 16th digit
|
|||
|
t[15] = fix(t[15]);
|
|||
|
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
|
|||
|
t[4] = t[5] + table[fdbf*0xA+fdbs]; // 5th digit
|
|||
|
t[4] = fix(t[4]);
|
|||
|
|
|||
|
t[16] = t[17] + table[fdbf*0xA+fdbs+0x64]; // 17th digit
|
|||
|
t[16] = fix(t[16]);
|
|||
|
|
|||
|
t[5] = save1 + table[fdbfsave*0xA+fdbssave]; // 6th
|
|||
|
digit
|
|||
|
t[5] = fix(t[5]);
|
|||
|
|
|||
|
t[17] = save2 + table[fdbfsave*0xA+fdbssave+0x64]; // 18th
|
|||
|
digit
|
|||
|
t[17] = fix(t[17]);
|
|||
|
// end of second call
|
|||
|
// begin first call
|
|||
|
fdbf = 0xFFC+t[17]-0x1000-0x30 ; // create [5db5]
|
|||
|
if (fdbf < 0x0)
|
|||
|
fdbf += 0xA; // fix it if necessary
|
|||
|
else if (fdbf >= 0xA)
|
|||
|
fdbf -= 0xA;
|
|||
|
fdbs = fdbf; // and [5db7]
|
|||
|
|
|||
|
save1 = t[0]; //save first
|
|||
|
save2 = t[6]; // and 7th
|
|||
|
|
|||
|
for (q=1; q<=5; q++) // put [ ]'s where they were at end
|
|||
|
of loop
|
|||
|
{
|
|||
|
fdbf -= 1; // decrement
|
|||
|
if (fdbf == -1)
|
|||
|
fdbf = 9;
|
|||
|
fdbs -= 1;
|
|||
|
if (fdbs == -1)
|
|||
|
fdbs = 9;
|
|||
|
}
|
|||
|
fdbssave = fdbs;
|
|||
|
fdbfsave = fdbf;
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[0] = t[1] + table[fdbf*0xA+fdbs]; // 1st digit
|
|||
|
t[0] = fix(t[0]);
|
|||
|
|
|||
|
t[6] = t[7] + table[fdbf*0xA+fdbs+0x64]; // 7th digit
|
|||
|
t[6] = fix(t[6]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[1] = t[2] + table[fdbf*0xA+fdbs]; // 2nd digit
|
|||
|
t[1] = fix(t[1]);
|
|||
|
|
|||
|
t[7] = t[8] + table[fdbf*0xA+fdbs+0x64]; // 8th digit
|
|||
|
t[7] = fix(t[7]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[2] = t[3] + table[fdbf*0xA+fdbs]; // 3rd digit
|
|||
|
t[2] = fix(t[2]);
|
|||
|
|
|||
|
t[8] = t[9] + table[fdbf*0xA+fdbs+0x64]; // 9th digit
|
|||
|
t[8] = fix(t[8]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
|
|||
|
t[3] = t[4] + table[fdbf*0xA+fdbs]; // 4th digit
|
|||
|
t[3] = fix(t[3]);
|
|||
|
|
|||
|
t[9] = t[10] + table[fdbf*0xA+fdbs+0x64]; // 10th digit
|
|||
|
t[9] = fix(t[9]);
|
|||
|
|
|||
|
fdbf += 1; // increment
|
|||
|
if (fdbf == 10)
|
|||
|
fdbf = 0;
|
|||
|
fdbs += 1;
|
|||
|
if (fdbs == 10)
|
|||
|
fdbs = 0;
|
|||
|
|
|||
|
t[4] = t[5] + table[fdbf*0xA+fdbs]; // 5th digit
|
|||
|
t[4] = fix(t[4]);
|
|||
|
|
|||
|
t[10] = t[11] + table[fdbf*0xA+fdbs+0x64]; // 11th digit
|
|||
|
t[10] = fix(t[10]);
|
|||
|
|
|||
|
t[5] = save1 + table[fdbfsave*0xA+fdbssave]; // 6th
|
|||
|
digit
|
|||
|
t[5] = fix(t[5]);
|
|||
|
|
|||
|
t[11] = save2 + table[fdbfsave*0xA+fdbssave+0x64]; // 12th
|
|||
|
digit
|
|||
|
t[11] = fix(t[11]);
|
|||
|
// end of first call
|
|||
|
} // end for loop
|
|||
|
|
|||
|
printf("\nTo Get That 'Magic' Use: ");
|
|||
|
for (i=0; i<18 ;i++) // output the string (only first 18)
|
|||
|
putc(t[i], stdout);
|
|||
|
printf("\n\n Created by +xxxxx for +Orc's HCU 1996");
|
|||
|
|
|||
|
} // end of main()
|
|||
|
|
|||
|
|
|||
|
char fix(char x)
|
|||
|
// fixes chars to between 0 and 9
|
|||
|
{
|
|||
|
if (x < '0')
|
|||
|
x = x+0xA;
|
|||
|
|
|||
|
else if (x > 0x39)
|
|||
|
x -= 0xA;
|
|||
|
|
|||
|
return x;
|
|||
|
}
|
|||
|
|
|||
|
III. THE [DATADUMP_WINDOW] TRICK & HOW TO SEARCH THE WEB.
|
|||
|
|
|||
|
[WINFORMANT 4 HOW TO FIND IT]
|
|||
|
I have chosen (as usual) an older windows application for
|
|||
|
Win 3.1. (Version 1.10, by Joseph B. Albanese), in order to
|
|||
|
terminate completely the "password lessons" and at the same time
|
|||
|
show you a nice little trick that can be very useful in cracking
|
|||
|
*ALL* protected programs (password protected or time protected
|
|||
|
or function disabled): memory windows_dumping. There is in almost
|
|||
|
all protection routines, as you have already learned, a moment
|
|||
|
when on the stack appears the ECHO of the real, "correct"
|
|||
|
passnumber or password, in order to compare the input of the user
|
|||
|
with it.
|
|||
|
The location of this ECHO varies, but it will be most of the
|
|||
|
time in a range of +- 0x90 bytes from the user input. This is due
|
|||
|
to datadump windows restraints inside the tools used by the
|
|||
|
protectionists I'll not delve inside here, and this use is bound
|
|||
|
to diminish (especially after this lesson :=).
|
|||
|
You'll find the files that I use in this lesson searching
|
|||
|
the web with the usual search_tools and search_strategies: These
|
|||
|
are names, lengths and dates of the relevant files... this will
|
|||
|
allow you to FTPMAIL them after having located them through an
|
|||
|
ARCHIE_search:
|
|||
|
CTL3D DLL 20976 17/08/93 4:36
|
|||
|
README WRI 2688 08/05/94 1:54
|
|||
|
SS3D2 VBX 88096 11/06/92 18:42
|
|||
|
STDLL DLL 10880 06/05/94 22:57
|
|||
|
THREED VBX 64432 17/07/93 0:00
|
|||
|
WIN4MANT EXE 562271 07/06/96 17:51
|
|||
|
WIN4MANT HLP 190608 08/05/94 0:36
|
|||
|
XLIST VBX 15248 15/02/93 0:00
|
|||
|
|
|||
|
Please do not underestimate the importance of *EXACT NAMES*
|
|||
|
on the Web (be it of people, of subjects or of software)... as
|
|||
|
a matter of fact the Web corroborates (every day more). The old
|
|||
|
intuition from Persio: NOMEN ATQUE OMEN: how true! Think a moment
|
|||
|
about it, the importance of the NAMES on the Web is astonishing
|
|||
|
(and growing)!
|
|||
|
1) It is true for http://... addresses: domains must be
|
|||
|
unique and registered (and the Web registration burocrats will
|
|||
|
get from you 100 dollars per year just to keep them registered);
|
|||
|
2) It is true for programs (you must know BEFOREHAND the name of
|
|||
|
a file to find it quickly on the Web); 3) It's even true for your
|
|||
|
own site denomination (try searching for "Bill's" page instead
|
|||
|
than for "WIKKY_WAKKY's" page... that's (reversing this approach)
|
|||
|
one of the reason I have a "+" inside my handle, this confuses
|
|||
|
the search engines just enough to give me a little more anonymity
|
|||
|
(search for me! You'll get quite a lot of Warcraft stuff :=).
|
|||
|
Enough! If you do not know neither why all this happen nor
|
|||
|
how to search the Web, but are interested in these matters (as
|
|||
|
you should), study the web search engines themselves and read the
|
|||
|
relevant help files (search AltaVista and WebCrawler for
|
|||
|
"FTPMAIL", "WWW via e-mail", "AGORA", "search strategies" etc).
|
|||
|
It's amazing how few crackers (not to mention the lusers)
|
|||
|
do actually read the help files of the search engines they are
|
|||
|
using, which should be your bible (or the coran, or some other
|
|||
|
crap, for all I care about religions), your alpha and omega! The
|
|||
|
(growing) amount of junk on the Web makes your ability to search
|
|||
|
effectively the little grains of interesting truths that are
|
|||
|
escaping the growing heavy censorship of our enemies even more
|
|||
|
important.
|
|||
|
Back to our [Winformant] cracking now, and back to our
|
|||
|
stackdump window trick... here you are:
|
|||
|
|
|||
|
[WINFORMANT CRACKING]
|
|||
|
This application is -per se- absolutely crap, I doubt you'll
|
|||
|
ever use it: this program is so primitive it must have been one
|
|||
|
of the first crappy visual basic experiments made by his
|
|||
|
programmer... but this [Winformant] program is nevertheless very
|
|||
|
interesting for us coz it possesses a curious (and pretty rare)
|
|||
|
"deactivate" mode, i.e. you can "unregister" it on the fly if you
|
|||
|
feel the need to... it beats me why the programmer wanted such
|
|||
|
a feature inside... he was just probably collecting little
|
|||
|
routines and mixing them without sound reasons.
|
|||
|
This feature is as rare as useless, but it is worth for
|
|||
|
cracking scholars that (should) investigate password algorithms
|
|||
|
with valid and invalid codes without having to reinstall
|
|||
|
everything only in order to delete previous valid codes.
|
|||
|
For your cracking exercises you should therefore choose
|
|||
|
programs that have "REVERSIBLE" protections (like this
|
|||
|
Winformant... very rare) or that can be re-registered a billion
|
|||
|
times (that's a more frequent protection pattern). Programs that
|
|||
|
keep the valid registration on *.ini or special files can also
|
|||
|
be useful... you just need to change a couple of lines in these
|
|||
|
files to restore the "unregistered" mode.
|
|||
|
The trick we'll use in this lesson: "password proximity",
|
|||
|
bases on the fact that the protectionists need to keep an eye on
|
|||
|
their protection when they "build" it and have to *see* closely
|
|||
|
the relationships between
|
|||
|
1) USER INPUT PASSNUMBER (i.e. the input registration number
|
|||
|
that the user should have bought, but could be a fake bad guy
|
|||
|
input)
|
|||
|
2) USER INPUT TRANSFORMED (i.e. the result of the working of
|
|||
|
the protectionist's algorithm on the user input passnumber)
|
|||
|
and the
|
|||
|
3) CORRECT PASSNUMBER ANSWER (The BINGO!) i.e., the Passnumber
|
|||
|
calculated with some algorithm on the bases of the USER INPUT
|
|||
|
NAME (the name of the user, eventually transformed in USER INPUT
|
|||
|
TRANSFORMED).
|
|||
|
In order to clear bugs these relationships must be
|
|||
|
constantly checked when they prepare the protection... i.e. when
|
|||
|
they are writing the protection code.
|
|||
|
Most of the time all these data will therefore dwell inside
|
|||
|
a small stack... that means they will be "visible" in the SAME
|
|||
|
"watchwindow" inside the protectionist's debugger... and they use
|
|||
|
the same turbodebugger (or Winice) YOU are using!
|
|||
|
This means that most of the time the "ECHO" will swell not
|
|||
|
very far away from the USER INPUT. Therefore proceed as follows:
|
|||
|
|
|||
|
Fire Winice
|
|||
|
Fire Winformant
|
|||
|
Choose HELP
|
|||
|
Choose REGISTRATION
|
|||
|
Fill the registration fields
|
|||
|
this is mine: "+ORC+ORC" as "Registrant"
|
|||
|
and "12121212" as "Activation" code
|
|||
|
CTRL+D ;switch to Winice
|
|||
|
task ;let's see the names
|
|||
|
|
|||
|
:task
|
|||
|
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?
|
|||
|
|
|||
|
:hwnd diskomat
|
|||
|
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
|
|||
|
3758(2) 2C9F DISKOMAT Edit 2C3F:24BE
|
|||
|
37A0(2) 2C9F DISKOMAT Button 2C3F:1CEA
|
|||
|
37E4(2) 2C9F DISKOMAT Button 2C3F:1CEA
|
|||
|
... and many more irrelevant windows.
|
|||
|
|
|||
|
bmsg relevant_window wm_gettext ;let's pinpoint the code, here
|
|||
|
;the relevant window is the first "edit" one (obviously),
|
|||
|
;i.e. wHnd 3710 you could also use GetWindowsText or
|
|||
|
;GetDlgItmText to locate the relevant routines
|
|||
|
|
|||
|
:bmsg 3710 wm_gettext ;set breakpoint
|
|||
|
CTRL+D ;run the babe
|
|||
|
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 that we have pinpointed the code... let's snoop around
|
|||
|
a little: first thing to do is a good stack command which, here,
|
|||
|
will work OK (in other cracking sessions it may not -magic
|
|||
|
involved- but do not worry: if it does not work immediately, just
|
|||
|
pinpoint a little more... for instance on GetWindowText() (always
|
|||
|
good) or do a BPRW diskomat (also very useful), and then try and
|
|||
|
retry the stack... should this too fail to work, do 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... till you get the "real" list of calls coming from your
|
|||
|
babe's protection (in our example the babe's name is "DISKOMAT").
|
|||
|
|
|||
|
:stack
|
|||
|
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 picture! Immediately BPX on 2C7F:EA20 (on your
|
|||
|
computer the segment will differ, the offset will be the SAME).
|
|||
|
|
|||
|
2C7F:EA20 9A25ABA704 CALL USER!GETWINDOWTEXT
|
|||
|
2C7F:EA25 8E4608 MOV ES,[BP+08]
|
|||
|
2C7F:EA28 26FFB42C02 PUSH WORD PTR ES:[SI+022C]
|
|||
|
2C7F:EA2D 8D865CFF LEA AX,[BP+FF5C]
|
|||
|
2C7F:EA31 16 PUSH SS
|
|||
|
2C7F:EA32 50 PUSH AX
|
|||
|
2C7F:EA33 6A50 PUSH 50
|
|||
|
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 ;strlen "ORC+ORC"
|
|||
|
2C7F:EA44 83C404 ADD SP,+04
|
|||
|
2C7F:EA47 3D2800 CMP AX,0028
|
|||
|
2C7F:EA4A 762C JBE EA78
|
|||
|
...
|
|||
|
2C7F:EA78 8D442C LEA AX,[SI+2C]
|
|||
|
2C7F:EA7B FF7608 PUSH WORD PTR [BP+08]
|
|||
|
2C7F:EA7B FF7608 PUSH WORD PTR [BP+08]
|
|||
|
2C7F:EA7E 50 PUSH AX
|
|||
|
2C7F:EA7F 9AE002772C CALL 2C77:02E0
|
|||
|
2C7F:EA84 0BC0 OR AX,AX
|
|||
|
2C7F:EA86 740F JZ EA97
|
|||
|
2C7F:EA88 687F2C PUSH 2C7F
|
|||
|
2C7F:EA8B 68E4ED PUSH EDE4
|
|||
|
2C7F:EA8E 6A00 PUSH 00
|
|||
|
2C7F:EA90 6A00 PUSH 00
|
|||
|
2C7F:EA92 6A00 PUSH 00
|
|||
|
2C7F:EA94 E94501 JMP EBDC
|
|||
|
2C7F:EA97 8D46AE LEA AX,[BP-52] ;load ptr "+ORC+ORC"
|
|||
|
2C7F:EA9A 16 PUSH SS ;various algor on input
|
|||
|
2C7F:EA9B 50 PUSH AX ;we do not care
|
|||
|
2C7F:EA9C 8D860AFF LEA AX,[BP+FF0A]
|
|||
|
2C7F:EAA0 16 PUSH SS
|
|||
|
2C7F:EAA1 50 PUSH AX
|
|||
|
2C7F:EAA2 6A51 PUSH 51
|
|||
|
2C7F:EAA4 8D442C LEA AX,[SI+2C]
|
|||
|
2C7F:EAA7 FF7608 PUSH WORD PTR [BP+08]
|
|||
|
2C7F:EAAA 50 PUSH AX
|
|||
|
2C7F:EAAB 9ABA00772C CALL 2C77:00BA
|
|||
|
2C7F:EAB0 0BC0 OR AX,AX
|
|||
|
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 ;strlen "12121212"
|
|||
|
2C7F:EAC1 83C404 ADD SP,+04
|
|||
|
2C7F:EAC4 50 PUSH AX
|
|||
|
2C7F:EAC5 8D865CFF LEA AX,[BP+FF5C] ;ptr "12121212"
|
|||
|
2C7F:EAC9 16 PUSH SS
|
|||
|
2C7F:EACA 50 PUSH AX
|
|||
|
2C7F:EACB 8D860AFF LEA AX,[BP+FF0A] ...etc
|
|||
|
|
|||
|
OK, it's enough: now what obviously follows is to "algorithmize"
|
|||
|
this second string, and somewhere, then, you'll have a compare
|
|||
|
that checks and divides good guys from bad fellows.
|
|||
|
|
|||
|
BUT NOW IT'S ALSO THE MAGIC MOMENT OF THE ECHO! We know it, we
|
|||
|
feel it: The echo is somewhere... what can we do to find it?
|
|||
|
Should we search "12121212" in memory? No, look how many
|
|||
|
locations we would find...
|
|||
|
|
|||
|
:s 30:0 lffffffff '12121212'
|
|||
|
Pattern Found at 0030:0005AD6A
|
|||
|
Pattern Found at 0030:0048AD6A
|
|||
|
Pattern Found at 0030:007DED98
|
|||
|
Pattern Found at 0030:007E25F8
|
|||
|
Pattern Found at 0030:008E0FE1
|
|||
|
Pattern Found at 0030:008E1433
|
|||
|
Pattern Found at 0030:008E186F
|
|||
|
Pattern Found at 0030:008E1904
|
|||
|
Pattern Found at 0030:008E601A
|
|||
|
Pattern Found at 0030:80509D6A
|
|||
|
Pattern Found at 0030:8145AD6A
|
|||
|
Pattern Not Found
|
|||
|
|
|||
|
And now...should we look for all occurrences of this string
|
|||
|
and get a memory dump of +- 0x90 around it till we find the
|
|||
|
echo... that's not zen... that's boring, even if we know that the
|
|||
|
relevant ones will ALWAYS be the ones that have MORE than
|
|||
|
80000000 in their "offset", i.e., in this case, only two:
|
|||
|
Pattern Found at 0030:80509D6A
|
|||
|
Pattern Found at 0030:8145AD6A
|
|||
|
But this procedure is not always true, and in other
|
|||
|
protection there will be a proliferation of locations with the
|
|||
|
aim of deterring casual crackers... clearly the above method is
|
|||
|
no good... there must be some other way... YES THERE IS!
|
|||
|
THE LAST loading of the numeric input string in the code
|
|||
|
(the one after the strlen count) is most of the time (exspecially
|
|||
|
in Visual Basic and Delphy programs) the "right" one for our
|
|||
|
cracking purposes, coz the protections follow (most of the time)
|
|||
|
this pattern (remember that we are here inside a stack "heavy"
|
|||
|
section of the code... if you want to crack higher I suggest you
|
|||
|
read some good literature about stack working and stack magics
|
|||
|
inside the 80386/80486/80586 processors).
|
|||
|
This is the usual sequence:
|
|||
|
|
|||
|
LOAD NAME
|
|||
|
COUNT NAMELENGTH
|
|||
|
LOAD NAME_AGAIN
|
|||
|
TRANSFORM NAME
|
|||
|
LOAD PASSCODE
|
|||
|
COUNT PASSCODE_LENGTH
|
|||
|
LOAD PASSCODE_AGAIN
|
|||
|
<- ECHO CHECK here
|
|||
|
TRANSFORM PASSCODE
|
|||
|
<- ECHO CHECK here
|
|||
|
COMPARE TRANSFORMED_NAME WITH TRANSFORMED_PASSCODE
|
|||
|
|
|||
|
So... what does this mean? 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
|
|||
|
|
|||
|
2C5F:61E8
|
|||
|
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 00 00 01 00-04 2C 2F 06 AE 24 36 62 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 00 0C 00 BC 02 00 00 12121212........
|
|||
|
00 00 00 00 49 00 BA 0F-AE 24 F2 24 2F 06 00 00 ....I....$.$/...
|
|||
|
AF 17 00 00 00 00 E2 5F-7A 62 FE FF 79 1B BA 0F ......._zb..y...
|
|||
|
96 0B 01 00 02 4E 00 00-37 01 8A 62 D2 0F 8F 17 .....N..7..b....
|
|||
|
2F 06 00 00 00 00 37 01-98 62 20 10 16 03 2F 06 /.....7..b .../.
|
|||
|
C2 62 2B 4F 52 43 2B 4F-52 43 00 0D AE 24 2F 06 .b+ORC+ORC...$/.
|
|||
|
2C5F:62A7
|
|||
|
|
|||
|
and look... everybody is there! The stack pointers points in the
|
|||
|
middle of this dump, at the string "12121212". 0x50 bytes before
|
|||
|
is our good old ECHO (i.e. the CORRECT passnumber) and 0x50 bytes
|
|||
|
afterwards is my beautiful input name "+ORC+ORC".
|
|||
|
Therefore the "right" code for "+ORC+ORC" is 8037-646-3836.
|
|||
|
It cannot be so easy! You'll protest. It is: this crap protection
|
|||
|
is already cracked and hunderts of Visual Basic/Delphy schemes
|
|||
|
are absolutely identical.
|
|||
|
Now begins the hard work: if you really want to learn,
|
|||
|
accomplish the following tasks:
|
|||
|
- First of all "Unregister" and find anew your own code for
|
|||
|
your own handle. *DO NOT* use serial numbers with any other
|
|||
|
name that your own handle.
|
|||
|
- Study the two coding algorithms, the one for the input name
|
|||
|
and the one for the input passnumber, this will be useful
|
|||
|
for ALL your future cracking sessions.
|
|||
|
- Find the compare locations, i.e. the code block that sets
|
|||
|
the two usual flags "good guy, you may move on" and "bad
|
|||
|
cracker, beggar off", and create a patch crack for this
|
|||
|
protection, that will allow anybody, with any name and any
|
|||
|
password number to get through.
|
|||
|
|
|||
|
Please accomplish all of the preceding tasks: once you do it
|
|||
|
you'll have FINISHED the password protection schemes part of my
|
|||
|
tutorial and you'll be able to pass over to the (very
|
|||
|
interesting) world of disabled and crippled functions (all these
|
|||
|
"demos" that do not save and do not print... I'll teach you how
|
|||
|
to do it, starting in Februar 1997).
|
|||
|
|
|||
|
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"
|
|||
|
|
|||
|
+ORC 526164@anon.penet.fi
|
|||
|
|