HOW TO CRACK, by +ORC, A TUTORIAL -------------------------------------------------------------- (Htocrk10.txt) Lesson 1: an approach (Htocrk20.txt) Lesson 2: tools and tricks of the trade (Htocrk31.txt) Lesson 3.1: hands on, paper protections (1) (Htocrk32.txt) Lesson 3.2: hands on, paper protections (2) (Htocrk51.txt) Lesson 5.1: disk & CD-Rom access (basics) (Htocrk61.txt) Lesson 6.1: funny tricks (Htocrk81.txt) Lesson 8.1: how to crack Windows, an approach (Htocrk82.txt) Lesson 8.2: how to crack Windows, a deeper approach (Htocrk91.txt) Lesson 9.1: how to crack Windows, hands on (Htocrka1.txt) Lesson A.1: advanced cracking: internet cracking (Unix) (Htocrkc1.txt) Lesson C.1: how to crack, cracking as an art (Htocrkc2.txt) Lesson C.2: how to crack, cracking as an art HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 1: an approach --------------------------------------------------------------------------- [Pooldemo.exe] -------------------------------------- The best way to learn cracking (i.e. understanding, broadly individuating, locating exactly and eliminating or suspending or deferring one or more protection schemes inside a software application you do not possess the source code of) is to begin your tampering experiments using OLDER applications which have OLDER protection schemes. In this way you 'll quickly grasp the base techniques of the trade. Do not forget that the evolution of the protection schemes has not been a one way road... strictly speaking it's not even an evolution: you'll eventually find some very clever new tricks, but most of the time you 'll unearth only various trite repetitions of past (and well known) tricks. This is no wonder: the REAL knowledge of the "commercial" programmers themselves (the "protectionists") is often very limited indeed: they are inclined to use the old methods (albeit somehow changed, sometimes even improved) instead of conceiving new methods. This typical "commercial" degeneration happens every time people act for money instead of doing things for the sake of it or for pleasure. This "commercial" trend is blindly encouraged by the stupid, money-oriented society we are coerced to live in. So I'll begin the "hands on" part (-> starting from lesson 3), using as examples, some "old" applications and some "old" tricks. We'll be able to come later over to the newest protection schemes in order to understand them, and you 'll learn how to defeat this kind of junk too. I'll also explain WHERE you can find a lot of programs to crack for next to no money at all, and HOW 'grossomodo', you should proceed in your work. This tutorial is for people who are getting started with cracking. Maybe you are just contemplating doing some cracking, maybe you have tried it with mixed success. If you are here to get aimed in the right direction, to get off to a good start with the cracking tricks and procedures, then you have come for the right reason. I can't promise you'll get what you want, but I'll do my best. On the other hand, if you have already turned out some working cracking code in assembler and already cracked many different protection schemes, then this tutorial is likely to be on the elementary side for you. (If you want to review a few basics and have no where else pressing to go, then by all means stay). In order to crack successfully you need four basic things: * A passing knowledge of assembler language (the more you know, the better and quicker you crack) * Some intuition * Some help from more experienced cracker * A non mercantile mind (more about this later) The applications you'll use to learn with can be divided into: 1 - Password crippled applications (the easiest to crack) 2 - applications crippled on how many times, or how many days, you use them (fairly easy to crack) 3 - applications crippled on which date you use them before (easy to crack) 4 - applications that have some functions present but disabled (sometimes easy, sometimes difficult) 5 - applications crippled on Disk access (protections schemes that are now defined as "obsolete") and applications crippled on CD-ROM presence (more or less the same methods, but - somehow- not defined as "obsolete") (very easy to crack) 6 - CRYPTOGRAFED ADDS ON (i.e. one of the previous protection schemes, but with some scrambled or self modifying code (XORring and SHRLing codes) (fairly easy to crack) 7 - None of the above (sometimes difficult to crack) WHERE TO GET THE STUFF The recent widespread appearance of "Demo"-CDROM on magazine covers is a treasure for all crackers! A short time after their release you 'll get all the copies that remain unsold for next to free. The demos on CD-ROMs will permit you to gather quickly a lot of applications -old and new- that have somehow been crippled (at times with interesting schemes). Truly a wonderful world of cracking possibilities! Gee! For next to no money you can secure on one CDROM the whole of LOTUS applications (or Microsoft or Wordperfect, or you name them) on "trial for 30 days" or "try it 20 times" editions. You'll really enjoy to crack them, to use them for ever and ever and/or graciously donate them on the Web to the poor lamers that have no money and no brain. GAMES are definitely not to be frowned upon! They are very interesting from a cracker prospective coz they are often "overprotected". With this I mean that they possess protection schemes of a relatively HIGH level hidden inside files that are relatively small. Now, see, it is much more easy, and simple, to track down and eliminate protection schemes inside a single 35.000 bytes long executable file than to locate them inside a collection of many lengthy DLLs and overlaids that could have swollen as long as 2.000.000 bytes each. The lazy bunch of "modern" programmers relies systematically for protection schemes on this "hide the sting in the wide desert" logic. As a matter of fact they are no longer able to program in assembler: they bank more and more on overbloated "fatty" atrocities like Visual Basic, Delphy or Visual C++. (Don't worry... I'll nevertheless teach you how to crack -and quickly- those huge applications too). There is another reason for employing games instead of applications as study material: often EXACTLY THE SAME protection schemes that you find in a simple (and short) shareware game will be used -without much improving- a little later in order to "protect" some huge and extremely expensive graphic application. For this reason in my tutorial we'll often crack games protection schemes, even if we'll later apply what we learn mainly in order to crack the protection schemes of commercial applications, or to crack the access protection routines to remote servers, or BBS, or even ATM (cash dispensers). Here follows an example cracking session, that will show you -I hope- the dos and donts of our art: let's crack together as introductory example a time crippled application. We'll learn later (-> LESSON 4) that all applications that are crippled on time (i.e. "how many times" you use them or "how long" you use them) rely on analogous protection schemes (albeit with a huge palette of small variations): 1- they may have a counter which "clicks" every so often: FIND IT AND DISABLE IT! 2- they may fetch the time_clock interrupts in your machine: INTERCEPT THEM YOURSELF! 3- they may compare a random_seed with a variable: NOOP IT! 4- they may check randomly the date of your other, unrelated, files on the hard disk: find this verification routine and INVERT the JUMPS! I wanted to start with a modern example of this "counter clicks" protection type, just to give you a feeling for cracking, and I have chosen a widely published demo: you should be able to find it pretty easily. In order to show you some of the problems you may encounter we'll crack this example "wrongly" (you'll learn how to crack effectively in the "HANDS ON" lessons). EXAMPLE: ARCADE POOL, Demonstration version, PC Conversion by East Point Software Ltd, (c) Team 17 Software Ltd 1994. This demo has been published by many magazines on their CDRom covers throughout 1995. What follows will be useful even if you do not have our example; nevertheless you should get a copy of this widespread demo in order to better grasp some of the following points. This nice demo of a billiard game is time-crippled. It is crippled on how long you use it: i.e., you can only play 2 minutes, afterwards a "nag" reminder of where and how you can buy the real version snaps: protectionist squalor at its best. So, how do you proceed? Where does the beginning begin? Here is what you could (but not necessarily should) do: Get [Soft-ice] and load it in your config.sys. See the TOOLS OF THE TRADE lesson (-> LESSON 2) about this debugger. Version 2.6 of [Soft-Ice] has been cracked by MARQUIS DE SOIREE and can be found on the Web for free. - vecs s (save all the vectors before loading the babe) - start [pooldemo.exe] - vecs c (vector compare, save a printing of all hooked vectors) - enter and leave Soft-ice a few times to understand what's going on and where in [pooldemo.exe] are we roaming around (you should always check MORE THAN ONCE your findings when you snoop around: nothing moves and confuses pointers in a more frenzied way than good old "inactive" DOS). - have a good look at the map of memory usage ("map") - now "snap_save" the main memory regions where [pooldemo.exe] dwells... snapping saves "photographs" of memory areas. - do not do anything, let just the seconds go by. - "snap_compare" every two or three seconds without moving anything at all on the game board (no mouse_clicking, NOTHING), so that the only changes are (hopefully) the changes caused by the time counters. - snap_compare twice in a second. - snap_compare at second 00:59 and at second 1:01. - snap_compare just before and just after the time limit and the snapping of the nag screen. - Now collect carefully your printed "snaps" data: write clearly on the various sheets the occurrences of the snaps. - now comes the graceful "zen-cracking" moment: Sit down with a dry Martini and Wodka (obviously only russian Wodka will do) and contemplate the printing of the various mutant locations. Feel, perceive, empathize! Look closely at the locations that have changed in the snap compares. Analyze, interpretate, evaluate. - Mmm! Hey! Something fishy is changing there, and there, and there! (you are lucky, few do actually change in this case: only two dozen) - breakpoint on execute at the location that you believe act as a "continuous" counter, i.e. the location that triggers the "a second went by" event when it zeroes. - Now set the occurrence counter of BPX in order to break at the moment where the location "refills" and restarts from the beginning (the equivalent of "one second" went by, let's start anew). Use the occurrence counter in order not to single-step through the program your life long! - IN THIS CASE you 'll quickly locate the refill at location 3DD0. Here follows the "refill" line: xxxx:3DCC C706F1013C00 MOV WORD PTR [01F1], 003C The "3C" byte at xxxx:3DD0 represents a counter_byte... i.e. the program "charges" 3C in this location and then DECs it step by step to 3B, 3A, 39, 38 etc... till 0. When it reaches 0: bingo! Sucker user has lost one second more of his precious two minutes. Now, you would get a first wizard level if you searched further on for the exact point where you get the "nag screen" in order to eliminate the whole witless protection, but you may think you got it already and you remember anyway that the first principle in cracking is the following: "once you can eliminate the effects of a protection, do not look further!" Most of the time this is true: you do not always need to eliminate a "whole" protection scheme (unless you are just studying it for the joy of it). It's normally easier (and quicker) to eliminate the "effects" of a given protection scheme. Unfortunately this is not true in this case. Here you believe that you have already found the way: you got the counter that charges the reverse clock that triggers the particular protection scheme of [pooldemo.exe]. Now you may think that if you could modify the refill_value... say changing "3C" to "EE" (Yeah, the maximum would be FF... but it's always good practice to avoid such extreme values when cracking) you should get four times more playtime for your game... more than enough in order to make the protection scheme useless. So you change location xxxx:3DD0 from "3C" to "EE". To work on bytes you should use a good Hexeditor like PSEDIT (Parity solutions, [Psedit.exe], brilliant shareware: see the "tool of the trade" section) but you could also work with simpler debuggers like [debug] or [symdeb] (-> see lesson 2). If you do, remember to work on a "dead" copy of your crippled [*.exe] file, i.e.: ren POOLDEMO.EXE POOLDEMO.DED symdeb POOLDEMO.DED -s (cs+0000):0 Lffff C7 06 F1 01 C3 <- this string corresponds to the refill line). cs:3E85 <- symdeb gives you two locations as answer cs:3EEA -e cs:3E85+4 EE <- refill changed from C3 to EE -w ren POOLDEMO.DED POOLDEMO.EXE Now you run your tampered pooldemo. You think you cracked it, you glee with satisfaction... but loo! Nothing at all has changed, everything's as lame as before, you still have only 2 minutes playtime. How disappointing: how comez it didn't work? Well, for a start you have not been attentive enough! The search in debug gave you TWO locations, you moron, and not just the one you just tampered with. Check and you 'll see that the second location (cs:3EEA) is a MIRROR/CONTROL location (more on this later). Some times there exist "double" locations... coz at times it's quicker to use a double routine than to use a branching if or switch structure... some times the second locations do mirror the first ones and correct them on the fly if need be. So you need to modify this too... you act as said above but this time you enter in debug a -e cs:3EEA+4 EE before writing back the dead file and then renaming it to exe and then running it... and loo! Hoow sloow! THERE YOU ARE! Your crippled POOLDEMO.EXE is now (sort of) unprotected: You think that you can now play the stupid game up to 12 minutes real time, even if the protection scheme (and the counter) "believes" that it is playing only two minutes. So you begin to play, and the seconds look veeery sloow, and everything seems OK, but -alas- NO! At screen second 28 you get the irritating "two minutes are over" nag screen! Obviously you were dead wrong: the program "knows" the time directly from the timer... you only modified the stupid counter ON THE SCREEN. So it's back to cracking, and now you are angry, and forget the quiet ways of the zen-analyze and begin the heavy cracking you should reserve -if ever- for really complicated schemes. You now start to check the hooked vectors (you did your routinely VECS_save before loading pooldemo in [Soft-ice] and your VECS_compare afterwards) and you see some findings that you believe interesting: vecs c 08 1EFD:84C6 0CD1:17AC <- the clock 09 1EFD:85EC 136A:069C <- the keyboard 22 0BCE:02B1 0BCE:017E <- the terminate That's more like it -you think. Smack at the beginning: the first hooked vector does it! It's good old interrupt_08: the timer_clicker! Some basics for those of you that do not know anything: INT_08 controls indirectly the INT_1C timer interrupt. The 8253 clock chip generates an IRQ_0 hardware interrupt at a rate of 18.2 interrupts per second. This gives control to the ISR (Interrupt Service Routine) that the INT_08 points to... and this should be at 0CD1:17AC, but has been hooked here, by pooldemo, to 1EFD:84C6. One of the actions taken by the INT_08 ISR within the BIOS is to issue a software interrupt call to INT_1C, just in case any software modules within the system have established an intercept. If no intercepts have been established, the default contents of the INT_1C vector point to an iret instruction within the BIOS, so that a null action results. Normally a protectionist would intercept INT_1C, coz at every ISR from INT_08 the CPU would fetch the contents of the corresponding interrupt vector and make an interrupt style call to the code at that address (which should contain the iret at address F000:9876 but can contain any trick they could think of). So -you think- the protectionist hooked here INT_08 directly (a pretty infrequently used protection scheme by the way): What now? A rather drastic measure would be, in such circumstances, to disable the IRQ_0 level timer interrupt, which is controlled by bit 0 of the mask register, at address I/O 0021h. When bit 0 within the mask register is set to 1, no further interrupts will be recognized for this IRQ level. This unfortunately won't work here, but it's an interesting technique per se, so you better learn it anyway, just in case you should need it elsewhere: --- Trick to disable the timer ("IRQ_0 masking" by +ORC) --- * prompt $t and hit ENTER a few times, see how the dos_clock is merrily ticking along? * enter DEBUG.COM * Assemble using the command 'a' - a in al,21 or al,1 out 21,al ret RETURN RETURN <- twice to exit immediate assembler - g 100 <- to run the tiny program. - q <- to quit debug. prompt $t is still on: hit ENTER a few times: whoa! The clock has stopped advancing! Compliments: you loaded the current mask register's contents into AL, you set the mask bit in the bit 0 position (which corresponds to IRQ_0) at then updated the value back to the mask register. When you are ready to activate IRQ_0 events again, reenter DEBUG, run the following and then reset the clock you stopped with DOS TIME command: - a in al,21 and al,fe out 21,al ret RETURN twice - g 100 - q A word of caution: with the timer click disabled some processes will not operate correctly: once you access the diskette drive, the motor will continue to run indefinitely afterwards, etcetera. ------------------------------------------------------- Unfortunately the above technique cannot work with our [pooldemo.exe], where you now are looking closely to the INT_08 hook you found, believing that it hides the protection scheme: herein you find immediately the EoI (End_of_interrupt: MOV AL,20h... OUT 20h,AL). Both controllers have a second port address at 20h (or 0a0h), from which the instructions are given. The most important is the EoI command (20h). This instruction indicates the end of the interrupt handler and frees up the corresponding controller for the next interrupt. If somebody writes a new custom interrupt handler (as many protectionists do), it's up to him to see to it that at the end of the handler the EoI command (20h) is written to either port 20h or port 0a0h. After the EoI follow the usual pushes, then some CALLS then a call that issues some OUT 40,AL that look like timer refreshing (OUT transfers data to an output port and ports 40-42 correspond to the Timer/counter). Some do_maintenance follows, then a double CALL, one more conditional CALL and then a "mysterious" call FAR CS:[AA91] on which depends a byte PTR[970C] that decides another final CALL... then the routine pops all registers and irets away. Ah! You say, and begin disassembling, reverse engineering and looking inside each suspect call (the quicker method in these cases is to breakpoint calls on entrance and see if you find the one that's only called at the awakening of the time limit protection). You work, and work, and work... and eventually find nothing at all, coz the protection of this program is NOT HERE! Back to the zen-analyze of the snap printings... we forsake it too soon, as you will see. If you watch with more attention the compare locations for the range DS:0 DS:FFFF you 'll notice that one of them changes relatively slowly from 0 to 1 to 2 to 3 and so on... the precedent location changes very quickly, and runs the complete cycle 0...FF. That's a counter, at locations DS:0009 and DS:000A! How long will it tick along? Well, we saw above that the "charge" every second is 3C, so it will be x3C*x78=x1C20, coz x78 is 120 seconds, i.e. the two minutes time limit. Now search this 1C20 value around inside the code (protections are most of the time at the beginning of the CS:offset section), and you 'll find quickly what follows: The protection in [pooldemo.exe] is at code_locations CS:0A8A 813E20A7201C CMP WORD PTR [A720], 1C20 compare location A720 with limit 1C20 CS:0A90 7C07 JL okay_play_a_little_more CS:0A92 E834FD CALL beggar_off_time_is_up BINGO!: FOUND! Now let's quickly crack it: ------------------------------------------------ CRACKING POOLDEMO.EXE (by +ORC, January 1996) ren pooldemo.exe pooldemo.ded symdeb pooldemo.ded - s cs:0 Lffff 81 3E 20 A7 20 1C xxxx:yyyy <- this is the answer of the debugger - e xxxx:yyyy+5 4C <- this time limit is much better - w - q ren pooldemo.ded pooldemo.exe ------------------------------------------------- We have done here a "weak" crack: we limited ourselves to accept a (better) time limit, changing it from 1C20 to 4C20 (4 minutes instead of two). We could obviously have done a more radical crack if we had changed the JL (jump lower) instruction in a JMP (jump anyway) instruction. In this case it would have worked, but for reasons that will be explained in lesson 4, you should choose a rather delicate approach in cracking when you deal with time-limit protection schemes. As you have seen, in this artificial cracking session we found the protection scheme after a little snooping around. But, as you will see in the hands on part, there are always MANY ways to crack a single protection scheme. You could -for instance- have found this protection the other way round: set a trace on memory range for the program, restricting the trace to the first part of it (say CS:0 to CS:1000, if you do not fetch anything you can always try the other blocks). Breakpoint at the nag screen, have a look at the last 300-400 backtraced instructions, if you did not move anything, everything will follow a repetitive pattern, until the protection snaps on: ... JL 0A99 CMP BYTE PTR [A72A],01 ... JL 0A99 CMP BYTE PTR [A72A],01 ... for ages and ages and then... ... JL 0A99 E834FD CALL 0759 <- BINGO! (CALL beggar_off_time_is_up) ... there it is, found the other way round. (But this apparently better method is unfortunately very unstable: it depends on your timing of the breaking in and on the distance between protection and nag screen, therefore the somehow more complicated, but more sure previous one should be favoured). The reason why "minimal" approaches in cracking are often more successful than heavy vector_cracking, is that the programs are hardly ever "overprotected", and therefore the protections are seldom difficult to find (and those that are really worth cracking for study reasons). Sometime you don't even need to crack anything at all! Some applications are fully functional -per se-, but have been crippled in a hurry in order to release them as demos. The commercial programmers want only money, do not even try to understand our zen ways, and do not care at all for a well done job. That means, among other things, that the hard disk of the user will be cluttered with files that the main program module never calls. A typical example of this sloppy method is the demo of [Panzer General] from SSI that appeared in the summer '95. This was in reality no less than the complete beta version of the game: you just had to substitute to one of the two "allowed" scenarios one of the 20 or more scenarios of the beta version in order to play them freely... you didn't ever need to crack! The pooldemo crack example above should not discourage you from cracking intuitively. Be careful! Perform a thoroughly zen_analyze before attempting deeper methods: do remember that you want to crack the protection scheme SOMEHOW, and not necessarily following the same line of thought that the programmer eventually WANTED YOU TO CRACK IT with. Well, that's it for this lesson, reader. Not all lessons of my tutorial are on the Web. You 'll obtain the missing lessons IF AND ONLY IF you mail me back (via anon.penet.fi) with some tricks of the trade I may not know that YOU discovered. Mostly I'll actually know them already, but if they are really new you'll be given full credit, and even if they are not, should I judge that you "rediscovered" them with your work, or that you actually did good work on them, I'll send you the remaining lessons nevertheless. Your suggestions and critics on the whole crap I wrote are also welcomed. E-mail +ORC +ORC an526164@anon.penet.fi HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 2: tools and tricks of the trade --------------------------------------------------------------------------- [INDY.EXE] -------------------------------------- LOST IN THE DARK CODEWOODS When you break into a program you end up in portions of code that are unfamiliar to you. It is also not uncommon for the breakpoints to occur outside of the confines of the program you want to crack. Getting your bearings is, in these cases, very important. One of the handiest utilities is the memory dump tool -it tells you where all the device drivers and TSR are loaded, in which memory locations the program you are cracking dwells, how much memory is left and what the next program load point is. The tools you use should report on the following: - the contents of interrupt vectors - the state of the BIOS data area, beginning at address 40:0 - internal structures within DOS, such as the MCB chain, the SFT (System File Table) chain, the chain of installed device drivers, the PSPs and memory allocations associated with installed TSRs - memory allocation statistic from XMS and EMS drivers When seeking to understand a section of foreign code, you must be especially careful to seek the real intent of the code. Consider using a profiler prior to undertaking an analysis of an unfamiliar program. This will help you by ensuring that you don't waste time studying sections of the program that aren't even involved in the protection scheme you are chasing down. Using a utility that charts a program's calling hierarchy can give you an important perspective on how your babe conducts its internal operations. YOUR DEBUGGER: YOUR FAVOURITE TOOL First and foremost, your debugger must be designed for use with resident modules (or must be itself a resident module). Trying to crack with simplistic [debug.com] is a sure way to get absolutely nowhere. We recommend Softice.exe from Nu-Mega technologies (Version 2.6 [S-Ice.exe] has been cracked by MARQUIS DE SOIREE and its vastly available on the Web). You could also use [Periscope] or [Codeview] or Borland's Turbodebugger... all these programs have been boldly cracked and/or distributed and are now on the Web for free... learn how to use YAHOO and find them. In emergency cases you could fix some quick crack using [debug] or [symdeb], but, as said above, most of the time these older debuggers won't do. I'll nevertheless ALWAYS give the final crack procedure for [debug.com], in order to permit even lusers to crack programs. When you first smell a protection, it can be tempting to immediately begin your crack using invasive types of techniques. While there is certainly nothing wrong with this approach, provided that you are fairly familiar with the protection scheme used, going in too deep too soon can be a problem when you don't have a strong hunch. Most of the time you'll end up missing important details. So first of all sit down and ponder... that's the zen-way, the only one that really works. Single-stepping is expensive, not only because of the time it requires but also because of the amount of detail with which you must contend. Your immediate goal is to home in on the protection scheme through a series of successively refined traps, your broader aim is to get an overview idea of the program's action... the wise use of breakpoints will condense these minutiae into an understandable form. The first step is to try to identify the section of the program where the protection scheme is snapping. Once you are able to isolate a certain section of a program, breakpoints can be used to gather a trace history of the program's execution. If your debugger sports a backtrace buffer, logging window, or similar feature, by all means learn how to use it. The debugger it's your best weapon, you must know all the possibilities it offers and all the capabilities it possesses. Having a debugger's display output echoed to a printer is another possibility. Using breakpoints is beneficial for two basic reasons: speed and reduction of detail. Manual single-stepping is invaluable when you are close to the protection scheme, but too much of it will bore you to death. When selecting breakpoint locations and the types of breakpoint to use, it is important to step back once more, drink a cool Martini-Wodka (use only Moskovskaja: non-russian Wodkas are appalling) and ask yourself: "What is this going to tell me?" and "What else will I need to know once the break occurs?". MOST IMPORTANT OF ALL: "Is my current cracking approach the simplest and most direct?", coz you do not want to waste precious cracking time. When devising a set of breakpoints it is wise to consider how "a trail of bread crumbs" can be left. Not allowing for an execution chronicle from the start can mean having to restart a cracking session. Setting breakpoints on certain software interrupt calls is an excellent way to get an overview of a program's operations. The INT_21 DOS services interrupt is probably the most universal useful of these, with BIOS interrupts such as the INT_13 (BIOS Disk services) and INT_16 (BIOS keyboard services) useful for specific cracking. When working with a debugger, evaluative breakpoints are usually your best shot. To avoid having to deal with a plethora of calls, you would want to have a debugger capable of being told to "break on any INT_21 call except where AH == 2C or AH == 0B". A real understanding of the working of a program is surely important, but don't overdo it! To reverse-engineer even a small program can involve many hours of analysis and documentation work. If you'll not be able to use the zen-cracking techniques described in this tutorial (sadly not everybody can) pace yourself and make sure your chair is comfortable: you'll be sitting for quite a spell. Much of the work involved in reverse-engineering consist of chasing down tentacles. In order to understand the operations of one function, you must understand what happens within each of the functions it calls- its child functions. To understand these child functions you must study their children; and so on down the calling hierarchy tree. Then there is the data. Tracing tentacles based on a program's calling hierarchy is a directed process. Each function you encounter is basically a list of other functions you must reckon with. When it comes to analyzing a function's interrelationship with the program's data structure, no such list is provided. You must have instinct, feeling and luck. Data analysis requires more of a broad-based inquisition. For each memory variable you are interested in, you must survey all functions to determine which ones read and write that variable. The use of memory conditional breakpoints and of a disassembler that builds a cross-reference table can make this task a lot easier. (Use Sourcer! It's a fairly good tool and version 4.08 of [sr.exe] has been long ago cracked and distributed on the Web). ALL SYSTEM CALLS IN ONE LOCATION Remember that if the program you are cracking was written in assembler in the first place (very unlikely knowing the laziness of to_days programmers), system calls are probably made directly from the functions which need them. But when a program is developed in a high-level language, it is more likely that common library functions will be used for many operations involving system calls. When a program makes all of its INT_21 calls from the same location, you know that this is certainly the case. Now, what happens sometimes is that the programmers write the whole application in a overbloated language like C++, but are afterwards compelled to "speed up" critical sections of the code writing them in assembler. And loo! A section where you repeatedly find assembler crafted patches is precisely the protection scheme! So you could have a program with all INT_21 calls from the same location but for one or two calls which are coming out of the section where the morons have "hidden" their protection strategy. By just "looking" at the dead code of a program, you should be capable to tell wich parts have been "added on" in a later phase. They presents themselves as unevenness and irregularities, especially if you use an utility that represents graphicallly the code of a program. Protections are often added on at the end of the development. Should you determine that the system calls relevant to your cracking are made from common library functions, all is not lost. The specific function from which these library calls were made, the function you are seeking to locate, is executing at some point in between these calls. Break in with your debugger at the end of the first system call, just where it is returning to the point of call. From there, trace through the remainder of the common library routine until it returns to its caller. In short order, you should find yourself in the function you need to see. The trick is to be able to identify it for what it is. ASCIIZ IN CODE In the interest of gaining an overall familiarity with the program you want to crack, it can be enlightening to use a hex dump utility to examine the message strings contained within the program's binary modules. If the program happens to load its message strings from separate files, your search has just been simplified. Your debugger's memory-dumping feature is one tool that can be useful for this type of exploration. You could also construct a filtering program, which would read a binary file and output all sequences of bytes that are comprised of displayable characters and are over a certain minimum length (the best cracker tools are often the ones you write yourself). When a protection scheme is marked by the issuance of a specific message on the screen, you could go into the program and locate the code that emits this message, and then determine what triggers it. A good way to start the location process is to see if a system call is used to display the string. Interrupt INT_21, INT_10 or INT_29 are usually used to display text messages to the console. When the message's display is not a result of one of these system calls, direct video writing is probably being used. If you know the screen location used, and if that part of video memory is not used for anything else at the time (a big if), a memory write breakpoint could be set on the video buffer address corresponding to the first character's position. If this won't work, use the step-over/step-around tracing technique while watching for the message to appear. Now you found it: from a disassembled listing, you locate the address of the message string and then survey the reminder of the file for any instructions that reference this address. [Sourcer] can generate labels for specific memory locations and a cross-reference table showing where these labelled locations are referenced. Otherwise, load the disassembled listing file into your editor and use its search capabilities. Manually searching for such things in a listing will make you old before your time. CODE AND DATA When stepping through code at the assembler level, watch out for interrupt calls that are followed by data. Sometimes you will find an interrupt call, typically within the range INT_34 to INT_3F, where several bytes immediately following the interrupt instruction will be data rather than code. Be especially suspicious of this type of code-and-data mixture when your debugger's disassembly output of the instructions immediately following an interrupt call doesn't make sense. Sometimes you can determine the offset of the next true instruction by inspecting the following code and data. In other cases, you will have to trace through the interrupt call to see how it accesses the data following the interrupt call instruction and how it manipulates the return address on the stack. HOOKED VECTORS Seeing what interrupt intercepts already exist within a system before running the program you want to crack, as well as what interrupt handlers are established by the target program, can provide useful clues. For example, if a protection establishes an INT_09 intercept just before the snapping of a keyboard verification routine, your range of suspects has just been narrowed significantly. To study the interrupt vector activities of an application, a vector dump map utility is useless. It can't be run while running the application you want to crack. One solution is to run the program under a debugger and watch for system calls to INT_21 functions 25h (set interrupt vector) and 35h (get interrupt vector), but in the event that the program reads and writes interrupt vectors directly, this method will not give you a complete picture. Normally you'll use a spy, trace or "step" utility. APPLYING A MEMORY WRITE BREAKPOINT TO A SPECIFIC VECTOR OR TO THE ENTIRE TABLE is another way to deal with this. Note that some sort of direct vector writing must be occurring if a vector change is detected between system calls. If a vector change is detected during a system call but it isn't function 25h of INT_21, suspect that an IRQ handler may be effecting the change. LITTLE TRICKS OF THE TRADE: * determining interrupt vector addresses **************** How do you determine the interrupt vector addresses? As example let's find the address of the INT_21 interrupt vector. Since the interrupt vector table starts at address 0000:0000 (easy to remember, isn't it?) and there are four bytes per vector, the basic process is to multiply the interrupt number four times and use the result at the offset (on segment zero). 21h + 21h = 42h 42h + 42h = 84h The int_21 vector is located at address 0000:0084 You could also use a calculator, for instance, the address of INT_63 is 63h*4=18ch -> 0000:018C * address conversion *************************************** After a painstaking cracking session, you have finally determined that a byte of memory at address 6049:891C is the trigger. But when you isolate the offending instruction, you find that the address it is generating when the protection occur is different, being 6109:7D1C instead! How can this be? An 80x86 type CPU, when running in real or VM86 mode, uses what is known as segment:offset type addressing. One side effect of this addressing method is that one physical address can be equivalent to many different segment:offset addresses. To find the PHYSICAL ADDRESS for a given segment:offset do the following: - convert the segment portion of the address to a 1-based number by multiplying it by 16 (x10)... it's easy: add 0 at the right end of the number!... 6049 -> 60490 6109 -> 61090 now all you have to do is to add this value to the offset value 60490+891C -> 68DAC 61090+7D1C -> 68DAC <- Got it? And the other way round? If you have a physical address, say 19AC3, and you want to obtain a segment:offset address you must first of all decide in which segment you want the address... if, say, you choose segment 16CC, you proceed as follows: 16CC -> 16CC0 19AC3-16CC0 = 2E03 (offset) address for 19AC3 in segment 16CC = 16CC:2E03 TOOLS OF THE TRADE Before starting this section, for those of you that do not know anything, here is the ARCHIE way you get all the program that do EXIST on the planet: e-mail following 1) (address) archie@archie.univ-rennes1.fr I use this french archie, but you can get a worldwide list using the metacommand "servers" 2) (text) set search sub <- anywhere in string set maxhits 140 <- (100-1000) set maxhitspm 15 <- not just 1 file all over find stepdos <- search e.g. this file Wait two hours, get your post and ftp the file you wanted (and YES!, you 'll find also EVERYTHING else for free on the Web). You could, instead of using archie, also learn how to use YAHOO. [MEMSCAN.EXE] One of the most fascinating tools that I have ever seen is a (very old) program: MEMSCAN.EXE. This program was originally written in 1988 by Scott A. Mebust, running in CGA. It's a "visual" utility: it enables you to see graphically the 1-meg of PC memory in 8 kbyte chunks. It's a powerful tool in order to locate quickly bit mapped graphics and other 'objects' in memory, like program data tables, stack areas, code areas, available RAM, etc. I used this great idea to create (in C) my own tools: a "dead_programs scanner" and an ameliorate version of Memscan itself. Looking at the VISUAL STRUCTURE of a program it's a great help when you'll crack higher levels. [TRACKMEM.COM] A very good tool by James W.Birdsall, tracks memory usage of programs (EMS, XMS, conventional). [SCANCODE.COM] "THE" scancode lister, by the code_masters from clockwork software. The must utility for crackers that do not learn all scancodes by heart. [MAP.EXE] Actually "MAP2", THE memory mapper from the code_masters at clockwork software. It's a very good tool and an interesting one too, coz you get it with the "Nigel" nag screens. They are not difficult to remove (a "passletter" protection scheme, you'll learn how to find and remove it from [Map.exe] in LESSON 3.2). [FILEDUMP.COM] [HEXDUMP.COM] [TDUMP.EXE] [DUMP.EXE] There are hundred of file dump utilities, coz file dumping is one of the first exercise they learn you at C-school. Hexdump.com is 558 bytes long, Tdump.exe 120.704, pick the one you like better or write your own (even better). Filedump.com, by Daniel M.O'Brien, 1046 bytes long, it's nice. [SPRAY.COM] That's a good crack utility indeed! This 1989 program by Daniel M.O'Brien gives you a "post-mortem" picture of your memory. You redirect it to 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 an526164@anon.penet.fi HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 3.1: hands on, paper protections (1) --------------------------------------------------------------------------- [UMS.EXE] [LIGHTSPD.EXE] [GENERAL.EXE] -------------------------------------- SOME PROBLEMS WITH INTEL's INT The INT instruction is the source of a great deal of the flexibility in the PC architecture, because the ability to get and set interrupt vectors means that system services (included DOS itself) are infinitely extensible, replaceable and MONITORABLE. Yet the Int instruction is also remarkably inflexible in two key ways: - an interrupt handler DOES NOT KNOW which interrupt number invoked it. - the int instruction itself expects an IMMEDIATE operand: you cannot write MOV AX,x21, and then INT AX; you must write INT x21. That would be very good indeed for us cracker... unfortunately many high level language compilers compile interrupts into PUSHF and FAR CALL instruction sequences, rather than do an actual INT. Another method is to PUSH the address of the handler on the stack and do RETF to it. Some protection schemes attempt to disguise interrupt calls, 1) camouflaging the code, 2) putting in substitute interrupt instructions which look harmless and modifying them "on the fly" or 3) replicating whole interrupt routines inside the code. This is particularly frequent in the various "disk access" protection schemes that utilize INT_13 (the "disk" interrupt) and will therefore be thoroughly explained in -> lesson 5. A LITTLE BASIC ASSEMBLER In order to understand the protection schemes and to defeat them, you must acquire a passing knowledge of assembler, the "machine language" code. You can find a lot of good, well explained code for free: viruses are one of the best sources for good "tight and tricky" assembler code. You can find the source code of almost all viruses on the web: oddly all the would be hackers seem to have an aberrant passion for this kind of stuff instead of studying cracking techniques. But there are millions of lines of good explained "commercial" assembler code on the net, just fish it out and study it: the more you know, the better you crack. I'll restrict myself to some observations, sprinkled throughout this tutorial. Let's start with some must_know: ------------------------ STRINGS ---------------------------- The string instructions are quite powerful (and play a great role in password protection scheme). ALL of them have the property that: 1) The source of data is described by the combination DS:SI 2) The destination of data is described by the combination ES:DI 3) As part of the operation, the SI and/or DI register(s) is(are) incremented or decremented so the operation can be repeated. ------------------------- JUMPS ----------------------------- JZ ero means what it says JNZ ero means what it says JG reater means "if the SIGNED difference is positive" JA bove means "if the UNSIGNED difference is positive" JL ess means "if the SIGNED difference is negative" JB elow means "if the UNSIGNED difference is negative" JC arry assembles the same as JB, it's a matter of aesthetic choice CRACKING PASSWORD PROTECTED PROGRAMS Refer to lesson one in order to understand why we are using games instead of commercial applications as learn material: they offer the same protection used by the more "serious" applications (or BBS & servers) although inside files that are small enough to be cracked without loosing too much time. A whole series of programs employ copy protection schemes based upon the possess of the original manual or instructions. That's obviously not a very big protection -per se- coz everybody nowadays has access to a photocopier, but it's bothering enough to motivate our cracks and -besides- you'll find the same schemes lurking in many other password protected programs. Usually, at the beginning of the program, a "nag screen" requires a word that the user can find somewhere inside the original manual, something like: "please type in the first word of line 3 of point 3.3.2". Often, in order to avoid mistakes, the program indicates the first letter of the password... the user must therefore only fill the remaining letters. Some examples, some cracks: --------------------------------------------------- UMS (Universal Military Simulator) version 1 by Dr Ezra SIDRAN (c) 1987 Intergalactic Development European Union: Rainbird Software United States: Firebird Software --------------------------------------------------- This very old EGA program is one of the first I cracked in my youth, and it's very interesting coz it employs a very basilar protection scheme (a "PRIMITIVE"! More than 80% of the protection schemes used to day (January 1996) are directly derived from one of the 12 primitives. The nag screen snaps at the beginning and keeps indefinitely asking your answer, only the use of CTRL+C will bring you out of it, back to DOS. That's a clear sign of older protection schemes: newer schemes let you in for only 3 attempts or even only one, and pop out to the OS if you fail. In UMS, besides, there is no "first letter" aid, a later improvement. The cracking procedure for password protected programs is, first of all, to find out where are stored the letters that you type in. So examine your memory map, find out where the program dwells in memory, do a snap save of these memory areas and a series of snap compares as you type your password in. Strangely enough, in the case of UMS, as you type your password there seems to be no difference at all in the memory locations where this program dwells... yet the data must be somewhere... Usually such a situation is a clear sign that an hooked interrupt is used to hide the data. Checking the hooked vectors you find out the following: vecs 00, 02, 22 are hooked where needs be vecs 34-3D are hooked at xxxx:0 vec 3E is hooked at xxxx:00CA Ha! Let's have a closer look at this bizarre 3E hook. Let's search for some words used in the nag_screen and then let's dump the area where we find them (in UMS that will be at 3E_hook address + 7656) and loo! You'll see the content of the nag screen and, immediately afterwards, ALL the passwords "in extenso", i.e. not encoded, not scrambled, nothing at all... THERE THEY ARE (that's a very old protection scheme indeed). You could now, for instance, easily patch all the different passwords to (for instance) "PASS", and this would work... it's a very primitive protection, as we said, nevertheless the use of a hooked vector as hiding place for the protection code is not yet obsolete... we'll find it elsewhere, in many "more modern" programs. Now let's go deeper and examine the "compare" mechanism, we want to crack, here, not just to patch. Password protected programs (and access protection routines for server and BBS, for that matter) have quite a lot of weak points. The most obvious one (you 'll find out the other when you'll high crack) is that they MUST compare the password of the user with the original one(s). So you do not need to steal a password, you just need to "ear" the echo of the original one in the memory locations used for the compare, or, and that's more correct, to crack the compare mechanism itself so as to make it let you in even with a totally false password. The compare mechanism of UMS can be found setting a breakpoint on the memory range that covers the three locations where the password is stored (and you 'll find these with your search capabilities and with a pair of snap compares): ES:0F8E (here you 'll see a copy of the password that the program is asking) ES:0F5C (here you 'll see a copy of the password that the user types in) INT_3E hook_address + 7656 (here are all the possible passwords in extenso). Here is how the protection scheme looks out: MOV CX,FFFF Charge MAX in CX REPNZ SCASB Scan ES:DI (the user password) NOT CX Now CX holds the number of the character that the user typed in MOV DI,SI Real password offset to DI LDS SI,[BP+0A] User password offset in SI REPZ CMPSB Compares DS:SI with ES:DI (user password and real password) then snap out at CX=0 or at char_different, whichever comes first. Nice, we found the compare schema... how do we crack it now? There are many elegant solutions, but let's remain on a basic level... you look at the code that follows the CMPSB searching the "snapping schema"... here it is immediately afterwards (that's the case in most of the primitives). Remember: we sprung out of the CMPSB check at the first different char, OR at the end of the count of the user chars. Here it is what follows: MOV AL,[SI-01] loads in AL the before_different char of the user password (should be zero) SUB AL,ES:[DI-01] subs with the before_different char of the real password (should be zero) CBW zero flag set, "TRUE", if OK_match Well let's now look for the next JZ near (it's a "74" code) CS:IP 740D JZ location no_good Wait, let's continue a little... is there another check (often you have a double check on DI)... yes there is! CS:IP 7590 JNZ location no_good Cracking such a schema is very easy: you just need to substitute 75 to 74 and 74 to 75: transform your JZ in a JNZ and the JNZ in a JZ... now you will always pass, no matter what you write, unless you exactly guess the password! Now let's quickly crack it: ------------------------------------------------ CRACKING UMS.EXE (by +ORC, January 1996) ren ums.exe ums.ded symdeb ums.ded - s (cs+0000):0 Lffff 74 0D 1E B8 C2 3F (nothing) - s (cs+1000):0 Lffff 74 0D 1E B8 C2 3F (nothing) - s (cs+2000):0 lffff 74 0D 1E B8 C2 3F xxxx:yyyy (this is the answer of the debugger) - e xxxx:yyyy 75 - e xxxx:yyyy+17 74 - w - q ren ums.ded ums.exe ------------------------------------------------- In the debug/symdeb crack above we use as search string the bytes comprising and following immediately the first JZ. I know, I know... we saw them in [Soft-ice] and we could have modified them there, but I'm teaching also pupils who may not have [Soft-ice]. Note that the program is x431A0 bytes long, and therefore has a BX=4 sectors adding to the CX=31A0 in the initial registers... that's the reason I wanted to examine all the sectors (even if I knew that the snap was in sector (cs+2000): that's good practice! If you do not find your string in the first sector you must search for it in the next sectors, till you find it, coz in many programs there may be MORE THAN ONE repetitions of the same schema (more about this double check later). That's it, pupils, that's the way to crack old [UMS.EXE]. Let's go over, now, to more elaborate and more modern password protection schemes. -------------------------------------------------------- LIGHTSPEED, from Microprose (we crack here version 461.01) -------------------------------------------------------- This program, released in 1990, operates a more "modern" variation of the previous scheme. You 'll find this variation in many access routines of remote servers (and this makes it very interesting indeed). Let's begin as usual, with our hooked vectors examination and our snap compares. Hooked vectors: 00, 08, 1B, 22, 23: nothing particular. The snap_comparisons of the main memory area -as you type the password in- gives more than six pages of changing locations... that's clearly much too much to examine. What now? Sit down, have a Martini Wodka (I'm afraid that only Moskovskaja 'll do) and meditate. Get the memory map of the program's layout. Start anew: snap_save (before typing anything in). Type as password "ABCDE". Get the print of the snap compares. Sit down, sip Martini Wodka, relax. You know that the code for A is x41, for B x42, for C x43 and so on... and in the snap_compares, that you made between letters, you 'll have only some locations with these values changing. Focus on these. You 'll soon enough find out that for LIGHTSPEED absolute location (in my computer) 404307, i.e.: relative locations (in my computer) 30BE:F857 or 4043:0007 evoke the characters you type, i.e. something like ----------------------------------------------------- F855 F856 F857 F858 F859... 41 3E first_ready_letter your_1st_letter your_2nd_one... ----------------------------------------------------- Inspecting the same prints, you 'll find out that absolute location 30C64 (imc) or relative location 30BE:F83E evokes the LAST character you typed in. The relative code line is: CS:0097 MOV AX,[BP-08] where SS:F83E = 00+letter_code Now breakpoint at these locations and investigate what's going on (for instance, the instruction that follows is CS:009A MOV [BX], AX and this means that the code of the letter you just typed in will be now copied in BX=F85A. What else can you do? Time to use a little intuition: look for an instruction "CMP AX,000D", which is the typical "IF the user hits ENTER then" instruction, coz "x1D" its the ENTER keystroke. This must be somewhere around here. Ha! You 'll soon enough find the line CS:0073 3D0D00 CMP AX,000D And now the way is open to the crack. But YOU DO NOT NEED ALL THIS! Since the password protection schemes are -as I told you- all more or less the same, I would suggest that you use first of all following trick: in the largest part of the program (use memory map to see where the program dwells) search the "F3A6" sequence, that's instruction REPZ CMPSB. In the case of Lightspd you 'll get as answer FOUR addresses with this instruction: (pgsg=program main segment) pgsg:C6F9 pgsg:E5CA pgsg:E63E pgsg:EAB0 There you are! Only four... have a short look at each of them: you 'll see that the second one (pgsg:E5CA) is the "good" one. The compare mechanism in this program of 1990 it's more or less the same as in 1987'UMS (and do believe me: the same mechanism is still in use to day (1996)! B9FFFF MOV CX,FFFF charge Max in CX F2AE REPNZ SCASB this scans ES:DI (the original password) F7D1 NOT CX so many chars in the original pw 2BF9 SUB DI,CX change DI for compare F3A6 REPZ CMPSB compares DS:SI with ES:DI (real pw with user pw) then snaps out at CX=0 or at char_differs See how easy? They all use the same old tricks the lazy bastards! Here the section is preceded by a small routine to lowercase the user password, coz the original muster is always lowercased. Now you would like, may be, to breakpoint at one of these locations, in order to stop the program "in the snap area" and inspect the snap mechanism... that WILL NOT DO with a "fixed" breakpoint, coz these locations are called by the snap with a different segment:offset numeration as the one you found (that's old dos magic). So you MUST first set a memory_read/write breakpoint on these locations, and then get at them at the snap. Now you can find out the segment:offset used by the snap and only now you'll be able to set a fixed breakpoint (for instance on the NOT CX instruction). Now run the program and breakpoint in: have a dump of the ES:DI and see the original password. How nice! We have now the original password in extenso in our memory dump window. That's the "echo". By the way, there is a whole school of cracking devoted to find and use these echoes... we work on different paths, nevertheless password fishing can be interesting: where are the password stored? From which locations do they come from? A common practice of the protectionists is to hide them in different files, far away, or in hooked vectors, or in SMC parts. This is a program of 1990, that differs in respect to UMS: the passwords are not "hidden" inside a hooked vector, coz that's a pretty stupid protection: any hexdump utility would still permit you to see them. Here the passwords are encoded (albeit in a very primitive manner): looking for them (with memory range breakpoints) you'll quickly find a section of the program code that looks like this: sg:0118 8C 91 9D 95 9B 8D 00 B8 EC 94 9B 8D 8F 8B 9B sg:0128 94 9B 8D 00 AE EC 9C 9B 8A 9B 86 00 A9 EC 91 This is a typical encoded matrix, with clear 00 fences between the encoded passwords. Ha! If all codes where so easy to crack! This is no better than children's crypt! It's a NEG matrix! And there is direct correspondence: 91=6F="o"; 92=6E="n"; 93=6D="m" and so on... Ha! Let's now leave the "hidden" passwords and proceed with our cracking... let's follow the snap procedure after the REPZ CMPSB instruction looking for the "jump to OK" instruction... F3A6 REPZ CMPSB ; compares DS:SI with ES:DI 7405 JZ preserved_AX=0000 <--- Here the first JZ 1BC0 SBB AX,AX ADFFFF SBB AX,FFFF :preserved_AX=0000 8BF3 MOV SI,BX 8BFA MOV DI,DX 5D POP BP CB RETF .... 83C404 ADD SP,+04 0BC0 OR AX,AX 7509 JNZ 0276 <------ And here it is! Now, remembering the UMS crack, you would probably want to change the JZ instruction in a JNZ instruction (you tried it on the fly INSIDE [Soft-Ice] and it did work!), the "74" with a "75" also. And then you would like to change the JNZ instruction in a JZ instruction... Please feel free to try it... it will NOT work! (You will not even find the second JNZ in the program code). You should always be aware of the SMC (self modifying code) protections: parts of the code my be decrypted "on the fly", as needs arise, by the program. The code you modify while the program is running may be different from the code of the "dead" program. Here we have a small "improvement" of the primitive: the same instruction is used as "muster" for manipulation of other parts of the program... if you do change it in a JNZ you get an overlay message and the program pops out with instability! You cannot easily modify the JNZ instruction either, coz the part after the RETF will be compiled "on the fly" by lightspeed, and you would therefore have to search the decryption mechanism and modify the original encrypted byte somewhere... and may be they do encrypt it twice... and then you must hack all night long... very annoying. So do the following: back to the snap, a sip of martini- Wodka and meditate: loo! The only thing that happens after the JZ, is the setting of the AX register to flag *FALSE* (AX=1... that's what the two SBB instructions do) if the snap went out with a non-zero flag... i.e. if you did not know the password. So let's nop the 5 bytes of the two SBB instructions, or, more elegantly, let's have a INC AX, DEC AX, NOP, INC AX, DEC AX sequence instead of the two SBB! There is a good reason to use a sequence of working instructions instead of a series of NOPs: recent protection schemes "smell" patched nops inside the program and trash everything if they find more than -say- three consecutive NOPs! You should always try to choose THE LESS INTRUSIVE and MORE "CAMOUFLAGED" solution when you crack! Eliminating the two SBBs we get our crack! No need to bother with the second JNZ either... the program will work as if you got the password if you have it AND if you do not (that's better as the previous type of crack -seen for UMS- when you crack computer accesses: hereby the legitimate user will not have any suspects 'coz the system will not shut him out... everybody will access: the good guys and the bad ones... that's nice isn't it?). Now let's quickly crack LIGHTSPD: ------------------------------------------------ CRACKING LIGHTSPEED.EXE (by +ORC, January 1996) ren lightspd.exe lightspd.ded symdeb lightspd.ded - s (cs+0000):0 Lffff 2B F9 F3 A6 74 xxxx:yyyy (this is the answer of the debugger) - s (cs+1000):0 Lffff 2B F9 F3 A6 74 (nothing, but do it nonetheless, just to be sure) - s (cs+2000):0 lffff 2B F9 F3 A6 74 (nothing, just to be sure, now it's enough) - e xxxx:yyyy+6 40 [SPACE] 48 [SP] 90 [SP] 40 [SP] 48 - w - q ren lightspd.ded lightspd.exe ------------------------------------------------- All this CMPSB is very common. Some programs, nevertheless, utilize a password protection scheme that is slightly different, and does not rely on a F3A6 REPZ CMPSB instruction. Let's analyze, for instance, the protection scheme used in the first version of Perfect general I from QQP-White wolf, July 1992. When you break in, at the nag screen, you are in the middle of the BIOS procedures, coz the program expects your input (your password, that's is). You 'll quickly find out (MAP MEMORY USAGE!) that [General.exe] dwells in two main areas; Setting breakpoints on memory write you 'll find out that the memory area "queried" by the protection mechanism is xxxx:1180 to xxxx:11C0 where xxxx represents the second of the memory segments where the program dwells. Now do the following (a very common cracking procedure): * Breakpoint on memory range WRITE for the small memory area touched by the program in querying you for the password. * Breakpoint TRACE on the whole memory range of the MAIN CODE. * Run anew everything It's already done! Now it's your intuition that should work a little: Here the last 9 traces (traces [!], not instructions following on a line) before the calling of the procedure sniffing your memory area: -9 xxxx:0185 7425 JZ somewhere, not taken -8 xxxx:0187 2D1103 SUB AX,0311 -7 xxxx:018A 7430 JZ somewhere, not taken -6 xxxx:018C 2DFD04 SUB AX,04FD -5 xxxx:018F 7443 JZ next_trace, taken -4 xxxx:01D4 E85500 CALL funny_procedure -3 xxxx:022C 803E8F8C11 CMP BYTE PTR[8C8F],11 -2 xxxx:0231 750E JNZ somewhere, not taken -1 xxxx:0233 9A0A0AC33E CALL procedure_that_sniffs our_memory_area Well, the call to funny_procedure followed by a byte compare "feels" fishy from very far away, so let's immediately look at this part of the code of [General.exe] :funny_procedure 803E8F8C11 CMP BYTE PTR[8C8F],11 750E JNZ compare_byte 9A0A0AC333 CALL procedure_that_sniffs 0AC0 OR AL,AL 7405 J2 compare_byte C6068F8C2A MOV BYTE PTR [8C8F],2A :compare_byte 803E8F8C2A CMP BYTE PTR [8C8F],2A 7504 JNZ after_ret B001 MOV AL,01 C3 RET You should be enough crack-able ;=), by this lesson, to notice immediately the inconsistency of the two successive instructions MOV 2A and CMP 2A, coz there would be no sense in comparing the "2A" in order to JNZ to after_ret if you just had the 2A set with the precedent MOV instruction... but the first JNZ jumps to the compare WITHOUT putting the "2A" inside. And "2A" is nothing else as the "*" symbol, commonly used by programmer as "OK"! This protection works in the following way (this is the above code explained): - compare holy_location with 11 - jump non zero to compare holy_loc with "*" - else call sniffing protection part - or al,al (al must be zero, else) - jump zero to compare holy_loc with "*" - if al was zero mov "*" inside holy_loc - compare holy_loc with "*" - if there is a difference then JNZ beggar_off_ugly_copier - else ret_ahead_nice_buyer Now let's quickly crack it: ------------------------------------------------ CRACKING GENERAL.EXE (by +ORC, January 1996) ren general.exe general.ded symdeb general.ded - s (cs+0000):0 Lffff 8C 11 75 0E xxxx:yyyy (this is the answer of the debugger) - e xxxx:yyyy+2 EB [SPACE] 09 - w - q ren general.ded general.exe ------------------------------------------------- And in this way you changed the JNZ to the cmp "*" instruction in a JMP to the mov "*" instruction. So no more nag screens, no more protections... serene, placid, untroubled [general.exe]. Well, that's it for this lesson, reader. Not all lessons of my tutorial are on the Web. You 'll obtain the missing lessons IF AND ONLY IF you mail me back (via anon.penet.fi) with some tricks of the trade I may not know that YOU discovered. Mostly I'll actually know them already, but if they are really new you'll be given full credit, and even if they are not, should I judge that you "rediscovered" them with your work, or that you actually did good work on them, I'll send you the remaining lessons nevertheless. Your suggestions and critics on the whole crap I wrote are also welcomed. E-mail +ORC +ORC an526164@anon.penet.fi HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 3.2: hands on, paper protections (2) --------------------------------------------------------------------------- [TOP.EXE] [F19.EXE] [POPULOUS.EXE] [MAP.EXE] -------------------------------------- You have seen in the previous lesson that the use of a password protection, independently of the coding and hiding methods used to store them in memory, implies the use of a comparing procedure with the password that the user types in. You therefore have many options to begin your cracking work: - find the location of the user password - find the "echo" in memory of the real password - find the routine that compares both - find the passwords hideout and encryption type - find the go_ahead_nice_buyer exit or jump - find the beggar_off_ugly_copier exit or jump just to name the more obvious ones. In order to make things more difficult for us crackers, the protectionists have devised many counter-strategies, the more obvious ones being: - keeping the various part of the store/compare/hide routines well apart in code (no match for zen-cracking); - filling these routines with "bogus" compares, bogus jumps and bogus variables, in order to make things more difficult for the crack (no match for decent crackers); - disseminating the code with anti-debugger tricks, like INT_3 instructions or jumps in and out protected mode (no match for our beloved [Soft-Ice]); - trying to eliminate the need for passwords altogether letting the user input "one letter" or "one number" or "one image" as answer to some variable question. In this lesson I'll teach you how to crack these "passletters" protection techniques. Let's first resume the "uses" of a password protection: PASSWORDS AS PERMISSION TO ACCESS These passwords serve to acknowledge that a legitimate user is using the program. This is the type of password that you'll find, for example, protecting your user account on Compuserve, on Networks or even in ATM machines used by banks or corporations. These require a little hardwiring to crack: ATM passnumber protection schemes rely on an answer from the central computer (they do NOT verify only the three magnetic areas in the magnetic strip on the card). The lines between ATM's & their hosts are usually 'weak' in the sense that the information transmitted on them is generally not encrypted in any way. (Some banks use encrypted information, but this is fairly easy to crack too). So for ATMs you should do the following 1) cross over the dedicated line between the ATM and the host; 2) insert your computer between the ATM and the host; 3) Listen to the "normal" messages and DO NOT INTERFERE YET; 4) Try out some operations with a legal card, make some mistakes, take note of the various codes; 5) When you are ready insert a fraudulent card into the ATM. Now the following happens: - the ATM sends a signal to the host, saying "Hey! Can I give this guy money, or is he broke, or is this funny card invalid?"; - the microcomputer intercepts the signal from the host, discards it, sends on the "there's no one using the ATM" signal; - the host gets the "no one using" signal and sends back its "good, keep watching out if somebody comes by, and for God's sake don't spit out any money on the street!" signal to the ATM; - the microcomputer intercepts this signal (again), throws it away (again), and sends the "Wow! That guy is like TOO rich! Give him as much money as he wants. In fact, he's so loaded, give him ALL the cash we have! He is a really valued customer." signal. - the ATM obediently dispenses cash till the cows come home. All this should be possible, but as a matter of fact it has not much to do with cracking, unless there is a special software protection on the line... so if you want to work on ATMs contact our fellow phreakers/hackers and learn their trade... and please remember to hack only cash dispenser that DO NOT HAVE a control camera :=) PASSWORDS AS REGISTRATION This type of password is often used in shareware programs. When you register the shareware program, you are sent a password that you use to upgrade your shareware program to a complete and more powerful version. This method, used frequently for commercial applications, has recently been used quite a lot by many windows applications that come "crippled" on the magazines cover CD-roms, requiring you to telephone a hot line (and paying) in order to get the "unique key" to unlock the "special protection". It's all bullshit: we'll learn in the "how to crack windows" lessons how easy it is to disable the various routines that verify your entry. PASSWORDS AS COPY PROTECTIONS This type of password is often used for games and entertainment software. The password query does not usually appear any more at the start of the program, or as the program is loading. Instead, the password query appears after one or more levels are completed (this innovation was pioneered by "EOB I" and the "Ultima" series) or when the user reloads a saved game or session. DONGLE PASSWORDS A few extremely expensive programs use a dongle (also called an hardware key). A dongle is a small hardware device containing a password or checksum which plugs into either a parallel or a serial port. Some specially designed dongles even include complete program routines. Dongles can be cracked, but the amount of work involved is considerable and the trial and error procedure currently used to crack them via software is extremely tedious. It took me more than a week to crack MULTITERM, Luxembourger dongle protected program. The quickest method to crack dongle protected programs, involves the use of pretty complicated hardware devices that cannot be dealt with here. I myself have only seldom seen them, and do not like at all to crack dongles via software, coz it requires a huge amount of zen thinking and of luck and of time. If you want more information on the hardware way to crack dongles, try to contact the older ones on the appropriate web sites, they may even answer you if you are nice, humble and really technically interested. The obvious principle, that applies to the software password types mentioned above is the following: The better the password is hidden, and the better it is encrypted, the more secure the program will be. The password may be - encrypted and/or - in a hooked vector and/or - in an external file and/or - in a SMC (Self modifying code) part Let's finally inspect the common "ready_made" protection schemes (used by many programmers that do not program themselves): * password read in * letters added to a key to be entered * complement of the letters formed xoring with 255 * saved key (1 char) * saved password (256 chars) * saved checksum (1 char), as protection, against simple manipulations * generating file PASSWORD.DAT with password, to be inserted inside a different file than the one containing the calling routine Now the lazy programmer that wants to "protect" his program searches first the file where the password is stored, then loads the key, the password and the checksum. He uses a decrypt procedure to decrypt the password and a check_checksum procedure to check whether the password was modified. All this is obviously crackabe in few seconds. [PASSWORD ACCESS INSIDE THE SETUP] Some computers have a password protected access INSIDE the Setup (at the beginning), the protection scheme does not allow a boot with a floppy and does not allow a setup modify. In these cases the only possible crack is an old hack method: * open the PC * find on the motherboard a small jumper (bridge) with the words "Pw" * take it away * PC on * run the setup with F1 or Del (depending from the BIOS) (the protection will not work any more) * deactivate inside the setup the option password * PC off * put the small jumper (bridge) back again * close the PC * PC on, cracked (if you want to be nasty you could now use the setup to set YOUR password) If you want to know more about access refuse and access denying, encryption and locking of the FAT tables, get from the web, and study, the (very well written) code of a virus called "Monkey", that does exactly this kind of devastation. Virus studying is, in general, very useful for cracking purposes, coz the virus'code is at times - very well written (pure, tight assembly) - using concealing techniques not much different from the protection schemes (often far superior) - using the most recent and best SMC (self modifying code) tricks But, and this is very important, do not believe that the protection schemes are very complicated! Most of the time the protection used are incredibly ordinary: as a final example of our paper protection schemes, let's take a program released not long ago (1994), but with a ridiculous protection scheme: TOP (Tiger on the prowl) a simulation from HPS. Here the cracking is straightforward: - MAP(memory_usage) and find main_sector - type "AAAA" as password - (s)earch main_sector:0 lffff "AAAA" - dump L80 "AAAA" location -40 (gives you a "wide" dump), this gives you already the "echo" of the correct password - breakpoint on memory read & write to "AAAA" location and backtrace the complete main_sector it's done! Here the code_lines that do protect TOP: 8A841C12 MOV AL,[SI+121C] move in AL first user letter 3A840812 CMP AL,[SI+1208] compare with echo 7402 JZ go_ahead_nice_buyer EB13 JMP beggar_off_ugly_cracker Now let's quickly crack it: ------------------------------------------------ CRACKING TOP.EXE (by +ORC, January 1996) ren top.exe top.ded symdeb top.ded - s (cs+0000):0 Lffff 8A 84 1C 12 3A 84 xxxx:yyyy (this is the answer of the debugger) - e xxxx:yyyy+2 08 (instead of 1C) - w - q ren top.ded top.exe ------------------------------------------------- And you changed the MOV AL, [SI+121C] instruction in a MOV AL, [SI+1208] instruction... it is now reading the ECHO instead of the characters you typed in... no wonder that the ECHO does compare exactly with itself... and you pass! "SOMETHING FISHY UNDER COVERS" Back to the "Passletter" type of password protected programs. Let's take as an example the protection used in a game of 1990: "F19", where the protection scheme asks you to identify a particular plane's silhouette. This kind of protection is used in order to avoid the use of memory locations where the passwords are stored: we saw in the first part of our "passwords hands on" how easy it is to crack those schemes. To crack this kind of protection, you could try a technique know as "memory snuffing". The protected program, START.EXE, install itself first at location xxxx:0000 with a length of 6C62 bytes, but proceeds to a relocation of its modules (with some SMC, self modifying code parts) in different locations. What does all this mean? Well, this could mean quite many things... the most important one for crackers is that the protection code will probably snap way ahead of the actual user input phase. Now you 'll quickly find out that the routine determining (randomly) which plane is being chosen, leaves the progressive number of this plane in one memory location: (imc) 43CD:DADA. This brings us to the random triggering mechanism: E87FAF CALL random_seed 83C402 ADD SP,02 8946E8 MOV [BP-18],AX and ds:(BP-18) is the location you are looking for Now, every time this random triggers, you get a different number (00-x14) in this location, corresponding to the different plane the user should choose. The random seed routine, evidently, comes back with the random seed in AX... what we now need is to zero it: the user will always have to choose the same plane: "plane 0", and he will have given the correct answer. Note how elegant all this is: we do not need to interfere with the whole mouse pointing routines, nor with the actual choosing of the planes... the random seed may choose whatever plane it wishes... the memory location for this choice will always report the (legitimate) choice of zero. So, let's quickly crack this program: --------------------------------------------------- CRACKING "F19" [START.EXE] (by +ORC, January 1996) ren start.exe start.ded <- let's have a dead file symdeb start.ded <- let's debug it - s cs:O lffff 83 C4 02 89 46 E8 <- search ADD SP,02 xxxx:yyyy <- debugger's answer - e xxxx:yyyy 58 [SPACE] 31 [SPACE] C0 [SPACE] - w <- write the crack - q <- back to the OS ren start.ded start.exe <- re-write the exe ---------------------------------------------------- You just transformed the instruction you searched for 83C402 ADD SP,+02 in the following sequence: 58 POP AX <- respecting ADD SP,+02 31C0 XOR AX,AX <- xoring to zero (the POP AX instruction increments the stack pointer by 2, in order to respect the previous ADD SP,+02). Well, nice. It's getting easier, isnt'it? Now let's take as example a protection that has no "echo" in memory. (At the beginning this was a smart idea: "the cracker won't find the correct password, 'coz it's not there, ah!". We'll now therefore crack one of the first programs that used this scheme: [Populous.exe], from Bullfrog. [POPULOUS.EXE] A old example of the protection scheme "password that is not a password" can be found in [Populous.exe], from Bullfrog. It's a very widespread program, and you'll surely be able to find a copy of it in order to follow this lesson. The program asks for the identification of a particular "shield", a combination of letters of various length: the memory location were the user password is stored is easily found, but there is (apparently) no "echo" of the correct password. You should be able, by now, to find by yourself the memory location were the user password is stored. Set a breakpoint memory read & write on this area, and you 'll soon come to the following section of code: F7AE4EFF IMUL WORD PTR [BP+FF4E] <- IMUL with magic_Nø 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:[0166] 07 POP ES AC LODSB ... You could already eliminate the delay and you could already force always the same passletter, in order to temperate the effects of the protection... but we crack deep!: let's do the job and track back the caller! The previous routine is called from the following section of the code: 91 XCHG AX,CX 6792 XCHG AX,DX 28939193 SUB [BP+DI+9391],DL 2394AA94 AND DX,[SI+94AA] 2EC7064B880100 MOV WORD PTR CS:[884B],0001 2E803E5C0106 CMP BYTE PTR CS:[015C],06 7416 JZ ret <- Ha! jumping PUSHa & POPa! 505351525756 PUSH the lot E882F3 CALL 8870 2E3B064B88 CMP AX,CS:[884B] 7307 JAE after RET <- Ha! Not taking the RET! 5E5F5A595B58 POP the lot C3 RET ... <- some more instructions E86700 CALL delay_user BE9195 MOV SI,9591 2E8B3E255C MOV DI,CS:[5C25] 83EF16 SUB DI,+16 2E8A263D01 MOV AH,CS:[013D] 50 PUSH AH E892C7 CALL routine_LODSB <-- HERE! B42C MOV AH,2C CD21 INT 21 <- get seconds in DH 80E60F AND DH,0F 80C641 ADD DH,41 58 POP AX 8AC6 MOV AL,DH 83EF04 SUB DI,+4 AB STOSW E85A00 CALL INT_16_AH=01 B400 MOV AH,00 CD16 INT 16 24DF AND AL,DF <- code user's letter_answer 3AC6 CMP AL,DH <- pass_compare 75F3 JNZ CALL INT_16_AH=01 E807F3 go_ahead You just need to look at these instructions to feel it: I think that unnecessary code segments (in this case protections) are somehow like little snakes moving under a cover: you cannot easily say what's exactly going on yet, but you could bet that there is something fishy going on. Look at the code preceding your LODSB routine call: you find two JUMPS there: a JZ ret, that leaves a lot of pusha and popa aside, and a JAE after RET, that does not take the previous ret. If you did smell something here you are thoroughly right: The first JZ triggers the NIGEL screen protection, and the second JAE does THE SAME THING (as usual, there are always redundances, exactly as there are a lot of possibilities to disable a single protection). Now you know... you can disable this protection at different points: the two easiest blueprints being 1) to change 7416 (JZ ret) in a EB16 (JMP ret anyway) 2) to change 7307 (JAE after ret) in a 7306 (JAE ret). We have not terminated yet: if you try locating this part of the code in order to change it, you won't have any luck: it's a SMC (Self modifying code) part: it is loaded -partly- from other sections of the code (here without any encryption). You must therefore first of all set a breakpoint on memory range; find out the LODSW routine; find out the real area; dump that memory region; find out a search sequence for the "dead" code... and finally modify the "dead" program. Now let's quickly crack it: ------------------------------------------------ CRACKING MEM.EXE (version 2) (by +ORC, January 1996) ren map.exe map.ded symdeb map.ded - s (cs+0000):0 Lffff 74 16 50 53 51 52 57 xxxx:yyyy <- this is the debugger's answer - e xxxx:yyyy EB - w - q ren map.ded map.exe ------------------------------------------------- Now you have done it, NIGEL has been cracked! Well, that's it for this lesson, reader. Not all lessons of my tutorial are on the Web. You 'll obtain the missing lessons IF AND ONLY IF you mail me back (via anon.penet.fi) with some tricks of the trade I may not know that YOU discovered. Mostly I'll actually know them already, but if they are really new you'll be given full credit, and even if they are not, should I judge that you "rediscovered" them with your work, or that you actually did good work on them, I'll send you the remaining lessons nevertheless. Your suggestions and critics on the whole crap I wrote are also welcomed. E-mail +ORC +ORC an526164@anon.penet.fi HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 5.1: Disk & CD-Rom access (basics) --------------------------------------------------------------------------- [MARIO ANDRETTI] [REACH FOR THE SKY] [FS v.2.12] -------------------------------------- LESSON 5 (1) - HOW TO CRACK, HANDS ON - Disk/CDROM access (plus bypasses "on the fly") Somewhere I have to put the bypasses (loader programs) in this tutorial, allow me to put them here: Preparing a loader to bypass a protection [MARIO ANDRETTI] At time the protectionists hook vectors in order to impose a particular protection. In this (and similar) cases a good crack-way is to prepare a "loader" program, that "de-hooks" the vector used for the protection. This kind of crack can be used also for internet cracking (on some firewall configurations, see lesson A.2). As example let's take "Mario andretti racing challenge", a stupid game that uses the SAME (!) protection scheme you'll still find to day on some access routines of military servers around the witlessly called "free" world. In order to crack this cram you would prepare a loader on the following lines: loc code instruction what's going on ------------------------------------------------------- :0100 EB44 JMP 0146 ... :0142 0000 <- storing for offset of INT_21 :0144 5887 <- storing for segment of INT_21 :0146 FA CLI :0147 0E PUSH CS :0148 1F POP DS :0149 BCB403 MOV SP,03B4 :014C FB STI :014D 8C1EA901 MOV [01A9],DS <- save DS :0151 8C1EAD01 MOV [01AD],DS three :0155 8C1EB101 MOV [01B1],DS times :0159 B82135 MOV AX,3521 <- get INT_21 :015C CD21 INT 21 in ES:BX :015E 891E4201 MOV [0142],BX <- store offset :0162 8C064401 MOV [0144],ES <- store segment :0166 BA0201 MOV DX,0102 :0169 B82125 MOV AX,2521 <- set INT_21 to :016C CD21 INT 21 DS:0102 :016E 0E PUSH CS :016F 07 POP ES <- ES= current CS :0170 BBB403 MOV BX,03B4 :0173 83C30F ADD BX,+0F :0176 B104 MOV CL,04 :0178 D3EB SHR BX,CL <- BX= 3C :017A B8004A MOV AX,4A00 <- Modify memory block :017D CD21 INT 21 to 3C paragraphs :017F BA9E01 MOV DX,019E <- ds:dx=program name :0182 BBA501 MOV BX,01A5 <- es:bx = param. block :0185 B8004B MOV AX,4B00 <- load ma.com :0188 CD21 INT 21 :018A 2E8B164201 MOV DX,CS:[0142] <- reset old int_21 :018F 2E8E1E4401 MOV DS,CS:[0144] :0194 B82125 MOV AX,2521 :0197 CD21 INT 21 :0199 B8004C MOV AX,4C00 <- terminate with return :019C CD21 INT 21 code :019E 6D612E636F6D00 "ma.com" 0000 fence :01A7 B2015887 :01AB B2015887 :O1AF B2015887 0000 fence let's now prepare a routine that hooks INT_21: push all CMP AX,2500 <- go on if INT_21 service 25 JNZ ret CMP Word Ptr [0065], C00B <- go on if location 65 = C00B JNZ ret MOV Byte Ptr [0060], EB <- crack instructions MOV Byte Ptr [0061], 3C MOV Byte Ptr [0062], 40 <- INC AX MOV Byte Ptr [0063], 90 <- NOP MOV Byte Ptr [0064], 48 <- DEC AX pop all JMP FAR CS:[0142] <- JMP previous INT_21 From now on this loader will work every time that a program with location [0065] containing an 0R AX,AX instruction (0BC0: it's the case of ma.com) calls INT_21 service 25 (hook a vector), the target program will be modified on the fly and will get, at location [0060], the instruction JMP 3C locations ahead, despite the fact that it has routines capable of self checking in order to make sure it has not been modified. The most important thing is the routine that YOU write that will precede the call to INT_21 (or any other INT) service 25 (or any other service) in order to crack on the fly the offending program. I'll show you another one, this one for [Reach for the skies] (reach.com): push all CMP AH,3D <- is it service 3D? (open file) JNZ ret <- no, so ret CMP DX,13CE <- you wanna open file at 13CE? JNZ ret <- no, so ret MOV AX,[BP+04] <- in this case MOV DS,AX CMP Byte Ptr [B6DA],74 <- old instructions JNZ 015B CMP Byte Ptr [B6DB],0F <- ditto JNZ 015B CMP Byte Ptr [B6DC],80 <- ditto, now we now where we are JNZ 015B MOV Byte Ptr [B6DA],EB <- crack MOV Byte Ptr [B697],40 <- camouflaged no-opping MOV Byte Ptr [B698],48 <- cam nop MOV Byte Ptr [B699],90 <- cam nop MOV Byte Ptr [B69A],40 <- cam nop MOV Byte Ptr [B69B],48 <- cam nop MOV DX,CS:[0165] MOV DS,CS:[0167] MOV AX,2521 <- set hook INT 21 POP all JMP FAR CS:[0165] Here you did change the instruction 740F in the instruction EB0F, and you did "noop" the instructions at B697-B69B. (Well, more elegantly than "noop" them with "90" bytes, you choose a INC AX, DEC AX, NOP, INC AX, DEC AX sequence instead! There are sound reasons to use a sequence of "working" instructions instead of NOPs: recent protection schemes "smell" patched nops inside the program and trash everything if they find more than -say- three consecutive NOPs! You should always try to choose THE LESS INTRUSIVE and MORE "CAMOUFLAGED" solution when you crack!) You can apply this kind of crack, on the same lines, to many programs that perform self checking of the code and hook the vectors. REAL DISK ACCESS STUFF Now we may come to the subject of this lesson: As usual, let's begin from the beginning: history is always the key that allows an understanding of present and future, in cracking matters too. As the older 5 1/4 inch big black floppy disks were still used (the 320K/8 tracks or 360K/9 tracks ones, that were really "floppy" and have nowadays almost disappeared) one of the more common methods to protect a program, was to format the "master" (key) disk in a weird way. Old floppy disk for the PC did usually store 360K at 9 sectors per track. Some basics for those of you that do not know anything: in order to defeat this kind of cracks you need to know two things: the floppy disk parameter block (FDPB) and the interrupt routines dealing with format/read disk (basically INT_13). Most often, the protection scheme is to either format one or more sectors or tracks with sector sizes other than the standard 512 bytes, or to either give one of the sectors a wild sector number like 211 or just not format a whole track of eight/nine/15 sectors. If you, for instance, have got the same (very old) copy of VisiCalc master I do, you'll find that sector 8 on track 39 is missing entirely. The interrogation with assembly or with an "ad hoc" utility (I use the tools I wrote myself, but you 'll be able to find many such utilities in public domain, the oldest one, from 1984 (!) being the seasoned [U-ZAP] an "Ultra utility" from the "Freesoft company") will tell you which sector numbers were altered, their size in bytes, and if they were formatted with a CRC error (another not so fancy trick). The floppy disk parameters are stored in the BIOS: interrupt vector 1E contains the address of the floppy disk parameter block. The FDPB's contents are the following: Offset Function crackworthy? Example 0 Step rate & head unload no DF 1 head load time no 02 2 Motor on delay no 25 3 Number of bytes per sector yes 02 4 Last sector number yes 12 5 Gap length yes 1B 6 Data track length yes FF 7 Format gap length yes 54 8 Format byte no F6 9 Head settle time no 0F A Motor start time no 02 0) Offset #0: the left "nybble" (single digit) of this value is the step rate time for the disk drive head. The right nybble is the disk head unload time. These values are best left alone. 1) Offset #1: again, don't fool around with these values. The left nybble is the disk head load time, and the right nybble is the direct memory access mode select. 2) Wait time until motor is turned off. Not normally of use. 3) Bytes-per-sector value: AH-HAH! If you place a "0" in this value, the PC expects all sectors to be 128 bytes long. A "1" means a sector size of 256 bytes, a "2" means 512 bytes (this is the standard DOS value), and a "3" means 1024 bytes per sector. 4) Highest sector number on a track: this is used for formatting and tells DOS how many sectors there are on each track. 5) Gap length for diskette reads: this is what you fool around with if you keep getting CRC errors when you try to read a non-standard size sector. Normally, you can just leave this alone except when formatting with a U-Format tool. 6) Data length: This contains the number of bytes in a sector when the value in table byte #4 doesn't contain a 0, 1, 2, or 3. 7) Number of bytes in the gap between sectors: this is also only used when formatting special tracks. 8) Format fill byte: When formatting, this is the initialization byte that will be placed in all new sectors. 9) Head settle time: leave this alone. A) Motor start time: don't fool with this either. In order to modify globally the number of tracks on a given disk and the number of sectors per track you can always format with the DOS command switches "/t:" and "/n:" FORMAT /t:tracks /n:sectors If you want to find out what the existing parameters are, run [Debug.exe] or [Symdeb.exe] and enter the following commands: - d 0:78 l 4 <- get FDPB address 0000:0070 22 05 00 <- debugger's likely response - d 0:522 l a <- get 10 FDPB values 0000:520 DF 02 25 02 12 1B FF... <- see preceding table Remember that all standard disk formats under DOS support a sector size of 512 bytes, therefore, for one-sided 5.25 inch floppies: 40t*8s*512b=163.840 bytes (160Kb) 40t*9s*512b=184.320 bytes (180Kb) and for two-sided 5.25 inch floppies: 40t*8s*512b*2sides=327.680 bytes (320Kb) 40t*9s*512b*2sides=368.640 bytes (360Kb) Beginning with DOS version 3.0 (Yeah, more and more history!) a new floppy disk format has been supported: The IBM AT (80286 CPU) introduced the so called "high capacity" 5.25 u- inch floppy, capable of storing 1.2M at 15 sectors per track: 80t*15s*512b*2sides=1.228.800 bytes (1.2Mb) Later on were introduced the to-day universally used 3.5 inch floppies, the ones inside a rigid small plastic cartridge, and we have, similarly: 3.5-inch double sided/double density 720K 3.5-inch double sided/quad density (HD) 1440K 3.5-inch double sided/high density 2880K [INT_13, AH=18, Set media type for format] In order to create weird layouts, the protectionists use interrupt 13h, service 18h, that specifies to the formatting routines the number of tracks and sectors per track to be placed on the media: * Registers on entry: AH=18h; CH=Nø of tracks; CL= Sectors per track; DL= Drive number (A=0; B=1;C=2... bit 7 is set if the drive is an hard disk) * Registers on Return: DI: Offset address of 11-byte parameter table; ES: Segment address of 11-byte parameter table. [INT_13, AH=2, Read disk sectors] In order to read them, they have to use INT_13, service 2, read disk sectors, with following layout: * Registers on entry: AH=2h; AL= Nø of sectors; BX= Offset address of data buffer; CH=track; CL= Sector; DH= Head (side) number; DL= Drive number; ES: Segment address of data buffer. * Registers on Return: AH= return code. If the carry flag is not set, AH=0, therefore the weird sector has been read, if on the contrary the carry flag is set, AH reports the status byte as follows: 76543210 HEX DEC Meaning 1 80h 128 Time out - drive crazy 1 40h 064 Seek failure, could not move to track 1 20h 032 Controller kaputt 1 10h 016 Bad CRC on disk read 1 09h 009 DMA error - 64K boundary crossed 1 08h 008 DMA overrun 1 04h 004 Bad sector - sector not found 11 03h 003 Write protect! 1 02h 002 Bad sector ID (address mark 1 01h 001 Bad command [Return code AH=9: DMA boundary error] One of the possible errors should be explained, coz it is used in some protection schemes: AH=9 DMA boundary error, means that an illegal boundary was crossed when the in formation was placed into RAM. DMA (Direct memory access) is used by the disk service routines to place information into RAM. If a memory offset address ending in three zeros (ES:1000, ES: 2000...) falls in the middle of the area being overlaid by a sector, this error will occur. [INT_13, AH=4 Verify disk sectors] Another possible protection interrupt is interrupt 13H, service 4, Verify disk sectors. Disk verification takes place on the disk and DOES NOT involve verification of the data on the disk against data in memory! This function has no buffer specification, does not read or write a disk: it causes the system to read the data in the designated sector or sectors and to check its computed cyclic redundancy check (CRC) against data stored on the disk. See INT_13, AH=2 registers and error report. [CRC] The CRC is a checksum, that detects general errors. When a sector is written to disk, an original CRC is calculated AND WRITTEN ALONG with the sector data. The verification service reads the sector, recalculates the CRC, and compares the recalculated CRC with the original CRC. We saw that some protection schemes attempt to disguise interrupt calls. This is particularly frequent in the disk access protection schemes that utilize INT_13 (the "disk" interrupt). If you are attempting to crack such programs, the usual course of action is to search for occurrences of "CD13", which is machine language for interrupt 13. One way or another, the protection scheme has to use this interrupt to check for the special sectors of the disk. If you examine a cross section of the program, however, you'll find programs which do not have "CD13" in their machine code, but which clearly are checking the key disk for weird sectors. How comez? There are several techniques which can be used to camouflage the protection scheme from our nice prying eyes. I'll describe here the three such techniques that are more frequent: 1) The following section of code is equivalent to issuing an INT 13 command to read one sector from drive A, side 0, track 29h, sector ffh, and then checking for a status code of 10h: cs:1000 MOV AH,02 ;read operation cs:1002 MOV AL,01 ;1 sector to read cs:1004 MOV CH,29 ;track 29h cs:1006 MOV CL,FF ;sector ffh cs:1008 MOV DX,0000 ;side 0, drive A cs:100B XOR BX,BX ;move 0... cs:100D MOV DS,BX ;...to DS register cs:100F PUSHF ;pusha flags cs:1010 PUSH CS ;pusha CX cs:1011 CALL 1100 ;push address for next instruction onto stack and branch cs:1014 COMP AH,10 ;check CRC error cs:1017 ... rest of verification code ... ... cs:1100 PUSHF ;pusha flags cs:1101 MOV BX,004C ;address of INT_13 vector cs:1104 PUSH [BX+02] ;push CS of INT_13 routine cs:1107 PUSH [BX] ;push IP of INT_13 routine cs:1109 IRET ;pop IP,CS and flags Notice that there is no INT 13 command in the source code, so if you had simply used a debugger to search for "CD13" in the machine code, you would never have found the protection routine. 2) Another technique is to put in a substitute interrupt instruction, such as INT 10, which looks harmless enough, and have the program change the "10" to "13 (and then back to "10") on the fly. A search for "CD13" would turn up nothing. 3) The best camouflage method for interrupts I have ever cracked (albeit not on a INT 13) was a jump to a section of the PROGRAM code that reproduces in extenso the interrupt code. This elegant (if a little overbloated) disguise mocks every call to the replicated interrupt. LOADING ABSOLUTE DISK SECTORS Old good [debug.com] has been called the "swiss army knife" of the cracker. It allows a lot of nice things, inter alia the loading, reading, modifying and writing of absolute sectors of the disks. The sector count starts with the first sector of track 0, next sector is track 0, second side (if double sided), then, back to the first side, track 1, and so on, until the end of the disk. Up to 80h (128) sectors can be loaded at one time. To use you must specify starting address, drive (0=A, 1=B, etc...), starting sector and number of sectors to load. - l 100 0 10 20 This instruction tells DEBUG to load, starting at DS:0100, from drive A, sector 10h for 20h sectors. This allows at times the retrieval of hidden and/or weird formatted data. If you get an error, check the memory location for that data. Often times, part of the data has been transferred before the error occurs, and the remainder can be manually entered or gathered through repetitive retries. Bear all this in mind learning the following cracks. Let's now crack an "oldie" primitive: MS Flight simulator (old version 2.12, from 1985!) This old program used -in 1985!- following beautiful protection scheme: on the disk you had only a "stub", called FS.COM with few bytes, which had following instructions: loc code instruction what's going on ------------------------------------------------------- :0100 FA CLI ;why not? :0101 33C0 XOR AX,AX ;ax=0 :0103 8ED0 MOV SS,AX ;ss=0 :0105 BCB0C0 MOV SP,C0B0 ;SP=C0B0 :0108 8EC0 MOV ES,AX ;ES=0 :010A 26C70678003001 MOV Wptr ES:[0078],0130 ;Wp 0:78=130 :0111 268C0E7A00 MOV ES:[007A],CS ;0:7A=Segment :0116 BB0010 MOV BX,1000 ;BX=1000 :0119 8EC3 MOV ES,BX ;ES=1000 :011B 33DB XOR BX,BX ;BX=0 :011D B80102 MOV AX,0201 ;AH=2 AL=1 sector :0120 BA0000 MOV DX,0000 ;head=0 drive=0 :0123 B96501 MOV CX,0165 ;track=1 sector=65 (!) :0126 CD13 INT 13 ;INT 13/AH=2 :0128 B83412 MOV AX,1234 ;AX=1234 :012B EA00000010 JMP 1000:0000 ;JMP to data we just read :0130 CF IRET ;Pavlovian, useless ret You see what's happening in this old protection scheme, don't you? Herein you can watch the same snap that happens in more recent (much more recent) protection schemes (as you'll see in the next lesson): the protection searches for a weird formatted sector and/or for particular data. That should be no problem for you any more: you should just reverse engineer everything (and that goes on pretty quickly: just watch and break on the INT_13 calls), fetch the "weird" data, tamper the whole crap and have your soup as you like it. One more word about "old" protection schemes. Be careful not to spurn them! Some of them are -- CLEVER -- STILL USED -- DIFFICULT TO CRACK... I mean, this older DOS programs had nice protections... it's pretty annoying to crack windows programs that require a registration number: as you saw in Lesson 3, you just type your name and a serial number of your choice in, say "666666666", break into the program with WINICE, search the "666666666" and search too, for good measure, your own name, set a memory read breakpoint where the number dwells and look at the code that manipulates your input. As [Chris] rightly pointed out, you can even rip the code straight out of the program and create a key generator which will produce a valid code. This code will work for any name you typed in only in the "pure maths manipulation" protection schemes, and will on the contrary be specific, following the name you typed in, the "alpha-maths manipulation" protection schemes (like MOD4WIN, see the Windows lessons), watch in this case the "pseudo-random xoring" of the letters that compose your name. -- STUNNING, coz new ideas have always been infrequent, and they are getting more and more rare in this objectionable world of lazy, incapable programmers patronizing us with ill-cooked outrages like Windows'95... yeah, as usual there is no "development" at all, quite the contrary, I would say. Take a step backward, sip a good Martini-Wodka (please remember that only Ice cubes, Dry Martini, Wodka Moskovskaja, Schweppes' "Indian tonic" a green olive from Tuskany and a maltese lemon zest will really be perfect) and watch from your balcony, with unsullied eyes, your town and the people around you: slaves everywhere, leaving home at 7.30 in the morning, stinking in a progression of identical cars, forced to interminably watch advertisement panels and endlessly listen to boorish publicity, happy to go to work (if they happen to have the "luck" to work, in this inequitable society) the whole day long in order to produce other cars in order to buy, one day, a new car with a different colour... Why people don't look at the stars, love each other, feel the winds, ban the stinking cars from the places where they live and eat, study colours... name yourself a not-consumistic activity? Why don't they read any poems any more? No poetry any more, in the grey society of the publicity-spots slaves...poetry will soon be forbidden, coz you cannot CONSUME as you read poems, and in this farce of a society you are BOUND to consume, that's the only thing they want you to do... you are CULTIVATED to consume... no books worth to read any more... stupid american conventional cram everywhere... boy, at times I'm missing some well placed neutron bombs, the ones that would kill all these useless zombies and leave noble books and good Wodka untouched. It's difficult to believe in democracy any more... if I ever did... all the useless zombie do -unfortunately- vote, and they do vote for "smiling semblances", for "conventionally minded idiots" that so act as if they would "really" be like what they "look" like and could not care less about anything else than making bucks and defend intolerant and petty patterns. The slaves choose the people they have "seen" on TV... as if the egyptians would VOTE for their pharaohs, exhilarated under the whips of publicity... sorry, at times I forget that you are here for the cracks, and could not care less about what I think... You 'll obtain the OTHER missing lessons IF AND ONLY IF you mail me back (via anon.penet.fi) with some tricks of the trade I may not know that YOU discovered. Mostly I'll actually know them already, but if they are really new you'll be given full credit, and even if they are not, should I judge that you "rediscovered" them with your work, or that you actually did good work on them, I'll send you the remaining lessons nevertheless. Your suggestions and critics on the whole crap I wrote are also welcomed. E-mail +ORC +ORC an526164@anon.penet.fi HOW TO CRACK, by +ORC, A TUTORIAL --------------------------------------------------------------------------- Lesson 6.1: Funny tricks (1) --------------------------------------------------------------------------- LESSON 6 (1) - Funny tricks. Xoring, Junking, Sliding EXERCISE 01: [LARRY in search of the King] Before the next step let's resume what you have learned in the lessons 3-5, beginning with a very simple crack exercise (again, we'll use the protection scheme of a game, for the reasons explained in lesson 1): SEARCH FOR THE KING (Version 1.1.). This old "Larry" protection sequence, is a "paper protection" primitive. It's a very widespread (and therefore easy to find) program, and one of the first programs that instead of asking meaningful passwords (which offer us the possibility to immediately track them down in memory) asked for a random number that the good buyer could find on the manual, whereby the bad cracker could not. (Here you choose -with the mouse- one number out of 5 possible for a "gadget" choosen at random). I don't need any more to teach you how to find the relevant section of code (-> see lesson 3). Once you find the protection, this is what you get: :protection_loop :C922 8E0614A3 MOV ES,[A314] ... :C952 50 0E PUSH AX & CS :C954 E81BFF CALL C872 <- call protection scheme :C957 5B POP BX twice :C959 8B76FA MOV SI,[BP-06] <- prepare store_room :C95C D1E6 SHL SI,1 <- final prepare :C95E 8942FC MOV [BP+SI-04],AX <- store AX :C961 837EFA00 CMP Word Ptr [BP-06],+00 <- good_guy? :C965 75BB JNZ C922 <- loop, bad guy :C967 8E0614A3 MOV ES,[A314] :C96B 26F606BE3501 TEST Byte Ptr ES:[35BE],01 <- bad_guy? :C971 74AF JZ C922 <- loop, bad guy :C973 8B46FC MOV AX,[BP-04]... <- go on good guy Let's see now the protection scheme called from :C954 :C872 55 PUSH BP ... :C8F7 90 NOP :C8F8 0E PUSH CS :C8F9 E87234 CALL FD6E <- call user input :C8FC 5B POP BX :C8FD 5B POP BX :C8FE 8B5E06 MOV BX,[BP+06] :C901 D1E3 SHL BX,1 :C903 39872266 CMP [BX+6622],AX <- right answer? :C907 7505 JNZ C90E <- no, beggar_off :C909 B80100 MOV AX,0001 <- yes, AX=1 :C90C EB02 JMP C910 :C90E 2BC0 SUB AX,AX <- beggar_off with AX=0 :C910 8BE5 MOV SP,BP :C912 5D POP BP :C913 CB RETF <- back to main Here follow 5 questions, please answer all of them: 1) Where in memory (in which locations) are stored the "right" passnumbers? Where in memory is the SEGMENT of this locations stored? How does the scheme get the OFFSET? 2) Would setting NOPs instructions at :C965 and :C971 crack? Would it be a good idea? 3) Would changing :C907 to JZ crack? Would it be a good idea? 4) Would changing :C907 to JNZ C909 crack? Would it be a good idea? 5) Write down (and try) at least 7 OTHER different patches to crack this scheme in spades (without using any NOP!). Uff! By now you should be able to do the above 5 exercises in less than 15 minutes WITHOUT USING THE DEBUGGER! Just look at the data above and find the right answers feeling them... (you 'll now which one are the right one checking with your debugger... score as many points as you like for each correct answer and sip a good Martini-Wodka... do you know that the sequence should ALWAYS be 1) Ice cubes 2) Martini Dry 3) Wodka Moskovskaja 4) olive 5) lemon 6) Schweppes Indian t