Delphi Reverse Engineering
Adding functionality to a Delphi program
student
Not Assigned
26 April 2000
by +DaFixer
Courtesy of Fravia's page of reverse engineering
slightly edited
by Tsehp
There is a crack, a crack in everything That's how the light gets in
Rating
( )Beginner ( )Intermediate (X)Advanced ( )Expert

This essay shows how to change event handlers of a Delphi program and how to add functionality to it using native VCL routines and only HEX editor. A knowlage about Delphi programming will be in advance for you while reading the essay.
Delphi Reverse Engineering
Adding functionality to a Delphi program
Written by +DaFixer


Introduction
Well, this is my first essay about Delphi reversing and I'm takling about how to add a functionality to Delphi program using VCL library directly. Some interesting facts about Delphi executables format, class info and DFM resources are shown. There is no special code that is added and no target that is cracked. I just show the principle schema of event handling in Delphi and various ways we can play with every program. I hope you'll enjoi it! The next part(s) will be published as soon as I write them :)

Tools required
HEX Editor, nothing else

Target's URL/FTP
There is no special target. You may use any program written in Delphi (that is not packed/crypted) and play with it. Anyway in the essay the examples are givven to a simple test peroject I wrote for the essay. You may download it here.

Program History
May be before reading my essay you may want to check the LaZaRuS paper Finding standard functions in Delphi/C++ Builder and also some facts about DFM RCDATA in the +Aitor work DFM Files, Windows RCDATA and Object Conversion Routines

Essay
  PART 1

* Delphi executable, Class information and DFM resources
* Event Handlers. 
* Re-assigning events editing DFM resources and class information.


  Before all I whould like to explain the internal format of a Delphi executable according 
to our reversing goals. All Delphi programs compiled by Delphi 3, 4 or 5 has the following 
sections : CODE, DATA,  BSS, .idata, tls, .rdata, .rsrc. The most important from our point
 of view are the CODE and .rsrc sections.
   

The .rsrc section 
------------------------------------------------------------------------------------------

    Here except the "normal" resources are situated also the Project Information and DFM
resources. The section begins with the usual resource tables. After that starts the Project
Information and finally the DFM resources. They are the description of the forms, all 
contained controls and also all initialization settings for published properties of the
visual and not visual controls in the forms. The resources for separate forms are in
separate "sections" (separate resource). Each of them begins with the bytes : 
#54,#50,#46,#30 (TPF0) and immediately after that the name of the form as pascal string (
this means the first byte is the length of the string). Each DFM section is exactly copied 
by the linker from your original .dfm file when your project is linked. Note that DFM 
resources are so called RCDATA type resources that are also described in the resource 
tables in .rsrc PE section. This means that you can edit them with a resource editor - like
Borland Resource Workshop. The more interesting for us is what each DFM resource contains. 
The simple answer is that there is stored all the information that the Delphi Object 
Inspector shows you when you have the project opened. And this means that you can reassign 
all these published properties of the controls in the forms simply by editing the DFM RCDATA
resources. One of the important things is that you can also reassign the event handlers. 
   Another thing is that there are procedures in the Delphi VCL itself that allows you to 
read these RCDATA resources and also to save them as RES ot TXT format. In the classes.pas 
are defined these procedures:
   
   ObjectBinaryToText()
   ObjectResourceToText()
   ObjectTextToBinary()
   ObjectTextToResource()

   Using them you can simply transform binary DFM RCDATA resources into other ways of 
representing them. One usual text description of a form, that in our case contains one 
TButton looks like this:
   
object Form1: TForm1
  Left = 192
  Top = 105
  Width = 215
  Height = 109
  Caption = 'Test Project 1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 8
    Top = 16
    Width = 75
    Height = 25
    Caption = 'Show Form2'
    TabOrder = 0
    OnClick = Button1Click
  end
end
   
  By the way while you are designing your forms, Delphi uses these procedures very often. 
Try for example to select some object in your form. Then press Ctrl+C to copy it. Now if 
you press Ctrl+V you will paste this button in the form, but if you are in the unit code 
of Delphi editor and press there Ctrl+V you will see that Delphi will call 
ObjectBinaryToText() and will past in the editor the text representation of the button!
  Now let's have a little example. I have compiled a very simple project that has 2 forms. 
Form1 contains 2 buttons. When you press the Button1 the second form (Form2) is shown and 
when you press the Button2 a text is displayed. The Form2 has only one button that shows 
a text when pressed. So now we will change the event handlers of the two buttons of Form1 
by changing the DFM resources. Open the sample executable with hex editor and find the 
following: 

