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