HOW TO CRACK, by +ORC, A TUTORIAL


Lesson C (3): How to crack Windows, Hands on


[INSTANT ACCESS]


 

--------------------------------------------------------

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:



here. 

     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ë



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

                    


E-mail +ORC

+ORC an526164@anon.penet.fi