0004A4E0  020D 0007 5442 7574 746F 6E07 4275 7474  ....TButton.Butt
0004A4F0  6F6E 3104 4C65 6674 0208 0354 6F70 0210  on1.Left...Top..
0004A500  0557 6964 7468 024B 0648 6569 6768 7402  .Width.K.Height.
0004A510  1907 4361 7074 696F 6E06 0A53 686F 7720  ..Caption..Show 
0004A520  466F 726D 3208 5461 624F 7264 6572 0200  Form2.TabOrder..
0004A530  074F 6E43 6C69 636B 070C 4275 7474 6F6E  .OnClick..Button
0004A540  3143 6C69 636B 0000 0754 4275 7474 6F6E  1Click...TButton
0004A550  0742 7574 746F 6E32 044C 6566 7402 0803  .Button2.Left...
0004A560  546F 7002 3005 5769 6474 6802 4B06 4865  Top.0.Width.K.He
0004A570  6967 6874 0219 0743 6170 7469 6F6E 0604  ight...Caption..
0004A580  496E 666F 0854 6162 4F72 6465 7202 0107  Info.TabOrder...
0004A590  4F6E 436C 6963 6B07 0C42 7574 746F 6E32  OnClick..Button2
0004A5A0  436C 6963 6B00 0000 5450 4630 0654 466F  Click...TPF0.TFo

  We will change the Button1.OnClick property to Button2Click and Button2.OnClick property 
to Button1Click:
 
0004A4E0  020D 0007 5442 7574 746F 6E07 4275 7474  ....TButton.Butt
0004A4F0  6F6E 3104 4C65 6674 0208 0354 6F70 0210  on1.Left...Top..
0004A500  0557 6964 7468 024B 0648 6569 6768 7402  .Width.K.Height.
0004A510  1907 4361 7074 696F 6E06 0A53 686F 7720  ..Caption..Show 
0004A520  466F 726D 3208 5461 624F 7264 6572 0200  Form2.TabOrder..
0004A530  074F 6E43 6C69 636B 070C 4275 7474 6F6E  .OnClick..Button
0004A540  3243 6C69 636B 0000 0754 4275 7474 6F6E  2Click...TButton
0004A550  0742 7574 746F 6E32 044C 6566 7402 0803  .Button2.Left...
0004A560  546F 7002 3005 5769 6474 6802 4B06 4865  Top.0.Width.K.He
0004A570  6967 6874 0219 0743 6170 7469 6F6E 0604  ight...Caption..
0004A580  496E 666F 0854 6162 4F72 6465 7202 0107  Info.TabOrder...
0004A590  4F6E 436C 6963 6B07 0C42 7574 746F 6E31  OnClick..Button1
0004A5A0  436C 6963 6B00 0000 5450 4630 0654 466F  Click...TPF0.TFo

  This is all. Now save the new executable and run it. You'll find that when you click
Button1 instead of showing Form2 a text will be shown and when you click Button2 the Form2
will be shown.

  In this way you can reassign events to be handled by other event handlers defined in the 
same form. Also note that you can assign a event handler to an event only if they are 
compatable. This means you can not assign a TButton.OnClick event handler to fot example 
TForm.OnKeyDown. We are also not able by editing DFM RCDATA resources to assign to 
Form1.Button1.OnClick the Form2.Button1Click handler for example. But this can be done in 
a different way. Read below.
  
The CODE section
------------------------------------------------------------------------------------------

  Here all classes information and code is situated. The last procedure in CODE section is 
the DPR code.
  I will not explain the meaning of all data in the class information but will talk about 
how the RVA offset of an event handler can be found. Open the test project in a hex editor. 
We know that there are Form1 and Form2 in this project. Seek for the string resource TForm2
in the CODE section. You'll find it 2 times here:

0003F870  746F 6E31 0100 1300 B804 4400 0C42 7574  ton1......D..But
0003F880  746F 6E31 436C 6963 6B06 5446 6F72 6D32  ton1Click.TForm2
0003F890  0100 58C3 4100 8BC0 9C04 4400 0706 5446  ..X.A.....D...TF
0003F8A0  6F72 6D32 8C03 4400 4440 4300 5500 0555  orm2..D.D@C.U..U
0003F8B0  6E69 7432 0000 8BC0 B8CC 0444 00E8 8EFC  nit2.......D.... 
  
  First note that all the strings are in pascal format. 
  Immediately before the Button1Click stays this: B804 4400. As you can guess this is the 
RVA offset of the event handler Form2.Button1Click. If we disassemble the test project and 
go to offset 004404B8 we will see the following:


* Possible String Reference to: "Hello from Form2"
|
004404B8   B8CC044400             mov     eax, $004404CC

