An interesting tool: Screen Ruler
The "pixel shortcut" method
by Fravia+ (MSRE)
+cracker!

(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.

trainin7
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 red anonymity +ORC students' essays tools cocktails
academy database antismut search_forms mail_Fravia
is reverse engineering legal?