Cracking Delphi Programs
Cracking Delphi Programs
By CodeRipper
Tools used: DeDe by DaFixer, Olly debugger, PE Explorer,
De Decompiler Lite
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 eax
00484A6F E830F1F7FF call 00403BA4 ; call System.LStrOfChar()
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
000531D0
000531E0
000531F0
07 42 75 74 74 6F 6E 31
61 62 65 6C 31 F8 02 00
6C 32 01 00 13 00 28 3E
6E 31 43 6C 69 63 6B 05
F4 02 00 00 01 00 06 4C
00 01 00 06 4C 61 62 65
45 00 0C 42 75 74 74 6F
54 47 6F 6F 64 02 00 60
.Button1......L
abel1......Labe
l2....(>E..Butto
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],10
00432492 JNZ SHORT CrackMe#.004324A6
00432494 CMP DWORD PTR DS:[EBX+6C],0
00432498 JE SHORT CrackMe#.004324A6
0043249A MOV EDX,EBX
0043249C 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#.004324BE
004324A6 CMP WORD PTR DS:[EBX+122],0
004324AE JE SHORT CrackMe#.004324BE
004324B0 MOV EDX,EBX
004324B2 MOV EAX,DWORD PTR DS:[EBX+124]
004324B8 CALL DWORD PTR DS:[EBX+120] ; this one calls the method 00454824
004324BE POP EBX ; we are here
004324BF RETN
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#.004427AC
0044279C MOV EDX,EBX
0044279E MOV EAX,DWORD PTR DS:[EBX+8C]
004427A4 CALL DWORD PTR DS:[EBX+88]
004427AA JMP SHORT CrackMe#.004427DC
004427AC TEST BYTE PTR DS:[EBX+1C],10
004427B0 JNZ SHORT CrackMe#.004427C4
004427B2 CMP DWORD PTR DS:[EBX+44],0
004427B6 JE SHORT CrackMe#.004427C4
004427B8 MOV EDX,EBX
004427BA 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#.004427DC
004427C4 CMP WORD PTR DS:[EBX+8A],0
004427CC JE SHORT CrackMe#.004427DC
004427CE MOV EDX,EBX
004427D0 MOV EAX,DWORD PTR DS:[EBX+8C]
004427D6 CALL DWORD PTR DS:[EBX+88] ; this one calls the method 00454814
004427DC POP ESI ; we are here
004427DD POP EBX
004427DE RETN
The address 004427D6 is called in the case of all buttons and all of menu items, just set a
breakpoint on it.
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!
00492531
00492534
00492537
0049253A
0049253F
00492541
00492542
00492547
0049254A
0049254D
0049254F
00492551
00492556
00492559
0049255E
0049255F
00492564
00492567
00492569
0049256F
00492574
00492579
0049257E
00492585
00492587
0049258A
00492594
00492596
00492599
004925A0
004925A2
004925A5
004925AA
004925AD
004925B4
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 jne
CALL DWORD PTR DS:[EDX+0EC] ; call the changed code
MOV BYTE PTR [00492585],074 ; we restore back to je
JMP 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 couldnt do.
Form1.Hide;
Form2.Show;
Form3.Show;
get translated into:
0045103C MOV EAX,DWORD PTR DS:[454B74]
00451041 CALL Project1.0044B808 ; Form1.Hide
00451046 MOV EAX,DWORD PTR DS:[453358]
0045104B MOV EAX,DWORD PTR DS:[EAX]
0045104D CALL HideForm.0044B810 ; Form2.Show
00451052 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,EDX
0044B80A CALL .00447BBC
0044B80F RETN
Under Form2.Show/ Form3.Show you will see:
0044B810 PUSH EBX
0044B811 MOV EBX,EAX
0044B813 MOV DL,1
0044B815 MOV EAX,EBX
0044B817 CALL HideForm.00447BBC
0044B81C MOV EAX,EBX
0044B81E CALL Project1.0042DF74
0044B823 POP EBX
0044B824 RETN
We set a breakpoint on SetWindowPos and you will fiind:
0044FDC8 PUSH EBP
0044FDC9 MOV EBP,ESP
0044FDCB PUSH EBX
0044FDCC MOV EBX,EAX
0044FDCE 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 = 00951294
0044FDD4 MOV EAX,DWORD PTR DS:[EAX+30h] ; hwnd pointed by DS:[009512C4]
hWnd = 'Project1',class='TApplication'
0044FDD7 PUSH EAX ; hWnd
0044FDD8 CALL JMP.&user32.IsWindowVisible
0044FDDD CMP EAX,1
0044FDE0 SBB EAX,EAX
0044FDE2 INC EAX
0044FDE3 CMP AL,BYTE PTR DS:[451FCC]
0044FDE9 JNZ SHORT .0044FE1E
0044FDEB CMP BL,BYTE PTR DS:[451FCC]
0044FDF1 JE SHORT .0044FE1E
0044FDF3 MOVZX EAX,BL
0044FE66
0044FE68
0044FE6A
0044FE6F
0044FE71
0044FE73
0044FE79
0044FE7A
0044FE7C
0044FE81
0044FE82
0044FE87
0044FE89
0044FE8B
0044FE8C
0044FE8E
0044FE93
0044FE94
0044FE96
0044FE97
0044FE98
0044FE9A
0044FE9B
0044FE9D
0044FEA2
0044FEA3
0044FEA4
0044FEA5
0044FEA6
0044FEA7
0044FEA8
JE SHORT .0044FE8B
MOV EAX,EBX
CALL Project1.00434E90
TEST AL,AL
JE SHORT Project1.0044FE8B
MOV EAX,DWORD PTR DS:[EBX+198]
PUSH EAX
MOV EAX,EBX
CALL Project1.00434BBC
PUSH EAX ; hParent
CALL user32.IsChild
TEST EAX,EAX
JNZ SHORT.0044FE96
PUSH EBP
MOV AL,1
CALL .0044FDC8 ; is called when a Form is showed
POP ECX
JMP SHORT .0044FEA3
INC EDI
DEC ESI
JNZ SHORT .0044FE4B
PUSH EBP
XOR EAX,EAX
CALL .0044FDC8 ; is called when a Form is hidden
POP ECX
POP EDI
POP ESI
POP EBX
POP ECX
POP EBP
RETN
This is all.
I hope you enjoy reading this.