Cracking Delphi Programs

15
Cracking Delphi Programs By CodeRipper Tools used: DeDe by DaFixer, Olly debugger, PE Explorer, De Decompiler Lite I. Let you familiarize with Delphi: A form is a class which contain a lot of buttons, radiobutons etc. So if we have a form called TfrmPurchase we can have a lot of properties/events: TfrmPurchase.btnOKClick – called when we click OK TfrmPurchase.btnCancelClick - called when we click Cancel TfrmPurchase.FormCreate – is called when the form is created; default when you double click on Form TfrmPurchase.FormShow - is called when the form is showed TfrmPurchase.TimerTimer – is called when the timer is out (something like WM_TIMER from VISUAL C++) TfrmPurchase.Edit1Change - called when the contents of Edit1 is changed TfrmPurchase.Memo1Change - called when the contents of Memo1 is changed If we have on the body of TForm1.Button1Click (under Nag Form.exe): Form1.DestroyWindowHandle; // kill Form1 Form2.ShowModal; // show the Form2 Form3.ShowModal; // show the Form3 The code will look like this: 0045241F MOV EAX,DWORD PTR DS:[455B74] ; reference to Form1 (under Class Information the BSS value) 00452424 MOV EDX,DWORD PTR DS:[EAX] ; now edx contain VMT Ptr (Classes Info in DeDe) 00452426 CALL DWORD PTR DS:[EDX+B4] 0045242C MOV EAX,DWORD PTR DS:[454378] ; reference to TForm2 instance (DATA)

Transcript of Cracking Delphi Programs

Page 1: Cracking Delphi Programs

Cracking Delphi ProgramsBy CodeRipper

Tools used: DeDe by DaFixer, Olly debugger, PE Explorer, De Decompiler Lite

I. Let you familiarize with Delphi:A form is a class which contain a lot of buttons, radiobutons etc.So if we have a form called TfrmPurchase we can have a lot of properties/events:TfrmPurchase.btnOKClick – called when we click OKTfrmPurchase.btnCancelClick - called when we click CancelTfrmPurchase.FormCreate – is called when the form is created; default when you double click on FormTfrmPurchase.FormShow - is called when the form is showedTfrmPurchase.TimerTimer – is called when the timer is out (something like WM_TIMER from VISUAL C++)TfrmPurchase.Edit1Change - called when the contents of Edit1 is changedTfrmPurchase.Memo1Change - called when the contents of Memo1 is changed

If we have on the body of TForm1.Button1Click (under Nag Form.exe):Form1.DestroyWindowHandle; // kill Form1Form2.ShowModal; // show the Form2Form3.ShowModal; // show the Form3

The code will look like this:0045241F MOV EAX,DWORD PTR DS:[455B74] ; reference to Form1 (under Class Information the BSS value)00452424 MOV EDX,DWORD PTR DS:[EAX] ; now edx contain VMT Ptr (Classes Info

in DeDe)00452426 CALL DWORD PTR DS:[EDX+B4]0045242C MOV EAX,DWORD PTR DS:[454378] ; reference to TForm2 instance (DATA)00452431 MOV EAX,DWORD PTR DS:[EAX] ; now eax contains the HEAP value00452433 MOV EDX,DWORD PTR DS:[EAX] ; now edx contain VMT Ptr00452435 CALL DWORD PTR DS:[EDX+F8]0045243B MOV EAX,DWORD PTR DS:[454220] ; reference to TForm2 instance

; (DATA)00452440 MOV EAX,DWORD PTR DS:[EAX]00452442 MOV EDX,DWORD PTR DS:[EAX]00452444 CALL DWORD PTR DS:[EDX+F8]

For finding these values you must go at Classes Info (in DeDe), double clickon the wanted form and look on the right part – you will see DATA,BSS,HEAP.A class is an abstract structure witch contains methods and variables (properties).An object is an instance of one class, a materialization of a class.Objects are kept in a special memory called HEAP.

Page 2: Cracking Delphi Programs

Delphi use for parsing parameters to functions EAX, EDX, ECX, if they are more then 3 parameters will be used the stack (push parameter_4, push parameter_5…). Note that these parameters are passed in reverse order.

Delphi deals with global and local variables reference it on the following way:- [ebp+value] means that is pointer to a global variable- [ebp-value] means that it is pointer to a local variable

Example:00484A6C 8B45FC mov eax, [ebp-$04] ; pointer to a local variable in eax00484A6F E830F1F7FF call 00403BA4 ; call System.LStrOfChar()

