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
|
||
|