An interesting tool: Screen Ruler
The "pixel shortcut" method
by Fravia+ (MSRE)
(11 September 1997)
With a welcome addition/solution by Frog's Print at the bottom!
adding functionalities, solving the trainer
(15 September 1997)
You may want to read ANOTHER essay about sruler
The
"call relocation table' and its importance :-)
(25 September 1997)
Courtesy of Fravia's page of reverse
engineering (of course :-)
An interesting tool: Screen Ruler
by Fravia, MSRE, September 1997
Screen Ruler (sruler), by Jesse Carneiro, is a very interesting
reverse engineering (and cracking) tool, as I hope to demonstrate with
this essay.
I am using here sruler.exe, version 1.0, 51.712 bytes, that you will be able
to download
here.
I will in this essay:
1) Use sruler in order to reverse engineer sruler.exe itself,
showing you a new method to get at the code that interests
us ("the pixel shortcut" method)
2) Denag sruler.exe and examine its three nag functions (delay, quiver
nag, "oldie nag")
3) Add "our" functionality to sruler.exe transforming a decimal
notation (for us useless) in an hexadecimal notation (for us very
important).
Da Target
First of all let's have a look at "manners and bearing" of our target.
When you launch sruler, you get on your screen a yellow "ruler" with decimal
measures in pixels. It is easy to drag the ruler around the screen, and a
little box allows us to change its "orientation", from horizontal to vertical.
Among other useful options, there is an "always on top" option.
Launch it right now and keep it on your screen, while you continue reading
this essay off-line.
The possibility of keeping it on our screen makes it an ideal tool
for serious reverse engineering, as you'll see. The main "real" purpose of
this tool for reverse engineers is to show us the exact width and height,
in pixels, of a given window (or nag screen), thus allowing us to quickly
individuate which parts of the code are dealing with a given "feature" of
your target.
Well, I'll show you right now what I mean: let's use sruler on sruler
itself. Launch ANOTHER copy of sruler, on this choose the "about screen ruler"
message, you'll get an elegant grey window with a black ribbon and a reference
to John 3.16.
Ok, now measure, using your first copy of sruler, the dimensions of
this "about" message. You'll see how easy it is: WIDTH = 290 pixels and
HEIGHT = 378 pixels. (and 256, 112 is the position of the top left corner of
the "about screen ruler" message, if you are interested in that too).
Now you don't even need to know about WHAT your target is doing...
How did he get that message on the screen? Who cares?
that could be a messagebox, or a window, or whatever you can get on screen
through
the thousand API functions... one thing is CERTAIN: whatever it is, it is
exactly 290x378 pixels, therefore the programmer MUST have specified these
data somewhere in its code...
Now get the dead listing of our target into your texteditor
(disassembling sruler through wdasm, for instance) and fetch the data below
using one of the two "height and width" values above (the less "common" one).
Search and here is where you will land right away searching for "0017C"
(0x17C = Dec378, the height of the "About" message):
:3C6C 6A00 push 0
:3C6E 687C010000 push 17C ;=Dec378
:3C73 6822010000 push 122 ;=Dec290
:3C78 6A32 push 32 ;=Dec50
:3C7A 6A32 push 32 ;=Dec50
:3C7C FF7508 push [ebp+08]
:3C7F FF159CE34000 Call dword ptr [0040E39C] ;USER32.MoveWindow, Ord:0190h
... and you'll notice that short afterwards you'll have
:3CD6 6888AB4000 push 0040AB88 ;->"CAboutBox.cpp"
As you can see, this "pixel shortcut" approach can represent a very easy way to get
at the code snippets you are interested in, even when you WILL NOT have,
inside your future dead listings, the
courtesy of nice meaningful names like AboutBox (say that a "nasty" Author has
called the window you are interested in something like, say,
"VF@A67_E1R" :-)
Now that I have proved that sruler is useful, since it is nagged,
let's have a look at its protection scheme. I am obviously doing this
only because I hope that a guy capable of programming such a excellent
utility could possibly be a conscientious coder and a worthy protector.
Alas, I was quickly disappointed: unfortunately the nag screen protection:
"Please register screen ruler. Used ... times" Is of the simplest kind:
:2FA7 BE02A44000 mov esi, 0040A402 ;->"Please register Screen Ruler."
:2FAC B900010000 mov ecx, 00000100
:2FB1 F3 repz
:2FB2 A4 movsb
:2FB3 8B45F0 mov eax, dword ptr [ebp-10]
:2FB6 83B8CC0100001E cmp dword ptr [eax+1CC], 1E ;if used more than 30 times
:2FBD 763A jbe 00402FF9
:2FD4 6802A54000 push 0040A502 ;->" Used %i times."
Even a modest "code fumbler" would be able to substitute
83B8CC0100001E with
83B8CC0100FFFF and get immediately rid of the
"Used %i times" part. Moreover, since there is an obligatory "waiting time"
of 3 seconds, any dilettante cracker would search and easily find the
(unique) SetTimer call that triggers this protection (and any +HCUker would
calculate that 3 seconds= 3000 milliseconds and find 0xBB8 inside the
dead listing even if there were 1000 SetTimer calls :-)
:25FB E8EA100000 call 36EA ;call pamper_tickcount
:2600 83C404 add esp, 4
:2603 89C1 mov ecx, eax
:2605 83F901 cmp ecx, 1
:2608 752B jne 2635 ;You could eventually change this to a jmp
:260A 6A00 push O
:260C 68B80B0000 push BB8 ;3000 milliseconds!
:2611 6880000000 push 80
:2616 8B45F0 mov eax, dword ptr [ebp-10]
:2619 FF7008 push [eax+08]
:261C FF15E0E34000 Call dword ptr [E3E0] ;USER32.SetTimer, Ord:01FEh
The crack is strightforward, the protection is stupid. Well, let's see if there
is nevertheless something to learn...
The call to 36EA above, at 25FB, calls a routine at 4500, where the
"GetTickCount" location
[0040AC70] is manipulated, with the purpose of allowing only A PART of the
occurrences of this target to run without nag. In fact, if the (pampered)
return value from call 36EA is one (true) you get your "3 seconds" nag,
if, instead, it is NOT equal to one, you don't get it. If you go and have
a look at the relevant part of that code, you'll see a fairly interesting
(for crackers) line::0040451B 25FF7F0000 and eax, 00007FFF
This is an interesting value because Ox7FFF (32767) is a very "particular" number
indeed: its binary representation is 0111111111111111, and it is often
used for logical operations of this "flag setting" kind.
Note that there is also another "time related" nag message... if the
system time has been set after 1998,
:00402FF9 68CE070000 push 7CE ;=1998
you'll get the message:
"This is an old version of Screen Ruler. Get an updated version", but since
this nag dwells too inside the same protection scheme with the "normal" nag,
that we have already defeated above, we don't need to worry about it.
OK, here you go with a little interesting tool... but we are not finished!
Unfortunately sruler calculates our pixel in decimal notation... yet for our
endeavour it would be more useful to get them directly in hexadecimal notation,
what do we need?
Da changes to da target
Well, oh sweet, oh mighty, oh powerful magic of the c code! Just have a look
at this part of the assembly data:
:0040A398 65 5F 56 5F 42 69 74 6D e_V_Bitm
:0040A3A0 61 70 00 25 69 00 20 50 ap.%i. P
:0040A3A8 69 78 65 6C 00 20 50 69 ixel. Pi
:0040A3B0 78 65 6C 73 00 25 69 00 xels.%i.
:0040A3B8 50 69 78 00 25 69 00 25 Pix.%i.%
What do you see there? You see %i, that is DECIMAL notation... repeated two
time, for "pixel" and for "pixels"... and what do we need to have our good
hexadecimal notation, instead of this decimal crap that compels us to calculate
each time the decimal->hexadecimal transposition? Actually we do NOT need much...
not much at all, my good friends, here you go:
:0040A3A0 61 70 00 25 78 00 20 50 ap.%x. P
:0040A3A8 69 78 65 6C 00 20 50 69 ixel. Pi
:0040A3B0 78 65 6C 73 00 25 78 00 xels.%x.
Yes, exactly, sooo simple! It is 0x78 = "x" instead of 0x69="i" (x for
hexadecimal, of course)... it's so easy I could scream! Try it!
And now you have your screen ruler in hexadecimal pixels which, btw, is now
ALSO an hexadecimal-decimal calculator, since we have left the little "tags"
below still in decimal notation. So you slide the arrow along the decimal tags
and read the hexadecimal result inside sruler... how nice!
BTW, strictly speaking it is NOT necessary to change to x the first
%i, since that first occurrence of "%i" represents the "singular"
(grammatical) notation, that you'll see only when you are at pixel 1 or at
pixel -1.
Moreover, there is still a little patch to do, since now the
"negative" pixels, when you go "outside" the ruler (left or above) with your
mouse, will not be very nice to see (-1=FFFFFFFF, -35= FFFFFFDD etcetera)...
I leave to the intelligence of the best readers the task of preparing the
necessary patch... best
solutions will be as usual primed with a nice strategic gamez from the
+Hcu's gamez collection :-)
That's it, people, hope you enjoyed this little "screen ruler" tour! Hope you'll
enjoy your ruler as a "pixel shortcutter" AND as a decimal/hexadecimal converter!
(c) Fravia+ (MSRE), 1997. All rights reversed.
A welcome addition/solution by Frog's Print!
And here follows the (quick) solution by Master Frog's print to the "little patch" I spoke above... well,
it was NOT so little, after all, and Frog has won (and got:-) a nice strategic gamez!.
I like Frog's solution... even if I have personally modified it a little, since I prefer
to keep my lowercase hexadecimal
notation (uppercase is pretty preposterous). There are various ways, for instance
passing to
:00402813 FF159CE24000 Call dword ptr [0040E29C] ;GDI32.TextOutA
BOOL TextOut(hdc, nXStart, nYStart, lpszString, cbString)
HDC hdc; /* handle of device context */
int nXStart; /* x-coordinate of starting position */ ;-)
int nYStart; /* y-coordinate of starting position */ ;-)
LPCSTR lpszString; /* address of string */
int cbString; /* number of bytes in string */
different start coordinates... Well, you'll see for yourself... just
read and enjoy! Thanks to Frog's Print, this is now
real reverse engineering... Yessir!! Much more fun (in our opinion) than
simple (boring) protection cracking!
Screen Ruler reverse engineering, adding on
by Frog's Print
(15 September 1997, slightly edited by Fravia+)
Following Fravia+'s essay about Screen Ruler v1.0, I decided to improve the display
of the negative hex notation. I'm getting more and more fed up about cracking stupid
protection schemes of stupid programs I will never use. I always really enjoyed
to modify and personalize the tools I often use. Reverse engineering the programs
(even freewares), Window$ DLLs or anything that pleases you in order to adapt them
to your need and to make them working the way you want is the most interesting
part of cracking (see Fravia+'s Filemon or Razzia's Notepad excellent essays).
On the other hand, this kind of Reverse Engineering is actually probably the only way left
for people like me (and probably you too!) who really love ASM, in order to continue
using this beautiful language (who would else ever need an Asm programmer when the
new 'languages' allow any idiot to write overbloated Window$ "programs" without having to
know what 'Mov eax, 0' means?).
As explained by Fravia+, when changing the display from Decimal to Hexadecimal you'll
get an ugly display like 'FFFFFFFF' for '-1', and if you set the ruler to the Vertical
orientation, you'll get a lot of garbage on your ruler because there is not enough room
for such a notation.
I will change the display as per follow:
- The negative Hex value will be turned into a positive one. For instance, 0xFFFFFFEA (-22)
will be change to 0x16 (22).
- A '+' or '-' sign will be added.
So, 0xFFFFFFEA will be shown as '16 -' and 0xF0 as 'F0 +', 0x01 as '1 +'...
Since the original program displays the words 'Pixel' or 'Pixels', we will put there
our '-' and '+' signs instead.
Regarding the Hex display, Fravia+ already showed you the 'trick', changing the '%i' to
'%x'. For those who don't know why, it is just an argument passed to the WsprintfA
function:
int WsprintF(LPTSTR lpBuffer, LPCTSTR lpszFormatString, [argument]...)
'%i' is used for a Decimal value (note that it could be '%d' as well), and '%x' or '%X'
for an Hex value. '%x' will display lowercases ('adbcef') and '%X' uppercases ('ABCDEF').
I will use the uppercase option because the lowercase one leaves a black pixel
on the ruler that the TextOutA function does not overwrite. This problem is due to the
'f' lower char (you'll see what I mean if you try the lowercase option, then move the
cursor to, let's say' 'ff' and then move it back to '10').
A 'F' uppercase char will avoid this problem.
So let's fix that right now:
We had:
00007990: 74 6D 61 70-00 53 69 7A-65 5F 56 5F-42 69 74 6D tmap.Size_V_Bitm
000079A0: 61 70 00 25-69 00 20 50-69 78 65 6C-00 20 50 69 ap.%i..Pixel..Pi
000079B0: 78 65 6C 73-00 25 69 00-50 69 78 00-25 69 00 25 xels.%i.Pix.%i.%
000079C0: 69 00 53 63-72 65 65 6E-20 52 75 6C-65 72 00 00 i.Screen.Ruler..
We change it to:
00007990: 74 6D 61 70-00 53 69 7A-65 5F 56 5F-42 69 74 6D tmap Size_V_Bitm
000079A0: 61 70 00 25-58 00 20 2D-00 00 00 00-00 20 2B 00 ap.%X..-......+.
000079B0: 00 00 00 00-00 25 58 00-50 69 78 00-25 69 00 25 .....%X.Pix.%i.%
000079C0: 69 00 53 63-72 65 65 6E-20 52 75 6C-65 72 00 00 i.Screen.Ruler..
I left the two '%i' preceding 'Screen Ruler' because they are used for the ruler's
graduation, so that our tools gives us both Hex/Dec values.
Now, we are ready to start.
We only need a good Hex/ASM editor, like HView. (All codes and offsets shown in this
essay come from HView v5.5)
First, let's see how SRuler checks the cursor location and displays it. As there are
2 positions (vertical and horizontal) for the ruler, it uses 2 different ways
to do so:
00001B82: 83783400 cmp d,[eax][00034],000 ; Is ruler Vertical?
00001B86: 745B je 000001BE3 ; If yes, jump
** Horizontal Ruler **
00001B88: 0FBF4508 movsx eax,w,[ebp][00008] ; Get cursor position in Eax
00001B8C: 50 push eax ; Push it
00001B8D: 68A3A34000 push 00040A3A3 ; Get output in Decimal format (%i)
00001B92: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001B95: 50 push eax ; Push it
00001B96: FF15E8E34000 wsprintfA ;USER32.dll ; Store in Ebp-58 cursor position
00001B9C: 83C40C add esp,00C
00001B9F: 66837D0801 cmp w,[ebp][00008],001 ; Is it 1?
00001BA4: 7407 je 000001BAD ; Jump if yes
00001BA6: 66837D08FF cmp w,[ebp][00008],0FF ; Is it -1?
00001BAB: 7507 jne 000001BB4 ; Jump if no
00001BAD: 68A6A34000 push 00040A3A6 ; "Pixel"
00001BB2: EB05 jmps 000001BB9
00001BB4: 68ADA34000 push 00040A3AD ; "Pixels"
00001BB9: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001BBC: 50 push eax ; Push it
00001BBD: E8391C0000 call 0000037FB ; Store "Pixel(s)" in Ebp-58 too
00001BC2: 83C408 add esp,008
00001BC5: 8D45A8 lea eax,[ebp][-0058] ; Get offset of Datas to display
00001BC8: 50 push eax
00001BC9: E8591C0000 call 000003827 ; Concat cursor pos. + "Pixel(s)"
00001BCE: 83C404 add esp,004
...
00001BE1: EB67 jmps 000001C4A ; Jump to Display_Cursor_Position
** Vertical Ruler **
00001BE3: 0FBF450C movsx eax,w,[ebp][0000C] ; Get cursor position in Eax
00001BE7: 0501000000 add eax,000000001 ; Add 1 to get actual position
00001BEC: 50 push eax ; Push it
00001BED: 68B5A34000 push 00040A3B5 ; Get output in Decimal format (%i)
00001BF2: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001BF5: 50 push eax ; Push it
00001BF6: FF15E8E34000 wsprintfA ;USER32.dll ; Store in Ebp-58 cursor position
...
00001C13: FF159CE24000 TextOutA ;GDI32.dll ; Display it
00001C19: 68B8A34000 push 00040A3B8 ; Get "Pix"
00001C1E: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001C21: 50 push eax ; Push it
00001C22: E8151C0000 call 00000383C ; Store "Pix" in Ebp-58
...
00001C4E: FF159CE24000 TextOutA ;GDI32.dll ; Display_Cursor_Position if Horizontal
!
; ; or 'Pix' if Vertical.
00001C54: FF75A4 push d,[ebp][-005C]
...
Pretty obvious as you can see.
Now, we need to find some places where we can put our own code. We will need
a little more than 100 byte for that.
As Fravia+ cracked the Nagscreens checking, we should find there the room we need:
000019FB: E8EA100000 call 000002AEA
00001A00: 83C404 add esp,004
00001A03: 89C1 mov ecx,eax
00001A05: 83F901 cmp ecx,001
00001A08: 752B jne 000001A35 ; HERE! Make it always Jump
00001A0A: 6A00 push 000
00001A0C: 68B80B0000 push 000000BB8
00001A11: 6880000000 push 000000080
00001A16: 8B45F0 mov eax,[ebp][-0010]
00001A19: FF7008 push d,[eax][00008]
00001A1C: FF15E0E34000 SetTimer ;USER32.dll
00001A22: 56 push esi
00001A23: 8B4DF0 mov ecx,[ebp][-0010]
00001A26: 8B19 mov ebx,[ecx]
00001A28: FF5350 call d,[ebx][00050] ; Interesting!
00001A2B: 83C404 add esp,004
00001A2E: E99C000000 jmp 000001ACF
00001A33: EB25 jmps 000001A5A
00001A35: 6A05 push 005
We see that, when changing the Jne 1A35 to a Jmp 1A35, the program will never reach
offsets located between :1A08 and :1A35. At offset :1A28 there is a 'call d,[ebx][0050]'
that therefore will never be used. This call calls a routine starting at offset 00002392
and ending at offset :24AA so, 24AA - 2392 = 0x118 that's 280 bytes that we can use in
order to write our own routines.
We will place some code, calls and jumps in other places inside SRuler.exe as well.
As the display of the cursor position as well as the words "Pixel(s)" and "Pix" is
different in the horizontal and the vertical orientation, we will start with the
horizontal one.
1/ Horizontal Ruler
First of all, we need to know if the cursor's position is a positive or negative value.
For this, we will add 0x00 to the cursor's position and then check the Sign Flag (SF) as
per follow:
PushF ; save flags
Add Cursor_location, 0
Jns Positive ; Jump If Not Sign
Negative: Neg Cursor_Location ; Turn it into Positive
Push '-' ; and add '-' sign
Jmp Go_Ahead
Positive: Push '+' ; Add '+' sign
Go_head : PopF ; restore flags
Display_Cursor_Location
We will know if the value is positive or negative but we need to find a place
to store it because we will not be able to check the Sign Flag and then to Push the '+'
or the '-' signs inside the same routine. We found at offset 00001B88 the following code:
00001B88: 0FBF4508 movsx eax,w,[ebp][00008] ; Get cursor position in Eax
Ebp+08 is only checked there so we will use it for our purpose:
Mov word ptr[ebp+08], 0 if Positive
Mov word ptr[ebp+08], 1 if Negative
Now we are ready to write our first routine. As said above, we will write our code
starting at offset 00002392 (I put a ">" in front of all changed code and a "+" sign
in front of any offsets moved a couple of bytes ahead due to the new code insertion):
> 00002392: 669C pushf
> 00002394: 83C000 add eax,000
> 00002397: 790A jns 0000023A3 ; jmp if positive
> 00002399: F7D8 neg eax ; otherwise Neg !
it
> 0000239B: 66C745080100 mov w,[ebp][00008],00001 ; Set flag to 1
> 000023A1: EB06 jmps 0000023A9
> 000023A3: 66C745080000 mov w,[ebp][00008],00000 ; Set flag to 0 if Positive
> 000023A9: 669D popf
> 000023AB: C3 retn &nbs!
p; ; back to the Caller
This routine will be called from within the listing of SRuler.exe I described above.
We must insert the Call and Flag check between offsets 1B88 and 1BB9.
We change it to:
00001B88: 0FBF4508 movsx eax,w,[ebp][00008] ; Get cursor position in Eax
> 00001B8C: E801080000 call 000002392 ; Call our new routine
+ 00001B91: 50 push eax ; Push Cursor position
+ 00001B92: 68A3A34000 push 00040A3A3 ; Get output in Hex format (%X)
+ 00001B97: 8D45A8 lea eax,[ebp][-0058]
+ 00001B9A: 50 push eax
+ 00001B9B: FF15E8E34000 wsprintfA ;USER32.dll ; Store in Ebp-58 cursor position
+ 00001BA1: 83C40C add esp,00C
> 00001BA4: 66837D0800 cmp w,[ebp][00008],000 ; OUR flag : Is it Positive?
> 00001BA9: 7407 je 000001BB2 ; Yes jmp, otherwise...
+ 00001BAB: 68A6A34000 push 00040A3A6 ; Push '-'
+ 00001BB0: EB07 jmps 000001BB9 ; Go_Ahead
+ 00001BB2: 68ADA34000 push 00040A3AD ; Push '+'
> 00001BB7: 40 inc eax ; Unused ...
> 00001BB8: 48 dec eax ; ...but useful.
00001BB9: 8D45A8 lea eax,[ebp][-0058] ; back to original code
That's all for the Horizontal ruler.
2/ Vertical Ruler
We cannot use exactly the same routine because when the ruler is vertical, it will just
display the word 'Pix' instead of 'Pixel' or 'Pixels' and the cursor position is not
concated with 'Pix' this time as both words are printed on different lines.
However we will use the same Push '+' and Push '-' but we will not need our flag Ebp+08.
As words are not concated, the program displays first the cursor location and, later, 'Pix'.
So, we will write two routines:
- Getting the Positive or Negative value of the cursor position:
As the first routine we wrote starts at offset :2392 and ends at offset :23AB we will write
our second one starting at offset :23AC. So, we can already write the Call to it:
We had:
00001BE3: 0FBF450C movsx eax,w,[ebp][0000C] ; Get cursor position in Eax
00001BE7: 0501000000 add eax,000000001 ; Add 1 to get actual position
00001BEC: 50 push eax ; Push it
00001BED: 68B5A34000 push 00040A3B5 ; Get output in Decimal format (%i)
00001BF2: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001BF5: 50 push eax ; Push it
00001BF6: FF15E8E34000 wsprintfA ;USER32.dll ; Store in Ebp-58 cursor position
We change it to:
00001BE3: 0FBF450C movsx eax,w,[ebp][0000C]
> 00001BE7: E8C0070000 call 0000023AC ; Call our second routine
00001BEC: 50 push eax
00001BED: 68B5A34000 push 00040A3B5 ; Get output in HEX format (%X)
00001BF2: 8D45A8 lea eax,[ebp][-0058]
00001BF5: 50 push eax
00001BF6: FF15E8E34000 wsprintfA ;USER32.dll
In order to add our Call, we deleted the 'add eax,01' so we will need to add it inside
our 2nd routine:
+ 000023AC: 0501000000 add eax,000000001
> 000023B1: 669C pushf ; Push flags
> 000023B3: 83C000 add eax,000 ; add 0 to cursor's location
> 000023B6: 7902 jns 0000023BA ; jmp if positive
> 000023B8: F7D8 neg eax ; otherwise neg it
> 000023BA: 669D popf ; restore flags
> 000023BC: C3 retn ; back to!
caller
- Adding a '+' or '-' sign:
Our second routine ends at offset :23BC. So we will write our 3rd one at offset :23BD
and we can already put a jump to it:
We had:
00001C13: FF159CE24000 TextOutA ;GDI32.dll ; Display Cursor position
00001C19: 68B8A34000 push 00040A3B8 ; Get "Pix"
00001C1E: 8D45A8 lea eax,[ebp][-0058] ; Get offset for output
00001C21: 50 push eax ; Push it
00001C22: E8151C0000 call 00000383C ; Store "Pix" in Ebp-58 to display it
We change it to:
00001C13: FF159CE24000 TextOutA ;GDI32.dll
> 00001C19: E99F070000 jmp 0000023BD ; Jmp to our 3rd routine
00001C1E: 8D45A8 lea eax,[ebp][-0058]
00001C21: 50 push eax
00001C22: E8151C0000 call 00000383C ; Will store '+' or '-' in Ebp-58
We got rid of the Push 'Pix' and it gave us exactly the room we needed to add our jmp.
To write our routine, we need to know the cursor location. Fortunately, it is stored
in Ebp+0C. Since right after our Jump, Ebp-58 (which contains the offset where the cursor
location is stored) will be moved into Eax, we can temporarily use this register to
store the cursor position with a Movsx instruction.
So, the 3rd routine:
> 000023BD: 0FBF450C movsx eax,w,[ebp][0000C] ; Get the cursor location in Eax
> 000023C1: 0501000000 add eax,000000001 ; Add 1 to get the new location
> 000023C6: 669C pushf ; Save flags
> 000023C8: 83C000 add eax,000 ; Add 0
> 000023CB: 790B jns 0000023D8 ; Jns to Positive otherwise
> 000023CD: F7D8 neg eax ; Neg it
> 000023CF: 669D popf ; Restore flags
> 000023D1: 68A6A34000 push 00040A3A6 ; Push '-'
> 000023D6: EB07 jmps 0000023DF ; Go_Ahead
> 000023D8: 669D popf ; Restore flags
> 000023DA: 68ADA34000 push 00040A3AD ; Push '+'
> 000023DF: E93AF8FFFF jmp 000001C1E ; Jump back
> 000023E4: 90 nop
> 000023E5: 90 nop
You'll notice that we had to restore the Flags BEFORE pushing '+' AND '-' to avoid
a system crash.
Now the patch is done and you can use this nice little tool for your +cracking purposes!
Frog's Print
(c) Frog's Print, 1997. All rights reversed.
You are deep inside Fravia's page of reverse
engineering, choose your way out:
Back to project 6
The
"call relocation table' and its importance :-)
homepage
links
anonymity
+ORC students' essays tools
cocktails
academy database
antismut search_forms mail_Fravia
is reverse engineering legal?