* Reference to: Dialogs.ShowMessage(System.AnsiString)
|
004404BD   E88EFCFFFF             call    00440150
004404C2   C3                     ret

  Well this is the code of TForm2.Button1.OnClick event handler. Now you may be already 
have the idea how to change the RVA offsets of event handlers in different forms. Have you ?
Well we just need to know the RVA of the procedure. Note that you can not simply assign 
every procedure to be an event handler because event handlers of different events have 
different parameters. So in our case we will assigne to Form1.Button1.OnClick the 
Form2.Button1OnClick handler and to Form2.Button1.OnClick the Form1.Button1OnClick handler.
They both are handlers of TNotifyEvent type wich has the declaration:
  
  Type TNotifyEvent = procedure (Sender : TObject) of object;

  So we can assign to TButton.OnClick every procedure that is an event handler from this 
type - TNotifyEvent. 
  OK lets do it now. Before changing event handlers of the two buttons we should know the 
RVA of the other handler. We can find TForm1 string in the CODE section and this will lead 
us to the following:

0003FA50  0000 0742 7574 746F 6E32 0200 1300 B006  ...Button2......
0003FA60  4400 0C42 7574 746F 6E32 436C 6963 6B13  D..Button2Click. 
0003FA70  00D8 0644 000C 4275 7474 6F6E 3143 6C69  ...D..Button1Cli
0003FA80  636B 0654 466F 726D 3101 0058 C341 0090  ck.TForm1..X.A..
0003FA90  9406 4400 0706 5446 6F72 6D31 6405 4400  ..D...TForm1d.D.
0003FAA0  4440 4300 5500 0555 6E69 7431 0000 8BC0  D@C.U..Unit1....

  So we can see that TForm1.Button1Click has RVA offset - 004406D8 and TForm1.Button2Click 
has RVA - 004406B0. Now we will change the TForm1.Button1.OnClick handler with the one at 
offset 004404B8:

0003FA50  0000 0742 7574 746F 6E32 0200 1300 B804  ...Button2......
0003FA60  4400 0C42 7574 746F 6E32 436C 6963 6B13  D..Button2Click. 
0003FA70  00D8 0644 000C 4275 7474 6F6E 3143 6C69  ...D..Button1Cli
0003FA80  636B 0654 466F 726D 3101 0058 C341 0090  ck.TForm1..X.A..
0003FA90  9406 4400 0706 5446 6F72 6D31 6405 4400  ..D...TForm1d.D.
0003FAA0  4440 4300 5500 0555 6E69 7431 0000 8BC0  D@C.U..Unit1....

  And also the TForm2.Button1.OnClick handler with the one at offset 004406D8:

0003F870  746F 6E31 0100 1300 D806 4400 0C42 7574  ton1......D..But
0003F880  746F 6E31 436C 6963 6B06 5446 6F72 6D32  ton1Click.TForm2
0003F890  0100 58C3 4100 8BC0 9C04 4400 0706 5446  ..X.A.....D...TF
0003F8A0  6F72 6D32 8C03 4400 4440 4300 5500 0555  orm2..D.D@C.U..U
0003F8B0  6E69 7432 0000 8BC0 B8CC 0444 00E8 8EFC  nit2.......D.... 

  Well this is all. Save the new executable and run it!


  
  So let now have more fun and write our own event handler, adding the code to the 
executable, that will change the caption of a button. Before doing this we should point 
to the following:

* VCL classes in executable. 
* Finding RVAs of VCL class methods. 
* Conrol IDs. 
* Reading and writing TEdit.Text and TLabel.Caption properties using VCL


  Have you ever asked the question why Delphi executables are so big in size? The answer 
is that in them is stored also the code of all classes from the VLC (Visual Component 
Library) that is needed for your program to run. 
  There is also another way - to compile the program with runtime packages. In this case 
the program will be very small, but will need the vclxx.bpl library to run (The same as 
the C++ MFC library, but mfcxx.dll goes with windows). 

  So we saw that in the CODE section in a Delphi executable is stored class information 
that is not executable code. All the VCL stuff needed by the program is also there but 
there it has no published properties. The exact structure of this class info is known and 
you can restore most of the binary code to pascal code and retrieve *ALL* the typeinfos. 
You can find more information about this at Python's site at 
  
  http://thunder.prohosting.com/~pytho/index.shtml.

  If we want to find the RVA offset of a certain VCL method we can use the ideology of 