II. How a Delphi program looks at entry point:The code of program:begin Application.Initialize; Application.CreateForm(TForm1, Form1); the NAG form which is first created Application.CreateForm(TForm2, Form2); Application.CreateForm(TForm3, Form3); Application.Run;end.

The compiled code will be:00452668 PUSH EBP00452669 MOV EBP,ESP0045266B ADD ESP,-100045266E MOV EAX,004524C000452673 CALL .00405C94 ; this is the _InitExe routine that also initialize units00452678 MOV EAX,DWORD PTR DS:[454260] ; TApplication instance (Classes Info)0045267D MOV EAX,DWORD PTR DS:[EAX]0045267F CALL .00450578 ; Forms.TApplication.Initialize()00452684 MOV ECX,DWORD PTR DS:[454344] ; for killing the Form1 we must change

; this to “jmp 0045269C”; You should notice that the first form which is created is considerate here as being the main form0045268A MOV EAX,DWORD PTR DS:[454260]0045268F MOV EAX,DWORD PTR DS:[EAX]00452691 MOV EDX,DWORD PTR DS:[452274]00452697 CALL .00450590 ; Application.CreateForm(TForm1, Form1);0045269C MOV ECX,DWORD PTR DS:[454378]004526A2 MOV EAX,DWORD PTR DS:[454260]004526A7 MOV EAX,DWORD PTR DS:[EAX]004526A9 MOV EDX,DWORD PTR DS:[451F04]004526AF CALL .00450590 ; Application.CreateForm(TForm2, Form2);004526B4 MOV ECX,DWORD PTR DS:[454220]004526BA MOV EAX,DWORD PTR DS:[454260]004526BF MOV EAX,DWORD PTR DS:[EAX]004526C1 MOV EDX,DWORD PTR DS:[4520C8]004526C7 CALL .00450590 ; Application.CreateForm(TForm3, Form3);004526CC MOV EAX,DWORD PTR DS:[454260]

Page 3: Cracking Delphi Programs

004526D1 MOV EAX,DWORD PTR DS:[EAX]004526D3 CALL .00450610 ; Application.Run;004526D8 CALL .00403DC8 ; close the application (call ExitProcess)

_InitExe - Initialization of units means running its initialization code.So you must step into 00405C94 and trace until you reach the IniUnits() routine.If you enter under 00405C94 you will see a GetModuleHandleA, after that is a call in which you must enter, after you enter inside him you will see another one -> step over this call whit F8 and return (RETN), you will see another call -> this time step into this call and you will find:00403C1C MOV DWORD PTR DS:[455014],JMP.&kernel32.RaiseException00403C26 MOV DWORD PTR DS:[455018],JMP.&kernel32.RtlUnwind00403C30 MOV DWORD PTR DS:[45563C],EAX00403C35 XOR EAX,EAX00403C37 MOV DWORD PTR DS:[455640],EAX00403C3C MOV DWORD PTR DS:[455644],EDX00403C42 MOV EAX,DWORD PTR DS:[EDX+4]00403C45 MOV DWORD PTR DS:[45502C],EAX00403C4A CALL .00403B0800403C4F MOV BYTE PTR DS:[455034],000403C56 CALL .00403BB4 ; you must trace into inside this one00403C5B RETN

If you enter inside call 00403BB4 you will find:…00403BDC CMP EDI,EBX00403BDE JLE SHORT .00403BF700403BE0 MOV EAX,DWORD PTR SS:[EBP-4]00403BE3 MOV ESI,DWORD PTR DS:[EAX+EBX*8] ; prepare the offset of initialization ; routine of a unit00403BE6 INC EBX ; increase processed units counter00403BE7 MOV DWORD PTR DS:[455640],EBX00403BED TEST ESI,ESI ; is there any initialization routine for this unit?00403BEF JE SHORT .00403BF3 ; if no, then process next unit00403BF1 CALL ESI ; else call it!00403BF3 CMP EDI,EBX ; did we processed all units?00403BF5 JG SHORT .00403BE0 ; if no go backYou can get a list whit all units from the program:Open the exe file with PE Explorer and go to Resource Viewer/Editor; double click on RC Data and click to PACKAGEINFO and you will see a list with all units from the program.

How we can simply find the offset of a method:

Load CrackMe#3.exe in Resource Tuner or PE Explorer and go at RC Data.TFORM1 has two buttons Button1 and Button2, Button1 has the event OnClick Button1Click and Button2 has the event OnClick Button2Click.

