home *** CD-ROM | disk | FTP | other *** search
- Remote Administrator v1.11 Tutorial by cLUSTER! - 12th December 1999.
-
-
- Now this is truly an excellent piece of software, the best of its kind
- really, and it also has one of the most interesting protection schemes
- I've come across so far.
-
- But even though Dmitry Znosko has put a lot of effort into making this
- application virtually uncrackable using traditional cracking approaches,
- such as serial-fishing and code-patching, us reversers always come up with
- new and brilliant ways of approaching our targets and find our ways about
- to make it obey our will!
-
- Still, this one has actually been on the stand before although none of the
- former crackers have succeeded to make a 100% working crack.
-
- The first attempt was made by someone in PGC, I don't remember who,
- however, he failed miserably. He managed to remove the NAG, and it also
- seemed registered, except for not showing any name and also saying 0 licenses.
- Now, this we could have lived with, IF he had at least managed to remove the
- checksums, which caused radmin to crash every time you added a new host or
- tried to connect to a server. Such a crack is not of much use, disabling the
- core functionality of the application.
-
- The second attempt made by Staier (tutorial can be found on fravia) on how to
- reverse this target by dumping the unpacked module and then disassembling it
- using IDA might be an interesting way of doing it, but we still don't end up
- with a fully registered application, instead it is still unregistered with the
- annoying nag showing and without any name/licenses, only the expiration has
- been removed. This method of reversing is too time consuming considering what
- we can achieve using it and also that it is fairly easy to find the piece of
- code that checks the registration using sice. But obviously that wasn't even
- what Staier had in mind, instead he concentrated on removing only the expiration
- checks, maybe because a deadlisting does not have any string references to where
- the regflag for registration is located ;)
-
- After numerous hours of analyzing the code and its bitching, I feel confident
- to say that I found a truly excellent way of terminating the need for any
- registration code or even any patched code.
-
- Turn On, Tune In and may this tutorial shed some light upon new ways to follow
- in the art of reverse engineering..
-
-
- Tools used: SoftIce, Custom Loader, Some Coke and Loads of Psychedelic Trance.
-
-
- NOTE: This application uses relative addresses for its unpacked code, so the
- code-snippets addresses below might differ from the ones you will get
- when reversing radmin.
-
-
- For starters, lets look at what we have here.. Running radmin for the first
- time tells us that it is an "unregistered copy" and that we can unlock it
- entering a registration code.
-
- Now we feel all confident.. There is a way to make it registered using a
- registration code.. This shouldn't be all that hard, should it?
-
- So, we click Enter Code and a dialog box shows up, asking us for the
- registration code.. Mhm.. No name.. Either this is gonna be quite easy
- to fish.. Using hardcoded serial or maybe parts of the reg. code generates
- the other parts of it.. Or if we're out of luck it is going to be a real
- bitch of a protection using checksums, maybe even system id and who knows
- what else...
-
- Enough speculating, lets find out.. First we enter our registration code..
-
- 1234554321
-
- Yeah, that's it.. This is nice combination of chars since it isn't very likely
- to be laying around somewhere in memory already.
-
- Now lets break into sice and put a breakpoint on hmemcpy.
-
- BPX hmemcpy ;the almighty undocumented feature especially implemented for
- us reversers.. coming soon to a winnt/2k machine near you! ...not!
-
- And then we click OK.
-
- It breaks into sice. Yea yea, it always works damnit. We are so friggin' 3li7e!
- ;)
-
- Since we don't usually enjoy F12'ing our way out of calls, let's just put a BPRW
- on the processes name instead.. (use MOD to see names)..
-
- BPRW radmin ;this causes softice to break when the applications code starts
- to execute again.
-
- Exit sice and let it rip.
-
- WTF?.. Back to the application... Now what's this.. As I see it there are two
- possible reason why sice didn't break. One is that the application is packed,
- this is the most likely one.. Or it might even be crypted (breakpoint
- protected).
- The other is that there is a second executable running that handles all the
- checking that we missed out on.. Less likely since there is just 2 executables
- installed and the other executable being the server. (It could not have been a
- DLL/VXD, since sice catches all such calls).
-
-
- Well, let's do it all over again.. This time using F12 instead of BPRW.
-
- Success.. This time we end up at,
-
- B46126 MOV EDI, [USER!EndDialog] (I take for granted that you use exports.)
-
- Now this is quite an odd memorylocation.. But still, it is part of Radmins
- code.. (check lower right corner in sice)
-
- Still, since I did bring up the subject on external DLL/VXD's used by the
- application, let's have a look at which ones radmin uses.
-
- QUERY radmin
-
- Base AllocBase AllocProt Size State Protect Owner
- -------------------------------------------------------------
- .... ...... .. .. .. .. xxxxxxxx
-
-
- While browsing through the Query status of radmin we should look at the
- Owner (xxxxxxxx) to locate any used DLL/VXD's.
-
- Nopes, nothing out of the ordinary.. Except for a whole lot of memory
- space allocated for use and the ordinary Windows DLL's.
-
- Out of curiosity we'll have a look at radmins bit sections to see if
- there is any sections we recognize (of any known packers)..
-
- MAP32 radmin
-
- Owner Obj Name Obj # Address Size Type
- -------------------------------------------------------------
- RADMIN .TEXT 0001 0167:01401000 00008D46 CODE RO
- RADMIN .RDATA 0002 016F:0140A000 00001952 IDATA RO
- RADMIN .DATA 0003 016F:0140C000 0002c418 IDATA RW
- RADMIN .RSRC 0004 016F:01439000 00025500 IDATA RO
- RADMIN .RELOC 0005 016F:0145F000 00000A30 IDATA RO
-
-
- Nah.. These are all common section names from executables..
-
- But looking at the section addresses tells us where radmins code is
- mainly located (the packed code that is), and our current EIP being
- B46126 confirms that we are indeed tracing a piece of unpacked code.
-
- But what do we care? We are gonna get ourselves a working reg. code.
- and if we ever need to investigate what packer has been used, if any
- known, we'd just use any of the existing exe analyzers. I'd recommend
- File Analyzer since it has proven to detect most common packers and
- also gets updated often. Radmin has it's very own packer though, so
- none of the existing exe analyzer will detect any packer being used
- with the executable.
-
- Anyways, let's get with the program.. standard routine here.. we'll just
- put a breakpoint-on-range on our reg.code string in memory and let radmin
- run and we will probably end up in some comparison routine and we're all
- set.. or maybe not.. Off we go.. (NOTE: BPR is not available in WinNT)
-
- First of all we need to find out where our reg. code string is located in
- memory.. Tracing a couple of lines and we'll end up at ...
-
- B46135 MOV EDX, [ESP+C]
-
- Do a D EDX to see memory contents.. ahh.. nice, there is our reg. code..
-
- (Using sice's S cmd is also very useful to locate strings in memory.)
-
- We'll do a BPR EDX EDX+A R to make sice break when radmin reads from our
- reg.code string.
-
- We exit sice and wait.. Several microseconds later, and we're back in action.
-
- This time at...
-
- B44618 MOV AL,[EBX] ;moves 31 to AL (31=1 from our string 1234554321)
- ...... XOR ESI,ESI
- ...... PUSH EDI
- ...... MOV EBP,EDX
- ...... TEST AL,AL ;checks if there is anything in AL
- ...... JZ B446FC ;if not, that is if we didn't enter any code, it
- jumps.
- ...... MOV CL, [EBX+1] ;moves 32 to CL (next char in our string)
- ...... TEST CL,CL ;checks if there is anything in CL
- ...... JZ B446FC ;if not, this is not a valid code, and it jumps.
-
- B44634 CALL B8A14A
-
- At this call we need to pay some attention..
-
- When tracing into this call, some 280 kb higher in memory, we see yet another
- call to a even higher address (4.5 mb higher).
-
- B8A14A PUSH 0000001E
- ...... CALL FE0540
-
-
- Radmin being 390 kb's in its original packed size, then the former piece of code
- (b44xxx->b8axxx) makes sense when it comes to size in memory.. But, some 4.5 mbs
- further up in memory doesn't. Seems as if radmin has been unpacking itself to
- several locations in memory.. But let's not bother with this right now though..
- On with the show...
-
- Let's trace into the call..
-
- FE0540 PUSH AD (pushes all registers to the stack)
-
- <start of code>
- ..
- ..
- FE0571 XOR EAX, [EBX*4+008BD934] ; checksums the code
- ..
- ..
- loop back to <start> of code until done with range of addresses.
- ..
- FE059D ADD EAX, D91A65C5 ; adds a static value to the checksum'd EAX value.
- ...... MOV EBX, [ESP+20] ; moves out an address to EBX
- ...... SUB EBX, EAX ; subs the address with what is left in EAX
- ...... MOV [ESP+24], EBX ; moves the results of the sub to the stack.
- ...... POPAD ; pops back all registers
- ...... RET ; exits
-
-
- Now what happens in the above code is that it points to an address of
- radmins unpacked code and then loops, inc's address and does a checksum
- on the code in each loop until it has completed the loop entirely..
-
- Then it uses the checksum'd value, which if correct, will results in
- the coming address to be executed when it has exited this call and the
- previous one.
-
- So, if we were to successfully unpack this piece of code (or just use an
- inmemory patcher) and patched some of its code, radmin would crash since
- the address it'd execute after the checksum routine would be way out
- of radmins code.
-
- Now I got you thinking.. "This guy sucks.. Nimas problemas.. I'll
- just go ahead and patch these checksums.. Been there done that!.."
-
- Not this time, this is a no can do situation. Since what we will see in the
- coming CALL's we trace is that every piece of checksum code is unique..
- It never uses the same static value once and that means we would have to
- patch each and every one in their very own way.. Sure this is theoretically
- possible.. But it'd be plain stupid!
-
- Hold it.. Stop right there.. Now I got you thinking again..
- "Fuck, this guy is seriously retarded.. It's easy.. Why patch the
- checksum routine that contains the static value that is fucking us up?
- I'll just go ahead and find out what address it calls once passing
- the checksum, and then patch the call that jumps to checksummin'
- code and make it call the correct piece of code directly..
- This is no match for me..".
-
- Bam Bam!.. General Protection Fault.. Since what we will also realize is that
- EVERY piece of god damn code in this friggin' application gets checksummored.
- That is, if you were to patch a single line of code, it'd trigger the checksum
- that checks this particular range of addresses, and removing this checksum
- as well would just trigger the next one.. and so on..
-
- In other words, this application is a bitch to patch.. So we better hope there
- is a good way of fishing/generating a valid reg. code.
-
- Back to where we were tracing, that is, after the checksum code.
-
- Code snippet of previous traced code -> current EIP ...
-
- B44618 MOV AL,[EBX] ;moves 31 to AL (31=1 from our string 1234554321)
- ...... XOR ESI,ESI
- ...... PUSH EDI
- ...... MOV EBP,EDX
- ...... TEST AL,AL ;checks if there is anything in AL
- ...... JZ B446FC ;if not, that is if we didn't enter any code, it
- jumps.
- ...... MOV CL, [EBX+1] ;moves 32 to CL (next char in our string)
- ...... TEST CL,CL ;checks if there is anything in CL
- ...... JZ B446FC ;if not, this is not a valid code, and it jumps.
-
- B44634 CALL B8A14A
-
-
- B8A14A PUSH 0000001E
- ...... CALL FE0540
- ...... RET <<<<<<<<<<<<<<<<<< WE ARE HERE !!
-
-
- After this ret, we will end up at the address the checksum ended up
- with.
-
- B441F0 MOVSX EAX, CL ;CL=32
- B441F3 ADD EAX, -2B ;32 + -2B = 7
- B441F6 CMP EAX, 4F ;why this? well, 4F+2B = 7A ("z").
- B441F9 JA B44380 ;not valid char, jumps.
- B441FF JMP [EAX*4+00B44384] ;7*4+B44384 = [B443A0] = 0C 42 B4 -> B4 42 0C
-
- B4420C MOV EAX, 00000002
- B44214 RET
-
- what the above code does is that it takes the second char in our string,
- contained in CL from former code, which is 32h = "2", and when the relative
- jump is made, the same decimal value is moved into EAX but now in hex form.
-
- So, 31 -> 01 , 32 -> 02 ... etc..
-
-
- After this ret we're back at main stream again.. Where we were before the
- checksum call, at
-
- B44639
-
- from which it continues to checksum the entered reg. code, looping in a
- huge piece of code until the entire reg. code string is done, ending up at
-
- B44701
-
-
- At this point it is time to ask ourselves what our approach to the situation
- is going to be.. Are we going to spend hours and hours analyzing the code
- that generates the checksum as well as the coming parts that will compare the
- checksum'd result with checksums and checksum and checksums.... get real!
- For fucks sake all we want to do is to beat this protection in ANY way and
- make this application fully registered as well as functional.. Why put hours
- or maybe days of hard work to eventually succeed in making a keygen for this
- application. So far this applications protection has been pretty impressive,
- so we can take for granted that reversing the protection scheme into being
- able to generate our own valid reg. code(s) would be on the edge to insanity.
-
- Nah, from here on we will try to locate where radmin compares our faulty
- generated checksum-code with whatever and see if we can fool it some way..
-
- I know, I know.. Patching the code won't be easy, but that is a problem
- we will have to deal with later..
-
- Back to reversing..
-
-
- After B44701 where it makes a RET it steps back in the code flow to
-
- B4614A MOV EAX, [ESP+8] ; [ESP+8] = 81 (part of checksumming)
- B4614E TEST EAX,EAX ; checks if the reg. code checksumming function
- successfully executed.
- B46150 JNZ B46157 ; if so, jump
-
- B46157 MOV EDX, [ESP+8] ; [ESP+8] = 81 (part of checksumming)
- B4615B LEA ECX, [ESP+000003F4] ; [ESP+000003F4] = Our regcode, in its
- checksum'd format.
- B46162 SHR EDX, 3 ; 81 -> 10 this is the length of our reg. code
- in checksum'd format.
- B46165 CALL B8A2C0 ; This call creates a registry key
- \SOFTWARE\RAdmin\v1.01\ViewType\Data
- containing the checksum'd reg. code.
- B4616A CALL B8A2CB ; Gets the registry key reg. code.
- ..
- ..
- B46177 CALL [USER32!SETDLGITEMTEXTA]
- B4617D PUSH 00
- B4617F PUSH ESI
- B46180 CALL EDI ; Calls [USER32!ENDDIALOG]
-
-
- Until the location above where it calls SetDlgItemTextA, still no
- comparison with the checksum'd reg. code had taken place, and after
- this call it was all over. The call to EndDialog ended it all.
-
- I was a bit confused here but after some more investigation I found out that
- the call to the final checking was made within the SetDlgItemTextA call itself.
-
- Let's do the following to get to the code that gets called from inside the api..
-
- S 0 l c0000000 "02345665432" (take note, the first char is now an "0")
-
- We'll find several memory locations with this string in it.
-
- On two of these locations the string will look like this:
-
- 023455432100MyFt-L0j9--2
-
- Here we put BPR's on those two addresses and then let radmin run again.
-
- We will now end up in a loop that generates the checksum'd code.
-
- (to those of you that have traced all code until this point, yes it is the same
- code as before that generated the checksum'd reg. code.)
-
- Once in this loop we will F12 us out of this call.
-
- Now we end up at B44914, from here forward until B44946 the actual comparisons
- of the checksum'd code takes place.
-
- Now, this is where things starts to get interesting again..
-
- Let us have a look at some code snippets...
-
- B44946 TEST EAX,EAX ; Regflag test. Is it a valid checksum'd reg.code?
- B44948 JNZ B44A4B ; If not, jump!
- B4494E MOV CL, [ESP+18] ; Move a byte from [ESP+18] to CL
- B44952 MOV AL, 16 ; Move 16 to AL
- B44954 CMP CL, AL ; Compare AL (16) with CL (00)
- B44956 JNZ B44A4B ; If not the same, jump!
- B4495C CMP [ESP+19], AL ; Compare [ESP+19], AL (16)
- B44960 JNZ B44A4B ; If not the same, jump!
- B44966 CMP [ESP+1A], AL ; ....
- B4496A JNZ B44A4B ; ....
- B44970 CMP [ESP+1B], AL ; ....
- B44974 JNZ B44A4B ; ....
-
- Let's start with this part of the code..
-
- First of all we must pass the regflag test, we'll do a R=0 for the
- time being.
-
- Next up, it compares the range [ESP+18 - ESP+1B] with 16's.
-
- We'll simply E [ESP+18] at B4494E and enter four 16's there.
-
-
- Tracing the next few lines leaves us clueless of what it wants,
- so let us just exit softice and let radmin run and see what
- happens.
-
- Fucking great!.. It says Registered.. But, to noone and with 0 licenses..
-
- Now this is not as great.. But wtf.. We're on a roll here, let's get
- on with the reversing.. We might just get lucky? ;)
-
- Let's have a look at what follows...
-
- B4497A MOV EAX, [ESP+1E] ; Moves a word from [ESP+1E] to EAX
- B4497E MOV ECX, [ESP+1D] ; Moves a word from [ESP+1D] to ECX
- B44982 MOV EDX, [ESP+1C] ; Moves a word from [ESP+1C] to EDX
- B44986 AND EAX, 000000FF
- B4498B SHL EAX, 08
- B4498E AND ECX, 000000FF
- B44994 AND EDX, 000000FF
- B4499A ADD EAX, ECX
- B4499C MOV ECX, [ESP+1F] ; Moves a word from [ESP+1F] to ECX
- B449A0 SHL EAX, 08
- ..
- ..
-
- To quickly get a grip on what is happening here we will do some
- trial & error.. We edit [ESP+1C - ESP+1F] and put four 11's there.
-
- Now exit softice and let radmin run.
-
- Ok, now we are kicking some serious asses.. Registered, and with 17 licenses..
-
- After a few minutes of playing around with this particular memory location,
- putting all kinds of different values there, we have successfully managed
- to recreate a working license-string.
-
- from [ESP+18 - ESP+1B] we should put 16's, this must be some kind of checksum.
-
- from [ESP+1C - ESP+1E] does nothing
-
- from [ESP+1F - ESP+20] decides how many licenses there should be (see table
- below)
-
- from [ESP+21 -> ESP+21+xx UNTIL 00h] string to put after registered to:
-
- from [ESP+xx (AFTER 00h) -> ESP+xx) string to put within the parenthesis.
-
- Maximum length of the entire string is 3e8h = 1000.
-
-
- Licenses table:
-
- x x x x
- -------
- 1 - 16 licenses
- 1 - 1 licenses
- 1 - 4096 licenses
- 1 - 256 licenses
- 1 1 - 17 licenses
- 2 - 32 licenses
- 2 2 - 8224 licenses
- F F F F - 65535 licenses
-
-
- So putting this string starting at [ESP+18] would make radmin registered
- with maximum amount of licenses:
-
- 16 16 16 16 00 00 00 FF FF 43 4C 55 53 54 45 52 00 41 53 53 4B 49 43 4B 45 52
-
-
- That's it.. Protection Terminated!..
-
- That is if you feel like using sice everytime you want to use radmin..
- And we wouldn't want that now would we?
-
- What must be done is a sophisticated loader.. A kickass in-memory patcher..
-
- And NO, you can NOT use any of the existing ones available on the net, since
- they all lack features that makes it possible to patch apps such as this one.
-
- I'm sorry to say that even though most of them have been undergoing development
- for a long time and they still are very limited.
-
- I will now explain how the loader I use to crack radmin with works, but I will
- not be giving away any sources with this tutorial.
-
- The reason for this is simple, I made this tutorial to show serious reversers
- how to approach a target such as radmin, not to ruin the developers of radmin
- by sharing all that is needed for people not being able to reverse a target
- such as this one themselves.
-
- If you are serious about using radmin you SHOULD buy it!.. The developer of
- radmin deserves every penny he can get.. He has made an kickass application,
- and he isn't asking for much, $25 is well worth spent money if you are
- seriously going to use this application.
-
-
-
- Loader approach
- ---------------
- Our goal is to reach to the address of the regflag test and once we've
- reached to this point, we need stop radmin from running and move the needed
- bytes into memory and then resume the execution of radmins code.
-
- To succeed in doing so, we need to implement the following features into our
- loader:
-
- - We must be able to put breakpoints in code and handle them.
- - Read/Write Registers.
-
-
- If you manage to make a loader with the above features, you will need to
- take the following under consideration to make a fully working loader...
-
- - The first breakpoint must be set relative to the start of the first
- unpacked code. Whenever you need to set new breakpoints, and you will
- have to do so since radmins code gets unwrapped progressively, you
- should keep in mind that you must put the breakpoints relative the start
- of the codeblock they belong to, which may be unpacked to different
- addresses each time the program is run...
-
-
- Hints: The only static code that jumps to unpacked code is at 1401690.
- From here you should proceed with the next steps.
-
- Use BPR on the unpacked code to find out from where it gets
- unwrapped.
-
- If you by some reason manage to get radmin to expired and want to
- remove the expiration, edit HKLM -> Software and REMOVE the key
- named DATA.
-
- When putting breakpoints at code that is not yet existing in
- memory but is about to be unpacked and executed soon, you can
- not use BPX with the address, you MUST use BPM address X ..
- Also do not forget to use ADDR to change to the right process
- before putting any such breakpoints.
-
-
- I hope that this tutorial was of any use.. I've tried to make this tutorial
- as detailed as possible, so that not only the very best reversers could get
- a grip on what is going on, but also the upcoming masters of the beautiful
- art of reverse engineering.
-
-
- Last but not least, I pay my deepest respects to MANMACHINE for not only
- being a great friend but also for making advanced loaders/patchers and other
- useful tools become a reality for me to use. I could never have made this one
- without you!
-
-
- Radmin Reversed & Tutorialized (c) Dec 1999 - [ cLUSTER! ]
- Loader Coding [Src Unrevealed] (c) Dec 1999 - [ mANMACHiNE! ]