2011-07-04 19:52:53 +00:00
unit Unit9;
{$MODE Delphi}
interface
uses
2020-08-21 16:15:09 +02:00
{$ifdef windows} windows, {$endif} LCLIntf, Messages, SysUtils, Classes, Graphics, Controls, Forms,
2021-03-26 00:10:44 +01:00
Dialogs, StdCtrls, Buttons, LResources, betterControls;
2011-07-04 19:52:53 +00:00
type
TForm9 = class( TForm)
Label1: TLabel;
Label2: TLabel;
Memo1: TMemo;
Button2: TButton;
Button1: TButton;
Button3: TButton;
SpeedButton1: TSpeedButton;
procedure FormCreate( Sender: TObject) ;
procedure Button1Click( Sender: TObject) ;
procedure Button3Click( Sender: TObject) ;
procedure FormClose( Sender: TObject; var Action: TCloseAction) ;
procedure FormCloseQuery( Sender: TObject; var CanClose: Boolean ) ;
procedure Button2Click( Sender: TObject) ;
procedure SpeedButton1Click( Sender: TObject) ;
private
{ Private declarations }
procedure relocate;
public
{ Public declarations }
end ;
type TLevel4 = record
a: integer ;
b: integer ;
c: integer ;
d: integer ;
e: integer ;
f: integer ;
health: integer ;
end ;
type PLevel4= ^ TLevel4;
type TLevel3 = record
p: PLevel4;
a: integer ;
b: integer ;
c: integer ;
d: integer ;
e: integer ;
f: integer ;
end ;
type PLevel3= ^ TLevel3;
type TLevel2 = record
a: integer ;
b: integer ;
c: integer ;
d: integer ;
e: integer ;
p: PLevel3;
f: integer ;
end ;
type PLevel2= ^ TLevel2;
type TLevel1 = record
a: integer ;
b: integer ;
c: integer ;
p: PLevel2;
d: integer ;
e: integer ;
f: integer ;
end ;
type PLevel1= ^ TLevel1;
var
Form9: TForm9;
basepointer: plevel1;
implementation
2021-11-22 21:15:37 +01:00
uses Unit4, Unit10, frmHelpUnit, cetranslator;
2011-07-04 19:52:53 +00:00
2012-01-04 10:31:22 +00:00
resourcestring
rsStep8MultilevelPointersPW = 'Step 8: Multilevel pointers: (PW=%s)' ;
rsUnrandomizerDetected = 'Unrandomizer detected' ;
rsYouVeGotSecondsLeftToChangeTheValueTo5000 = 'You' 've got %s seconds left to change the value to 5000' ;
rsTryAgain9 = 'Aw, you' 've almost reached the end. But don' 't worry, multilevel pointers can be a real pain when dealing with. If you get more experienced '
+ 'someday you can try it again. Are you sure you want to quit?' ;
2015-12-24 19:26:48 +01:00
rsLOSER = 'BOO' ;
2012-01-04 10:31:22 +00:00
rsTutorialStep8=
'This step will explain how to use multi-level pointers.' + #13 #10 +
'In step 6 you had a simple level-1 pointer, with the first address found already being the real base address.' + #13 #10 +
'This step however is a level-4 pointer. It has a pointer to a pointer to a pointer to a pointer to a pointer to the health.' + #13 #10 +
'' + #13 #10 +
2014-06-02 02:27:46 +00:00
'You basicly do the same as in step 6. Find out what accesses the value, look at the instruction and what probably is ' +
'the base pointer value, and what is the offset, and already fill that in or write it down. But in this case the address ' +
'you' 'll find will also be a pointer. You just have to find out the pointer to that pointer exactly the same way as you did ' +
'with the value. Find out what accesses that address you found, look at the assembler instruction, note the probable ' +
2012-01-04 10:31:22 +00:00
'instruction and offset, and use that.' + #13 #10 +
2021-09-05 13:51:56 +02:00
'And continue till you can' 't get any further (usually when the base address is a static address, shown up as green.)' + #13 #10 +
2012-01-04 10:31:22 +00:00
'' + #13 #10 +
'Click Change Value to let the tutorial access the health.' + #13 #10 +
2014-06-02 02:27:46 +00:00
'If you think you' 've found the pointer path click Change Register. The pointers and value will then change and you' 'll ' +
2021-09-05 13:51:56 +02:00
'have 3 seconds to freeze the address to 5000.' + #13 #10 +
2012-01-04 10:31:22 +00:00
'' + #13 #10 +
2021-09-05 13:51:56 +02:00
'Extra: This problem can also be solved using an auto assembler script, or using the pointer scanner.' + #13 #10 +
'Extra2: In some situations it is recommended to change CE' 's Codefinder settings to Access violations when ' + #13 #10 +
'encountering instructions like mov eax,[eax] since debug registers show it AFTER it was changed, making it hard to ' +
'find out the value of the pointer.' + #13 #10 +
2012-01-04 10:31:22 +00:00
'' + #13 #10 +
'' + #13 #10 +
'' + #13 #10 +
'' + #13 #10 +
'' + #13 #10 +
2014-06-02 02:27:46 +00:00
'Extra3: If you' 're still reading. You might notice that when looking at the assembler instructions that the pointer is ' +
'being read and filled out in the same codeblock (same routine, if you know assembler, look up till the start of the ' +
'routine). This doesn' 't always happen, but can be really useful in finding a ' +
2021-09-05 13:51:56 +02:00
'pointer when debugging is troublesome.' ;
2012-01-04 10:31:22 +00:00
2011-07-04 19:52:53 +00:00
procedure TForm9. relocate;
begin
//just adding some more chaos:
if ( basepointer< > nil ) then
begin
2020-08-21 16:15:09 +02:00
FillChar( basepointer. p. p. p^ , sizeof( TLevel4) , 0 ) ; //zeromemory(basepointer.p.p.p,sizeof(TLevel4));
FillChar( basepointer. p. p^ , sizeof( TLevel3) , 0 ) ; //zeromemory(basepointer.p.p,sizeof(TLevel3));
2011-07-04 19:52:53 +00:00
freemem( basepointer. p. p) ;
2020-08-21 16:15:09 +02:00
FillChar( basepointer. p^ , sizeof( TLevel2) , 0 ) ; //zeromemory(basepointer.p,sizeof(TLevel2));
2011-07-04 19:52:53 +00:00
freemem( basepointer. p) ;
2020-08-21 16:15:09 +02:00
FillChar( basepointer^ , sizeof( TLevel1) , 0 ) ; //zeromemory(basepointer,sizeof(TLevel1));
2011-07-04 19:52:53 +00:00
//delete a chunk inbetween if emptying wasn't enough already
end ;
getmem( basepointer, sizeof( TLevel1) + random( 1 2 8 ) ) ;
basepointer. a: = random( 9 9 9 9 9 ) ;
basepointer. b: = random( 9 9 9 9 9 ) ;
basepointer. c: = random( 9 9 9 9 9 ) ;
basepointer. d: = random( 9 9 9 9 9 ) ;
basepointer. e: = random( 9 9 9 9 9 ) ;
basepointer. f: = random( 9 9 9 9 9 ) ;
getmem( basepointer. p, sizeof( TLevel2) + random( 1 2 8 ) ) ;
basepointer. p. a: = random( 9 9 9 9 9 ) ;
basepointer. p. b: = random( 9 9 9 9 9 ) ;
basepointer. p. c: = random( 9 9 9 9 9 ) ;
basepointer. p. d: = random( 9 9 9 9 9 ) ;
basepointer. p. e: = random( 9 9 9 9 9 ) ;
basepointer. p. f: = random( 9 9 9 9 9 ) ;
getmem( basepointer. p. p, sizeof( TLevel3) + random( 1 2 8 ) ) ;
basepointer. p. p. a: = random( 9 9 9 9 9 ) ;
basepointer. p. p. b: = random( 9 9 9 9 9 ) ;
basepointer. p. p. c: = random( 9 9 9 9 9 ) ;
basepointer. p. p. d: = random( 9 9 9 9 9 ) ;
basepointer. p. p. e: = random( 9 9 9 9 9 ) ;
basepointer. p. p. f: = random( 9 9 9 9 9 ) ;
getmem( basepointer. p. p. p, sizeof( TLevel4) + random( 1 2 8 ) ) ;
basepointer. p. p. p. a: = random( 9 9 9 9 9 ) ;
basepointer. p. p. p. b: = random( 9 9 9 9 9 ) ;
basepointer. p. p. p. c: = random( 9 9 9 9 9 ) ;
basepointer. p. p. p. d: = random( 9 9 9 9 9 ) ;
basepointer. p. p. p. e: = random( 9 9 9 9 9 ) ;
basepointer. p. p. p. f: = random( 9 9 9 9 9 ) ;
end ;
procedure TForm9. FormCreate( Sender: TObject) ;
begin
relocate;
basepointer. p. p. p. health: = random( 4 0 0 0 ) ;
label1. caption: = inttostr( basepointer. p. p. p. health) ;
2021-11-22 21:15:37 +01:00
caption: = altnamer( caption) ;
memo1. lines. text : = altnamer( rsTutorialStep8) ;
2012-01-04 10:31:22 +00:00
memo1. Lines. Insert( 0 , Format( rsStep8MultilevelPointersPW, [ inttostr( 5 2 5 ) + inttostr( 9 2 7 ) ] ) ) ;
2011-07-04 19:52:53 +00:00
memo1. SelStart: = 0 ;
2016-09-05 21:17:11 +02:00
font. size: = 1 2 ;
2019-07-19 11:27:16 +02:00
frmHelp. attach( self, '8' ) ;
2011-07-04 19:52:53 +00:00
end ;
procedure TForm9. Button1Click( Sender: TObject) ;
var h: ^ integer ;
i: integer ;
a: plevel1;
b: plevel2;
c: plevel3;
d: plevel4;
begin
a: = basepointer;
if ( a. a= a. b) and ( a. b= a. c) and ( a. c= a. d) and ( a. d= a. e) and ( a. e= a. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if a. p= nil then exit;
b: = a. p;
if ( b. a= b. b) and ( b. b= b. c) and ( b. c= b. d) and ( b. d= b. e) and ( b. e= b. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if b. p= nil then exit;
c: = b. p;
if ( c. a= c. b) and ( c. b= c. c) and ( c. c= c. d) and ( c. d= c. e) and ( c. e= c. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if c. p= nil then exit;
d: = c. p;
if ( d. a= d. b) and ( d. b= d. c) and ( d. c= d. d) and ( d. d= d. e) and ( d. e= d. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
d. health: = random( 4 0 0 0 ) ;
label1. caption: = inttostr( d. health) ;
end ;
procedure TForm9. Button3Click( Sender: TObject) ;
var j: integer ;
k: integer ;
i: integer ;
a: plevel1;
b: plevel2;
c: plevel3;
d: plevel4;
begin
relocate;
a: = basepointer;
if ( a. a= a. b) and ( a. b= a. c) and ( a. c= a. d) and ( a. d= a. e) and ( a. e= a. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if a. p= nil then exit;
b: = a. p;
if ( b. a= b. b) and ( b. b= b. c) and ( b. c= b. d) and ( b. d= b. e) and ( b. e= b. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if b. p= nil then exit;
c: = b. p;
if ( c. a= c. b) and ( c. b= c. c) and ( c. c= c. d) and ( c. d= c. e) and ( c. e= c. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
if c. p= nil then exit;
d: = c. p;
if ( d. a= d. b) and ( d. b= d. c) and ( d. c= d. d) and ( d. d= d. e) and ( d. e= d. f) then
begin
2012-01-04 10:31:22 +00:00
showmessage( rsUnrandomizerDetected) ;
2011-07-04 19:52:53 +00:00
exit;
end ;
d. health: = random( 4 0 0 0 ) ;
label1. caption: = inttostr( d. health) ;
label1. Repaint;
k: = 3 ;
label2. Caption: = IntToStR( k) ;
label2. Visible: = true ;
2014-06-02 02:27:46 +00:00
button1. Anchors: = [ akLeft] ;
label2. anchors: = [ akLeft] ;
button3. visible: = false ;
2011-07-04 19:52:53 +00:00
while k> 0 do
begin
2012-01-04 10:31:22 +00:00
label2. Caption: = Format( rsYouVeGotSecondsLeftToChangeTheValueTo5000, [ IntToStR( k) ] ) ;
2011-07-04 19:52:53 +00:00
label2. Repaint;
sleep( 1 0 0 0 ) ;
deC( k) ;
end ;
label2. visible: = false ;
2014-06-02 02:27:46 +00:00
button3. visible: = true ;
button1. Anchors: = [ akLeft, akBottom] ;
label2. anchors: = [ akLeft, akBottom] ;
2011-07-04 19:52:53 +00:00
//check if it is 5000
if d. health= 5 0 0 0 then button2. Enabled: = true ;
{$O+}
j: = 0 ;
{$O-}
//if j=1 then beep;
end ;
procedure TForm9. FormClose( Sender: TObject; var Action: TCloseAction) ;
begin
application. Terminate;
end ;
procedure TForm9. FormCloseQuery( Sender: TObject; var CanClose: Boolean ) ;
begin
2012-01-04 10:31:22 +00:00
canclose: = MessageDlg( rsTryAgain9, mtconfirmation, [ mbyes, mbno] , 0 ) = mryes;
2011-07-04 19:52:53 +00:00
end ;
2018-05-29 15:10:22 +02:00
2011-07-04 19:52:53 +00:00
procedure TForm9. Button2Click( Sender: TObject) ;
begin
2011-10-25 20:44:03 +00:00
2011-07-04 19:52:53 +00:00
hide;
2018-05-29 15:10:22 +02:00
2011-07-04 19:52:53 +00:00
form10: = tform10. create( self) ;
2014-06-02 02:27:46 +00:00
form10. left: = left;
form10. top: = top;
form10. width: = width;
form10. height: = height;
2011-07-04 19:52:53 +00:00
form10. show;
2011-10-25 20:44:03 +00:00
{ hide;
2011-07-04 19:52:53 +00:00
form4: = tform4. create( self) ;
2011-10-25 20:44:03 +00:00
form4. show; }
2011-07-04 19:52:53 +00:00
end ;
procedure TForm9. SpeedButton1Click( Sender: TObject) ;
begin
2012-01-04 10:31:22 +00:00
showmessage( rsLOSER) ;
2011-07-04 19:52:53 +00:00
button2. Click;
end ;
initialization
{$i Unit9.lrs}
{$i Unit9.lrs}
end .