The "call relocation table' and its importance"
Some teachings from a small protection inside sruler
by fravia+ (MSRE)
(25 September 1997)
Courtesy of Fravia's page of reverse
engineering (well, of course :-)
The "call relocation table' and its importance"
(Some teachings from a small protection inside sruler)
We are not yet finished with screen ruler, a little useful cracking tool which you'll be able to download here. You'll find my original essay about this interesting cracking tool here, with a stimulating add-on by Frog's print. The original work was about adding some functionalities to the target, and is part of the +HCU's "crippledwarez & functionalities adding" project 6
I was recently fumbling around with my copy of screen ruler (that I have modified quite a lot) and as I eliminated the original one from my hard disk, I was puzzled by a small protection (if you want to call that a "protection") that I had not reversed in my original essay. I didn't even see it :(
In fact the code of this target checks for the existence of two files on your hard disk: its registration file and another help file. If you delete them, as I did when I deleted the original, it snaps.
This is a very
common scheme, since many shareware authors like their products to be distributed with all their parts.
Usually a simple run of filemonitor will alert you about this and land you directly with a good search string for your dead listing.
The protection inside this target is indeed absolutely simple, yet we'll use it in order to learn another very useful trick for our reverse engineering purposes: the "CALL RELOCATION" table.
Here is the part of the code where screen ruler checks the "existence" of its "registration file" (sreg.txt) and of,
its "text" help file (sruler.txt). I cannot understand why a target
should perform such an important checking in this "easygoing" way... In fact even a
stupid luser could
just prepare his own file, saving with the name "sruler.txt" a text file
where he wrote something, let's say the phrase "Hi guys, I'm sruler.txt!" and, loo
and behold, he would be done :-)
Here is my SYNTHETIZED listing of this part of the code, please note the two lines in red (in fact who calls it and where does it return):
:00401739 push ebp ;who calls here? THIS IS IMPORTANT
... ; ->"Sorry, this version of Screen
... ;"->"Ruler is incomplete."
:0040176F Call dword ptr [0040E324] ;FindExecutableA ->"SREG.TXT"
:00401775 mov ebx, eax ;pass return value
:00401777 cmp ebx, 2 ;file was not found
:0040177A jne 0040178D ;check_next_file if found
... ;not found, so:
:0040177E Call dword ptr [0040E36C] ;USER32.MessageBeep
... ;->"Error Notice"
:0040178B jmp 004017BC ;messagebox, flag 0 and ret
:check_next_file
...
:004017A0 Call dword ptr [0040E324] ;FindExecutableA ->"SRULER.TXT"
...
:004017AB jne 004017CF ;flag 1 and ret if found
... ;else
:004017AF Call dword ptr [0040E36C] ;MessageBeep,
... ;->"Error Notice"
:004017C5 Call dword ptr [0040E370] ; USER32.MessageBoxA
:004017CB xor eax, eax ;bad flag zero
:004017CD jmp ret
:004017CF mov eax, 1 ;good flag one
:004017DB ret ;Ja, where? THIS IS IMPORTANT
Well, there is not much to say about this codesnippet... the checking uses a
function that is really intended for EXECUTABLES (the 31 possible error codes have a lot to do with executables) just in order to check for the presence of the other two files of
the "bundle". As you should immediately see here, you can easily trick this stupid code into returning a good flag, or, as I said, you can write your own "faked" files...
But, just wait a minute:
would it not be nice if we could find WHERE this snippet is called from in our target? Yes, sure, but how the hell are we going to know FROM THE DEAD LISTING where did the call come from? There is (apparently) nowhere in the code a call to the beginning of the above code snippet at :00401739. No jumping here, no calls, how did the target get here?
We'll have to load and fire winice and trace back...
NO! Here is a nice trick that +ORC has teached us long ago, time to explain it to all future +crackers!
Dead listing using the CALL RELOCATION TABLE!
In order to find where the above code snippet is called from we'll have to
have a look at the CODE TABLES of our target (use hexworkshop and search for the
hex string "39174000", i.e. the start location of the procedure above... our location in INVERTED hex sequence):
7DC0: 00000000000000000000000000446174
7DD0: 610000000000000000002E354000E112 ;table begins at 7DDA, duh
4000BF134000DC174000F5174000BD1B
400046214000BA254000D6144000FB23
4000922840004C2B4000B12C40000634
40004D1340004E2A40000A2E4000F12E
40009B2A4000EE264000922F4000AB30
40007918400064144000A42340006431
7E40: 40006719400039174000FB3340000000 ;table ends at 7E4A (+70), duh
7E50: 5555AAAA5555AAAA5555AAAA5555AAAA
You dig it, don't you? In fact these tables, near the bottom of almost all windows files,
are very useful for our reverse engineering purposes (that's the real reason
I wanted to show you the stupid protection snippet above)... looking at them you can
immediately get the addresses of various important calls: here you have
:0040352E ;at the bottom
:004012E1 ;at the bottom+4
:004013BF ;at the bottom+8
...
:403164 ;at bottom+64
:401967 ;at bottom+68
:401739 ;(our nag call) at bottom+6C
:4033FB ;at the top (=+70)
And you will now be able to easily examine each one of the other... Yet you can do even more! Much more!
Since you can see the "bottom" of this table at 7DDA, you'll know that you have
here 7DDA = :0040352E, 7DDA+4 (=7DDE= :0040121E), 7DDA+8 (=7DE2 = :004013BF)... until
you get to our 7E46= :00401739_call_nag_if_missing_file, which is 7DDA+6C. You dig it: each 4 bytes we have, in this table, the beginning of a routine.
What the hell should we care! Will you cry exasperated by all this. Well, look at this nice piece of code, inside our target, that is not supposed to say us anything, look:
:004012E1 55 push ebp
:004012E2 89E5 mov ebp, esp
:004012E4 53 push ebx
:004012E5 83EC04 sub esp, 00000004
:004012E8 894DF8 mov dword ptr [ebp-08], ecx
:004012EB 89C8 mov eax, ecx
:004012ED 8B4D08 mov ecx, dword ptr [ebp+08]
:004012F0 894804 mov dword ptr [eax+04], ecx
:004012F3 89C1 mov ecx, eax
:004012F5 8B19 mov ebx, dword ptr [ecx]
:004012F7 FF536C call [ebx+6C] ;HERE!
:004012FA 89C1 mov ecx, eax
:004012FC 09C9 or ecx, ecx
:004012FE 7502 jne 00401302
:00401300 EB26 jmp 00401328
We could just look at this code snippet until our eyes start dazzling, and we would
never understand anything without some laborious softicing. Or would we?
In fact this is NOT a protection trick, it is the result of the COMPILATION of our
target, yet it amounts to the same "confusing" effect for us reverse engineers if you
will not use the "table relocation countermeasures" I'm explaining you now.
OK guys, I know, you already understood the whole point
Let's rewrite the "awful" code
snippet above in "our" way:
:004012E1 55 push ebp ;value corresponds to a "call [ebx+4]" somewhere
... ;prepare call
:004012F7 FF536C call [ebx+6C] ;call table value 00401739_nag_if_missing_file
:004012FA 89C1 mov ecx, eax ;get return value
:004012FC 09C9 or ecx, ecx ;is it zero (=bad)
:004012FE 7502 jne 00401302 ;no, continue
:00401300 EB26 jmp 00401328 ;yes, beggar off
Well, it makes MUCH more sense, doesn't it?... now, how is this for our "dead listing" purposes? Quite good, I would say, and there is no need whatsoever to fire winice in order to understand such "awful" dead listing snippets any more... note that I agree unconditionally with +ORC on this: good dead listing sipping a nice cocktail in
the shadows of a nice garden beats head down any eye - fatiguing live winicing :-)
In fact, who cares about the values in ebx and how they get there, and all the mischievous (or innocent) manipulations of those values any more? Once we know that there is a base for all relocated calls, those values "should" correspond (and indeed, almost always, they will) to the values inside our table of calls.
Therefore the cryptic "call [ebx+4C]" will
correspond (here in our target) to a simple call 7E26 (i.e.:004026EE), whereby the mysterious "call [ebx+64]"
will simply call the routine value hardcoded at 7E3E (i.e.:00403164). And so on and so on! Everything is SO easy! Reverse engineering, my dear readers, is just a little feeling, a little luck and a little help! (and a little brain too, you'll often need one :-)
Learn this, once for ever
You should ALWAYS have a look at these tables when you dead list a program, you should ALWAYS calculate their base and you should ALWAYS prepare a copy of said table, in order to integrate it to your "dead listing".
Use this trick to give meaningful tags to the numerous
"relocated" calls that you'll find inside the snippets of your compiled targets... you'll notice pretty soon
the incredible difference that this will mean for your understanding of the code!
Always remember +ORC's "Zen" teachings:
Your wordprocessor's search and replace facilities will be more
useful than ANY other tool when trying to "feel" your targets, and you
will feel the code, provided you have the necessary peace of mind: do
not, never, ran amok inside the dark codewoods, they are full of thorns.
Learn the names of the common structures and give meaningful names to all
things that you discover along your journey. If you have done your
homework, a brain and a pencil are all what you will need to crack ANY
target
Well, I love working with my brain and my colored staedtler pencils!
fravia+ (MSRE), 25 September 1997
(c) fravia+ (MSRE), 1997. All rights reversed.
You are deep inside fravia's page of reverse
engineering, choose your way out:
My (and Frog's) original essay about screen ruler
homepage
links
anonymity
+ORC students' essays tools
cocktails
academy database
antismut search_forms mail_fravia
is reverse engineering legal?