Page 4: Cracking Delphi Programs

Also we have a menu called MainMenu1 a submenu called Help1 and the menu item is called About1 -> About1 has the event OnClick About1Click.In the case of an Editbox we could also have the event OnChange Edit1Change (called when the text from Edit1 is changed).

Next step:We load the file under a hexeditor and we search for the ASCII string "Button1Click":

000531C0 07 42 75 74 74 6F 6E 31 F4 02 00 00 01 00 06 4C .Button1ô......L000531D0 61 62 65 6C 31 F8 02 00 00 01 00 06 4C 61 62 65 abel1ø......Labe000531E0 6C 32 01 00 13 00 28 3E 45 00 0C 42 75 74 74 6F l2....(>E..Butto000531F0 6E 31 43 6C 69 63 6B 05 54 47 6F 6F 64 02 00 60 n1Click.TGood..

The red value before the finded string represents the address of methods called when you click "Button1": 00453E28

Similar in the case of About1 we have 00454814.Similar in the case of Label3Click we have 00454824.

How we can easily find the code executed when you press a button or a menu items

Purpose of this: You got the code called when you click a menu item and we want to find the address which is called when you click on any menu item!Same things works for a Visual C++ program which use MFC42.DLL.

1. In the case of labels/buttons:We set a breakpoint to 00454824, we click on Label3 and after we return from 00454824 we find:0043248E TEST BYTE PTR DS:[EBX+1C],1000432492 JNZ SHORT CrackMe#.004324A600432494 CMP DWORD PTR DS:[EBX+6C],000432498 JE SHORT CrackMe#.004324A60043249A MOV EDX,EBX0043249C MOV EAX,DWORD PTR DS:[EBX+6C]0043249F MOV ECX,DWORD PTR DS:[EAX]004324A1 CALL DWORD PTR DS:[ECX+18]004324A4 JMP SHORT CrackMe#.004324BE004324A6 CMP WORD PTR DS:[EBX+122],0004324AE JE SHORT CrackMe#.004324BE004324B0 MOV EDX,EBX004324B2 MOV EAX,DWORD PTR DS:[EBX+124]004324B8 CALL DWORD PTR DS:[EBX+120] ; this one calls the method 00454824004324BE POP EBX ; we are here004324BF RETN

Page 5: Cracking Delphi Programs

The address 004324B8 is called in the case of all buttons and all of labels, just set a breakpoint on it.

2. In the case of menu items:We set a breakpoint to 00454814, we click on About and after we return from 00454814 we find:00442791 MOV EAX,DWORD PTR DS:[EAX+40]00442794 CMP EAX,DWORD PTR DS:[EBX+88]0044279A JE SHORT CrackMe#.004427AC0044279C MOV EDX,EBX0044279E MOV EAX,DWORD PTR DS:[EBX+8C]004427A4 CALL DWORD PTR DS:[EBX+88]004427AA JMP SHORT CrackMe#.004427DC004427AC TEST BYTE PTR DS:[EBX+1C],10004427B0 JNZ SHORT CrackMe#.004427C4004427B2 CMP DWORD PTR DS:[EBX+44],0004427B6 JE SHORT CrackMe#.004427C4004427B8 MOV EDX,EBX004427BA MOV EAX,DWORD PTR DS:[EBX+44]004427BD MOV ECX,DWORD PTR DS:[EAX]004427BF CALL DWORD PTR DS:[ECX+18]004427C2 JMP SHORT CrackMe#.004427DC004427C4 CMP WORD PTR DS:[EBX+8A],0004427CC JE SHORT CrackMe#.004427DC004427CE MOV EDX,EBX004427D0 MOV EAX,DWORD PTR DS:[EBX+8C]004427D6 CALL DWORD PTR DS:[EBX+88] ; this one calls the method 00454814004427DC POP ESI ; we are here004427DD POP EBX004427DE RETN

The address 004427D6 is called in the case of all buttons and all of menu items, just set a breakpoint on it.

Disable a menu item:

EnableMenuItem api is sometimes used to disable a menu item:

0012F074 0044C24A CALL to EnableMenuItem from CrackMe#.0044C2450012F078 002E0598 hMenu = 002E05980012F07C 0000F020 ItemID = F020 (61472.)0012F080 00000001 Flags = MF_BYCOMMAND|MF_GRAYED|MF_STRING

Also can be used AppendMenuA or AppendMenuW:BOOL AppendMenu( HMENU hMenu, UINT uFlags,

Page 6: Cracking Delphi Programs

UINT_PTR uIDNewItem, LPCTSTR lpNewItem);If the uFlags is 1 the menu item will be disabled, if uFlags is 0 the menu item will be enabled!

I. Killing NAG FORMS

Do “he ReleaseCapture” on Olly (ReleaseCapture is from user32.dll) – under same way can be also used for MessageDlg/ShowMessageYou should see something like this:0045306D MOV DL,10045306F MOV EAX,DWORD PTR DS:[410458]00453074 CALL HelpMan_.0040CB8C00453079 CALL HelpMan_.004037B00045307E CALL JMP.&user32.GetCapture00453083 TEST EAX,EAX00453085 JE SHORT HelpMan_.0045309800453087 PUSH 0 ; lParam = 000453089 PUSH 0 ; wParam = 00045308B PUSH 1F ; Message = WM_CANCELMODE0045308D CALL JMP &user32.GetCapture00453092 PUSH EAX ; hWnd00453093 CALL JMP.&user32.SendMessageA00453098 CALL JMP.&user32.ReleaseCapture0045309D MOV EAX,DWORD PTR SS:[EBP-4] ; ReleaseCapture return to this004530A0 OR BYTE PTR DS:[EAX+2CC],8004530A7 CALL JMP.&user32.GetActiveWindowDelete the hardware breakpoint and set a hardware breakpoint to last ret and Run with F9.Press “Continue” on form.You should now break to last ret.Now we step over with F8 a lot of times until we see something like this:006A0349 MOV EAX,DWORD PTR DS:[6AB3EC]006A034E MOV EAX,DWORD PTR DS:[EAX]006A0350 MOV EDX,DWORD PTR DS:[EAX]006A0352 CALL DWORD PTR DS:[EDX+D8] ; this create the form – which could be a nasty NAG - nop him and you will kill the NAG!006A0358 MOV EAX,DWORD PTR DS:[6AB76C] ; we land here

A strange way to kill the NAG:For some NAGS replace at 006A0352 with the method called when you click Try or Continue ( example: call TReminderForm.TryButtonClick) and now the beach always starts without NAG!

Page 7: Cracking Delphi Programs

II. Killing hardest NAGS:

For some nags first way (replaing the NAG creation whit nop) won’t work so here is the second way of doing it.Do “he ReleaseCapture” on Olly (ReleaseCapture is from user32.dll)You will now break to user32 code, return from it and you will see: (this is common to all Delphi functions):00492477 MOV DL,100492479 MOV EAX,DWORD PTR DS:[419F78]0049247E CALL scrwon.0040E2A000492483 CALL scrwon.0040427C00492488 CALL scrwon.00407680 ; JMP to USER32.GetCapture0049248D TEST EAX,EAX0049248F JE SHORT scrwon.004924A200492491 PUSH 000492493 PUSH 000492495 PUSH 1F00492497 CALL scrwon.00407680 ; JMP to USER32.GetCapture0049249C PUSH EAX0049249D CALL scrwon.004079A0 ; JMP to USER32.SendMessageA004924A2 CALL scrwon.00407960 ; JMP to USER32.ReleaseCapture004924A7 MOV EAX,DWORD PTR DS:[5CCBF0] ; we land here004924AC CALL scrwon.0049535C004924B1 XOR EAX,EAX004924B3 PUSH EBP004924B4 PUSH scrwon.004926D5004924B9 PUSH DWORD PTR FS:[EAX]004924BC MOV DWORD PTR FS:[EAX],ESP004924BF MOV EAX,DWORD PTR SS:[EBP-4]004924C2 OR BYTE PTR DS:[EAX+2F4],8004924C9 CALL scrwon.00407670 ; JMP to USER32.GetActiveWindow

Delete the hardware breakpoint and set a hardware breakpoint to the last ret from code and Run with F9.Press “Continue” on form.You should now break at last ret.Now step over with F8 until we see something like:005BFAB9 MOV EDX,DWORD PTR DS:[5CBC24]005BFABF MOV DWORD PTR DS:[EDX],EAX005BFAC1 MOV EAX,DWORD PTR DS:[5CBC24]005BFAC6 MOV EAX,DWORD PTR DS:[EAX]005BFAC8 MOV EDX,DWORD PTR DS:[EAX]005BFACA CALL DWORD PTR DS:[EDX+EC] ; this create the code005BFAD0 MOV EAX,DWORD PTR DS:[5CBC24] ; we land here

Now restart the application and set hardware breakpoint on execute to 005BFACA.You should now break to 005BFACA – step into this call and you will see:…………………..……………0049252B PUSH EBP0049252C PUSH scrwon.004926B3

Page 8: Cracking Delphi Programs

00492531 PUSH DWORD PTR FS:[EAX]00492534 MOV DWORD PTR FS:[EAX],ESP00492537 MOV EAX,DWORD PTR SS:[EBP-4]0049253A CALL scrwon.004923500049253F XOR EAX,EAX00492541 PUSH EBP00492542 PUSH scrwon.0049260700492547 PUSH DWORD PTR FS:[EAX]0049254A MOV DWORD PTR FS:[EAX],ESP0049254D PUSH 00049254F PUSH 000492551 PUSH 0B00000492556 MOV EAX,DWORD PTR SS:[EBP-4]00492559 CALL scrwon.00476A8C0049255E PUSH EAX0049255F CALL scrwon.004079A0 ; JMP to USER32.SendMessageA00492564 MOV EAX,DWORD PTR SS:[EBP-4]00492567 XOR EDX,EDX00492569 MOV DWORD PTR DS:[EAX+24C],EDX0049256F MOV EAX,DWORD PTR DS:[5CCBF0]00492574 CALL scrwon.004964D800492579 MOV EAX,DWORD PTR DS:[5CCBF0]0049257E CMP BYTE PTR DS:[EAX+9C],000492585 JE SHORT scrwon.00492596 (74 04)00492587 MOV EAX,DWORD PTR SS:[EBP-4]0049258A MOV DWORD PTR DS:[EAX+24C],200492594 JMP SHORT scrwon.004925AA00492596 MOV EAX,DWORD PTR SS:[EBP-4]00492599 CMP DWORD PTR DS:[EAX+24C],0004925A0 JE SHORT scrwon.004925AA004925A2 MOV EAX,DWORD PTR SS:[EBP-4]004925A5 CALL scrwon.004922A4004925AA MOV EAX,DWORD PTR SS:[EBP-4]004925AD CMP DWORD PTR DS:[EAX+24C],0004925B4 JE SHORT scrwon.0049256F

This code is a loop which wait for user to press a button, if button “Continue” is pressed the je from 00492585 will jump and the application will actually run.But this code is used for all forms of application and if you change the je forever you will have a bug.So we must change code at 005BFACA to jump to our code cave.In our code cave we enter:MOV BYTE PTR [00492585],075 ; change je to jneCALL DWORD PTR DS:[EDX+0EC] ; call the changed codeMOV BYTE PTR [00492585],074 ; we restore back to jeJMP 005BFAD0 ; jump right after NAG creation

The problem:The NAG is still showed for some seconds.I tried to find a way to set a form invisible butt I couldn’t do.

Page 9: Cracking Delphi Programs

“ Form1.Hide; Form2.Show; Form3.Show; „

get translated into:0045103C MOV EAX,DWORD PTR DS:[454B74]00451041 CALL Project1.0044B808 ; Form1.Hide00451046 MOV EAX,DWORD PTR DS:[453358]0045104B MOV EAX,DWORD PTR DS:[EAX]0045104D CALL HideForm.0044B810 ; Form2.Show00451052 MOV EAX,DWORD PTR DS:[453200]00451057 MOV EAX,DWORD PTR DS:[EAX]00451059 CALL Project1.0044B810 ; Form3.Show

Under Form1.Hide you will see:0044B808 XOR EDX,EDX0044B80A CALL .00447BBC0044B80F RETN

Under Form2.Show/ Form3.Show you will see:0044B810 PUSH EBX0044B811 MOV EBX,EAX0044B813 MOV DL,10044B815 MOV EAX,EBX0044B817 CALL HideForm.00447BBC0044B81C MOV EAX,EBX0044B81E CALL Project1.0042DF740044B823 POP EBX0044B824 RETN

We set a breakpoint on SetWindowPos and you will fiind:0044FDC8 PUSH EBP0044FDC9 MOV EBP,ESP0044FDCB PUSH EBX0044FDCC MOV EBX,EAX0044FDCE MOV EAX,DWORD PTR SS:[EBP+8]0044FDD1 MOV EAX,DWORD PTR DS:[EAX-4] ; mov in eax contents of DWORD PTR DS:[453B40], now EAX = 009512940044FDD4 MOV EAX,DWORD PTR DS:[EAX+30h] ; hwnd pointed by DS:[009512C4] – hWnd = 'Project1',class='TApplication'0044FDD7 PUSH EAX ; hWnd0044FDD8 CALL JMP.&user32.IsWindowVisible0044FDDD CMP EAX,10044FDE0 SBB EAX,EAX0044FDE2 INC EAX0044FDE3 CMP AL,BYTE PTR DS:[451FCC]0044FDE9 JNZ SHORT .0044FE1E0044FDEB CMP BL,BYTE PTR DS:[451FCC]0044FDF1 JE SHORT .0044FE1E0044FDF3 MOVZX EAX,BL

Page 10: Cracking Delphi Programs

0044FDF6 MOVZX EAX,WORD PTR DS:[EAX*2+451FD0] ; we patch this to put in eax 97h so the form will be hidden!0044FDFE PUSH EAX ; Flags = SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW (97h)0044FDFF PUSH 0 ; Height = 00044FE01 PUSH 0 ; Width = 00044FE03 PUSH 0 ; Y = 00044FE05 PUSH 0 ; X = 00044FE07 PUSH 0 ; InsertAfter = HWND_TOP0044FE09 MOV EAX,DWORD PTR SS:[EBP+8]0044FE0C MOV EAX,DWORD PTR DS:[EAX-4]; For Form1 - 009512940044FE0F MOV EAX,DWORD PTR DS:[EAX+30] ; handle of Window0044FE12 PUSH EAX ; hWnd = 001700A2 ('Project1',class='TApplication')0044FE13 CALL JMP.&user32.SetWindowPos0044FE18 MOV BYTE PTR DS:[451FCC],BL0044FE1E POP EBX0044FE1F POP EBP0044FE20 RETN

When the form is showed SWP_HIDEWINDOW (97h) is replaced by SWP_SHOWWINDOW (value is 57h)

Few line down you will see:0044FE24 PUSH EBP0044FE25 MOV EBP,ESP0044FE27 PUSH ECX0044FE28 PUSH EBX0044FE29 PUSH ESI0044FE2A PUSH EDI0044FE2B MOV DWORD PTR SS:[EBP-4],EAX0044FE2E MOV EAX,DWORD PTR SS:[EBP-4]0044FE31 CMP DWORD PTR DS:[EAX+30],00044FE35 JE SHORT .0044FEA30044FE37 MOV EAX,DWORD PTR DS:[454B44]0044FE3C CALL .0044CA000044FE41 MOV ESI, EAX ; return number of Forms (03)0044FE43 DEC ESI0044FE44 TEST ESI,ESI0044FE46 JL SHORT .0044FE9A0044FE48 INC ESI0044FE49 XOR EDI,EDI ; prepare the counter0044FE4B MOV EDX,EDI ; begin of loop0044FE4D MOV EAX,DWORD PTR DS:[454B44]0044FE52 CALL .0044C9EC0044FE57 MOV EBX,EAX0044FE59 CMP BYTE PTR DS:[EBX+57],0 ; always 0 when is hidden while when is showed is second time 10044FE5D JE SHORT .0044FE960044FE5F CMP DWORD PTR DS:[EBX+198],0

Page 11: Cracking Delphi Programs

0044FE66 JE SHORT .0044FE8B0044FE68 MOV EAX,EBX0044FE6A CALL Project1.00434E900044FE6F TEST AL,AL0044FE71 JE SHORT Project1.0044FE8B0044FE73 MOV EAX,DWORD PTR DS:[EBX+198]0044FE79 PUSH EAX0044FE7A MOV EAX,EBX0044FE7C CALL Project1.00434BBC0044FE81 PUSH EAX ; hParent0044FE82 CALL user32.IsChild0044FE87 TEST EAX,EAX0044FE89 JNZ SHORT.0044FE960044FE8B PUSH EBP0044FE8C MOV AL,10044FE8E CALL .0044FDC8 ; is called when a Form is showed 0044FE93 POP ECX0044FE94 JMP SHORT .0044FEA30044FE96 INC EDI0044FE97 DEC ESI0044FE98 JNZ SHORT .0044FE4B0044FE9A PUSH EBP0044FE9B XOR EAX,EAX0044FE9D CALL .0044FDC8 ; is called when a Form is hidden0044FEA2 POP ECX0044FEA3 POP EDI0044FEA4 POP ESI0044FEA5 POP EBX0044FEA6 POP ECX0044FEA7 POP EBP0044FEA8 RETN

This is all.I hope you enjoy reading this.