byte-to-byte recognition that IDA and DeDe uses. In this way most of the methods from 
component libraries like VCL and MFC can be found. There is almost a unique byte sequence 
for every method. If you have the asm soure of a method and corresponding byte opcodes 
and if you remove all memory offsets that are used in the instructions of this method 
you'll have such a pattern that can be used to identify the method. This technology of 
recognition is called FLIRT (Fast Library Identification and Recognition Technology). 
You can find more information about the IDA FLIRT at:

  http://www.datarescue.com/idabase/flirt.htm
  http://www.datarescue.com/idabase/idaflirt.htm

  So lets return to our goals and find the TControl.SetText VCL method RVA offset in the 
test project we have. This method is used to set the labels and buttons captions and also 
for all classes that inherits TControl. We can find using DeDe DSF function view or just 
"spying" with Delphi CPU Viewer. The ID of TControl.SetText(System.AnsiString) is:

  558BEC6A0053568BF28BD833C055680000000064FF306489208D55FC8BC3E8000000008B45FC8BD6......

  Here 6800000000 is a push instruction but the memory offset is removed/set to 00000000.
  Lets search for this pattern in the test executable. You'll find that the pattern 
558BEC6A0053568BF28BD833C05568 is found to often. More easy will be in this case to seek 
for 64FF306489208D55FC8BC3E8, then ignore the next four bytes and seek for 8B45FC8BD6 after 
that. We will find this sequence here:

00021270  FFFF FF5F 5E5B C390 558B EC6A 0053 568B 
00021270  F28B D833 C055 68CD 1E42 0064 FF30 6489
00021270  208D 55FC 8BC3 E8AD FFFF FF8B 45FC 8BD6

  With easy calculation we can find that the physical offset 21278 corresponds to RVA 
00421E78 in the CODE section. So this is the RVA offset of TControl.SetText. 
  Well lets have fun now and "write" our own event handler to Form1.Button1.OnClick and in 
this handler to change the caption of TForm1.Button2. Before doing this we should know a 
how the params are passed to TControl.SetText. It is not in the usual C way pushing them 
ontto the stack. If the procedure is a class method, as in our case, EAX contains the 
pointer to the class instance - in our case TForm.Button1. The first parameter is passed 
in EDX.
  So the pseudo code of our handler should look like this:

  mov  eax, offset_of_Button1
  mov  edx, offset_of_new_caption
  call TControl.SetText

  And this is all. Well the problem is how to find the offset (pointer) to our Button1. 
  If you are a Delphi programmer you have many times seen this parameter in event handlers 
of type TObject and having the name Sender. Normaly when the event handler is called by the 
generated event this Sender is the Form. And due to convention it (the Form pointer) is in 
EAX while steping in the code of handler. 
  Now I will point on the class info of our TForm1 again. May be you have noticed that 
except the event handlers names, and RVAs, there were also the name of controls in the Form:

00003FA30 58AC 4300 947A 4300 0200 8906 4400 C402  X.C..zC.....D...
00003FA30 0000 0000 0742 7574 746F 6E31 C802 0000  .....Button1....

  Note this 000002C4 value before "Button1". May be you wonder what is this. Well this is 
the offset after the offset of TForm2 where the pointer to Button1 can be found. So may be 
you are wondering were will point EAX+000002C4 in our event handler. YES, correct answer - 
to Button1. So this will be our code:

8B80C8020000           mov     eax, [eax+000002C8]
BAxxxxxxxx             mov     edx, the_offset_of_the_new_caption
E8xxxxxxxx             call    00421E78

  Now we need to find some "free space" for the code of our handler, to calculate the 
relative offset off TControl.SetText and to set the RVA offset of our handler as a handler 
of TForm1.Button1.OnClick event.
  First we can put our code at the end of .rsrc section. A good offset will be physical 
0004A7A0. This will correspond to RVA 0044F1A0 in .rsrc section. So now we can input the 
relative offset of our call:

0044F1A0  8B80C8020000           mov     eax, [eax+000002C8]
0044F1A6  BAB1F14400             mov     edx, 0044F1B1
0044F1AB  E8C82CFDFF             call    00421E78 
0044F1B0  C3                     ret

  Finally we need to add these bytes at physical offset 0004A7A0 :

  8B80C8020000BAB1F14400E8C82CFDFFC36269672066756E

  And also to change the TForm1 class info :

0003FA70  00A0 F144 000C 4275 7474 6F6E 3143 6C69  ...D..Button1Cli


  This is all now. Save new executable and run it to see the result!


  See ya again in PART 2.


Final Notes
If you are interested in Delphi reversing and you still havent found the power of 
DeDe you may want to test it. Feel free to send any 
coments and feedbacks to d_fixer@hotmail.com



Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside Fravia's page of reverse engineering, choose your way out:


redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia
redIs reverse engineering legal?

=