root/Cheat Engine/MemoryBrowserFormUnit.pas @ 312

Revision 312, 116.1 kB (checked in by dark_byte, 7 months ago)
Line 
1unit MemoryBrowserFormUnit;
2
3interface
4
5uses
6  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,tlhelp32, frmMemoryAllocHandlerUnit,
7  math, StdCtrls, Spin, ExtCtrls,CEFuncProc,symbolhandler,Clipbrd, Menus,plugin,debugger,kerneldebugger, assemblerunit,disassembler,addressparser,
8  Buttons,imagehlp, Contnrs, disassemblerviewunit, peinfofunctions ,dissectcodethread
9  ,stacktrace2, NewKernelHandler, ComCtrls,FormsExtra, frmCScriptUnit , byteinterpreter, StrUtils;
10
11
12type
13  TEdit2= class( TEdit)
14  private
15  public
16    procedure wmMouseWheel (var Msg : TWMMouseWheel); message wm_MouseWheel;
17
18  end;
19
20  TDisplayType = (dtByte, dtWord, dtDword, dtDwordDec, dtSingle, dtDouble);
21
22  TMemoryBrowser = class(TForm)
23    memorypopup: TPopupMenu;
24    Goto1: TMenuItem;
25    debuggerpopup: TPopupMenu;
26    Timer2: TTimer;
27    Panel1: TPanel;
28    Panel4: TPanel;
29    Replacewithnops1: TMenuItem;
30    Gotoaddress1: TMenuItem;
31    Search1: TMenuItem;
32    Change1: TMenuItem;
33    Addthisaddresstothelist1: TMenuItem;
34    Addthisopcodetothecodelist1: TMenuItem;
35    N1: TMenuItem;
36    N2: TMenuItem;
37    Splitter1: TSplitter;
38    Panel5: TPanel;
39    RegisterView: TPanel;
40    MainMenu1: TMainMenu;
41    File1: TMenuItem;
42    Loadsymbolfile1: TMenuItem;
43    Debug1: TMenuItem;
44    Step1: TMenuItem;
45    StepOver1: TMenuItem;
46    Runtill1: TMenuItem;
47    Setbreakpoint1: TMenuItem;
48    View1: TMenuItem;
49    Stacktrace1: TMenuItem;
50    ScrollBox1: TScrollBox;
51    EAXLabel: TLabel;
52    EBXlabel: TLabel;
53    ECXlabel: TLabel;
54    EDXlabel: TLabel;
55    ESIlabel: TLabel;
56    EDIlabel: TLabel;
57    EBPlabel: TLabel;
58    ESPlabel: TLabel;
59    EIPlabel: TLabel;
60    CSLabel: TLabel;
61    DSLabel: TLabel;
62    SSlabel: TLabel;
63    ESlabel: TLabel;
64    FSlabel: TLabel;
65    GSlabel: TLabel;
66    cflabel: TLabel;
67    pflabel: TLabel;
68    aflabel: TLabel;
69    zflabel: TLabel;
70    sflabel: TLabel;
71    oflabel: TLabel;
72    Label14: TLabel;
73    Shape1: TShape;
74    Label15: TLabel;
75    Shape2: TShape;
76    Label16: TLabel;
77    Shape3: TShape;
78    Run1: TMenuItem;
79    Threadlist1: TMenuItem;
80    Assemble1: TMenuItem;
81    N3: TMenuItem;
82    Break1: TMenuItem;
83    Extra1: TMenuItem;
84    Reservememory1: TMenuItem;
85    Savedisassemledoutput1: TMenuItem;
86    Savememoryregion1: TMenuItem;
87    Loadmemolryregion1: TMenuItem;
88    N4: TMenuItem;
89    OpenMemory: TOpenDialog;
90    Debugstrings1: TMenuItem;
91    CreateThread1: TMenuItem;
92    MemoryRegions1: TMenuItem;
93    FillMemory1: TMenuItem;
94    Disectwindow1: TMenuItem;
95    SaveDialog1: TSaveDialog;
96    Heaps1: TMenuItem;
97    N5: TMenuItem;
98    N6: TMenuItem;
99    EnumeratedllsandSymbols1: TMenuItem;
100    InjectDLL1: TMenuItem;
101    OpenDllDialog: TOpenDialog;
102    AutoInject1: TMenuItem;
103    Dissectcode1: TMenuItem;
104    Createjumptocodecave1: TMenuItem;
105    N7: TMenuItem;
106    N8: TMenuItem;
107    Findstaticpointers1: TMenuItem;
108    Scanforcodecaves1: TMenuItem;
109    Changestateofregisteratthislocation1: TMenuItem;
110    ogglebreakpoint1: TMenuItem;
111    N9: TMenuItem;
112    Breakpointlist1: TMenuItem;
113    Makepagewritable1: TMenuItem;
114    Dissectdata1: TMenuItem;
115    N10: TMenuItem;
116    Showsymbols1: TMenuItem;
117    Dissectdata2: TMenuItem;
118    N11: TMenuItem;
119    N12: TMenuItem;
120    Showmoduleaddresses1: TMenuItem;
121    Symbolhandler1: TMenuItem;
122    Kerneltools1: TMenuItem;
123    Allocatenonpagedmemory1: TMenuItem;
124    Getaddress1: TMenuItem;
125    Search2: TMenuItem;
126    Assemblycode1: TMenuItem;
127    Findmemory1: TMenuItem;
128    Driverlist1: TMenuItem;
129    Plugins1: TMenuItem;
130    Sericedescriptortable1: TMenuItem;
131    N13: TMenuItem;
132    Cut1: TMenuItem;
133    Pastefromclipboard1: TMenuItem;
134    N14: TMenuItem;
135    Setsymbolsearchpath1: TMenuItem;
136    Kernelmodesymbols1: TMenuItem;
137    Breakandtraceinstructions1: TMenuItem;
138    GDTlist1: TMenuItem;
139    IDTlist1: TMenuItem;
140    ScriptEngine1: TMenuItem;
141    Newwindow1: TMenuItem;
142    Follow1: TMenuItem;
143    dflabel: TLabel;
144    Copytoclipboard1: TMenuItem;
145    copyBytes: TMenuItem;
146    copyOpcodes: TMenuItem;
147    CopyBytesAndOpcodes: TMenuItem;
148    DissectPEheaders1: TMenuItem;
149    Back1: TMenuItem;
150    Showvaluesofstaticaddresses1: TMenuItem;
151    Findoutwhataddressesthisinstructionaccesses1: TMenuItem;
152    ScriptConsole1: TMenuItem;
153    DisplayType1: TMenuItem;
154    N15: TMenuItem;
155    dispBytes: TMenuItem;
156    dispWords: TMenuItem;
157    dispDwords: TMenuItem;
158    dispFloat: TMenuItem;
159    dispDouble: TMenuItem;
160    dispInts: TMenuItem;
161    Jumplines1: TMenuItem;
162    Showjumplines1: TMenuItem;
163    Onlyshowjumplineswithinrange1: TMenuItem;
164    Watchmemoryallocations1: TMenuItem;
165    Continueanddetachdebugger1: TMenuItem;
166    N16: TMenuItem;
167    Panel3: TPanel;
168    Panel2: TPanel;
169    Protectlabel: TLabel;
170    MBCanvas: TPaintBox;
171    HexEdit: TEdit;
172    TextEdit: TEdit;
173    ScrollBar2: TScrollBar;
174    Splitter3: TSplitter;
175    pnlStacktrace: TPanel;
176    sbShowFloats: TSpeedButton;
177    pmStacktrace: TPopupMenu;
178    All1: TMenuItem;
179    Modulesonly1: TMenuItem;
180    Nonsystemmodulesonly1: TMenuItem;
181    lvStacktraceData: TListView;
182    N17: TMenuItem;
183    Maxstacktracesize1: TMenuItem;
184    Splitter2: TSplitter;
185    Referencedstrings1: TMenuItem;
186    N18: TMenuItem;
187    stacktrace2: TMenuItem;
188    Executetillreturn1: TMenuItem;
189    procedure Button4Click(Sender: TObject);
190    procedure Button2Click(Sender: TObject);
191    procedure Splitter1Moved(Sender: TObject);
192    procedure FormShow(Sender: TObject);
193    procedure FormCreate(Sender: TObject);
194    procedure Goto1Click(Sender: TObject);
195    procedure FormResize(Sender: TObject);
196    procedure MemoryLabelClick(Sender: TObject);
197    procedure MBCanvasPaint(Sender: TObject);
198    procedure Timer2Timer(Sender: TObject);
199    procedure MBCanvasMouseUp(Sender: TObject; Button: TMouseButton;
200      Shift: TShiftState; X, Y: Integer);
201    procedure MBCanvasMouseMove(Sender: TObject; Shift: TShiftState; X,
202      Y: Integer);
203    procedure MBCanvasDblClick(Sender: TObject);
204    procedure memorypopupPopup(Sender: TObject);
205    procedure Replacewithnops1Click(Sender: TObject);
206    procedure FControl2KeyDown(Sender: TObject; var Key: Word;
207      Shift: TShiftState);
208    procedure FControl2KeyPress(Sender: TObject; var Key: Char);
209    procedure FControl2Enter(Sender: TObject);
210    procedure FControl2Exit(Sender: TObject);
211    procedure FControl1Exit(Sender: TObject);
212
213    procedure FControl1KeyDown(Sender: TObject; var Key: Word;
214      Shift: TShiftState);
215    procedure FControl1KeyPress(Sender: TObject; var Key: Char);
216    procedure Gotoaddress1Click(Sender: TObject);
217    procedure Search1Click(Sender: TObject);
218    procedure Change1Click(Sender: TObject);
219    procedure Addthisaddresstothelist1Click(Sender: TObject);
220    procedure Addthisopcodetothecodelist1Click(Sender: TObject);
221    procedure Splitter1CanResize(Sender: TObject; var NewSize: Integer;
222      var Accept: Boolean);
223    procedure ScrollBar2Scroll(Sender: TObject; ScrollCode: TScrollCode;
224      var ScrollPos: Integer);
225    procedure FormClose(Sender: TObject; var Action: TCloseAction);
226    procedure Run1Click(Sender: TObject);
227    procedure Step1Click(Sender: TObject);
228    procedure StepOver1Click(Sender: TObject);
229    procedure Runtill1Click(Sender: TObject);
230    procedure Stacktrace1Click(Sender: TObject);
231    procedure Threadlist1Click(Sender: TObject);
232    procedure Assemble1Click(Sender: TObject);
233    procedure HexEditKeyPress(Sender: TObject; var Key: Char);
234    procedure HexEditExit(Sender: TObject);
235    procedure HexEditKeyDown(Sender: TObject; var Key: Word;
236      Shift: TShiftState);
237    procedure EAXLabelDblClick(Sender: TObject);
238    procedure Break1Click(Sender: TObject);
239    procedure Reservememory1Click(Sender: TObject);
240    procedure Savememoryregion1Click(Sender: TObject);
241    procedure Loadmemolryregion1Click(Sender: TObject);
242    procedure HexEditDblClick(Sender: TObject);
243    procedure Debugstrings1Click(Sender: TObject);
244    procedure TextEditExit(Sender: TObject);
245    procedure TextEditKeyDown(Sender: TObject; var Key: Word;
246      Shift: TShiftState);
247    procedure CreateThread1Click(Sender: TObject);
248    procedure MemoryRegions1Click(Sender: TObject);
249    procedure TextEditKeyPress(Sender: TObject; var Key: Char);
250    procedure FillMemory1Click(Sender: TObject);
251    procedure Disectwindow1Click(Sender: TObject);
252    procedure Savedisassemledoutput1Click(Sender: TObject);
253    procedure Heaps1Click(Sender: TObject);
254    procedure EnumeratedllsandSymbols1Click(Sender: TObject);
255    procedure InjectDLL1Click(Sender: TObject);
256    procedure AutoInject1Click(Sender: TObject);
257    procedure Dissectcode1Click(Sender: TObject);
258    procedure Createjumptocodecave1Click(Sender: TObject);
259    procedure Findstaticpointers1Click(Sender: TObject);
260    procedure Scanforcodecaves1Click(Sender: TObject);
261    procedure Changestateofregisteratthislocation1Click(Sender: TObject);
262    procedure ogglebreakpoint1Click(Sender: TObject);
263    procedure Breakpointlist1Click(Sender: TObject);
264    procedure Makepagewritable1Click(Sender: TObject);
265    procedure Dissectdata1Click(Sender: TObject);
266    procedure Showsymbols1Click(Sender: TObject);
267    procedure Dissectdata2Click(Sender: TObject);
268    procedure Showmoduleaddresses1Click(Sender: TObject);
269    procedure Symbolhandler1Click(Sender: TObject);
270    procedure Allocatenonpagedmemory1Click(Sender: TObject);
271    procedure Getaddress1Click(Sender: TObject);
272    procedure Findmemory1Click(Sender: TObject);
273    procedure Assemblycode1Click(Sender: TObject);
274    procedure Driverlist1Click(Sender: TObject);
275    procedure Sericedescriptortable1Click(Sender: TObject);
276    procedure MBCanvasMouseDown(Sender: TObject; Button: TMouseButton;
277      Shift: TShiftState; X, Y: Integer);
278    procedure Cut1Click(Sender: TObject);
279    procedure Pastefromclipboard1Click(Sender: TObject);
280    procedure Setsymbolsearchpath1Click(Sender: TObject);
281    procedure Kernelmodesymbols1Click(Sender: TObject);
282    procedure Breakandtraceinstructions1Click(Sender: TObject);
283    procedure debuggerpopupPopup(Sender: TObject);
284    procedure GDTlist1Click(Sender: TObject);
285    procedure IDTlist1Click(Sender: TObject);
286    procedure ScriptEngine1Click(Sender: TObject);
287    procedure FormDestroy(Sender: TObject);
288    procedure Newwindow1Click(Sender: TObject);
289    procedure Follow1Click(Sender: TObject);
290    procedure CopyBytesAndOpcodesClick(Sender: TObject);
291    procedure DissectPEheaders1Click(Sender: TObject);
292    procedure Back1Click(Sender: TObject);
293    procedure Showvaluesofstaticaddresses1Click(Sender: TObject);
294    procedure Findoutwhataddressesthisinstructionaccesses1Click(
295      Sender: TObject);
296    procedure sbShowFloatsClick(Sender: TObject);
297    procedure ScriptConsole1Click(Sender: TObject);
298    procedure DisplayTypeClick(Sender: TObject);
299    procedure Showjumplines1Click(Sender: TObject);
300    procedure Onlyshowjumplineswithinrange1Click(Sender: TObject);
301    procedure Watchmemoryallocations1Click(Sender: TObject);
302    procedure Continueanddetachdebugger1Click(Sender: TObject);
303    procedure Panel2Resize(Sender: TObject);
304    procedure Panel2MouseDown(Sender: TObject; Button: TMouseButton;
305      Shift: TShiftState; X, Y: Integer);
306    procedure ScrollBox1Resize(Sender: TObject);
307    procedure Maxstacktracesize1Click(Sender: TObject);
308    procedure All1Click(Sender: TObject);
309    procedure Modulesonly1Click(Sender: TObject);
310    procedure Nonsystemmodulesonly1Click(Sender: TObject);
311    procedure Referencedstrings1Click(Sender: TObject);
312    procedure stacktrace2Click(Sender: TObject);
313    procedure Executetillreturn1Click(Sender: TObject);
314    procedure lvStacktraceDataData(Sender: TObject; Item: TListItem);
315    procedure lvStacktraceDataDblClick(Sender: TObject);
316  private
317    { Private declarations }
318    posloadedfromreg: boolean;
319    displaytype: TDisplayType;
320
321
322    editing: boolean;
323    editing2: boolean;
324
325    srow,scolumn: integer;
326
327    bytelength: integer;
328    chrlength: integer;
329
330    MBImage: TBitmap;
331    memorylabelcount: integer;
332    addresslabelcount: integer;
333    addresslabel: array of TLabel;
334    memorylabel: array of TLabel; //hex
335    memoryLabelA: array of TLabel; //ascii
336    MemoryLabelVerticalLines: integer;  //number of rows
337    MemoryLabelHorizontalLines: Integer;  //the number of lines
338
339    addressestext: array of string[8];
340    memorytext: array of string[2];
341    memorystring: array of string;
342    lengthof8bytes: Integer;
343    textheight: integer;
344
345
346    lines: integer;
347    oldlines: integer;
348    Highlightcolor: Tcolor;
349
350    numberofaddresses: integer;
351
352
353    part: integer;
354
355    {$ifndef net}
356
357    {$endif}
358
359
360    lastmodulelistupdate: integer;
361
362    disassemblerHistory: TStringList;
363    memorybrowserHistory: TStringList;
364    assemblerHistory: TStringList;
365
366    backlist: TStack;
367
368    lastspecialwidth: integer;
369    FShowValues: boolean;
370    FShowDebugPanels: boolean;
371    FStacktraceSize: integer;
372
373    strace: Tstringlist;
374
375    procedure SetStacktraceSize(size: integer);
376    procedure setShowDebugPanels(state: boolean);
377    procedure UpdateRWAddress(disasm: string);
378    procedure WMGetMinMaxInfo(var Message: TMessage); message WM_GETMINMAXINFO;
379    function getShowValues: boolean;
380    procedure setShowValues(newstate: boolean);
381
382
383    procedure disassemblerviewDblClick(Sender: TObject);
384  public
385    { Public declarations }
386    FSymbolsLoaded: Boolean;
387    memoryaddress: dword;
388    thhandle: Thandle;
389
390    disassemblerview: TDisassemblerview;
391
392    lastdebugcontext: _Context;
393    //EAXv: dword;
394    //EBXv: dword;
395    //ECXv: dword;
396    //EDXv: dword;
397    //ESIv: dword;
398    //EDIv: dword;
399    //EBPv: dword;
400    //ESPv: dword;
401    //EIPv: dword;
402    FControl2:Tedit2;
403    rows8: integer;
404    disassembler: boolean;
405    selecting,selectionmade: boolean;
406    selected,selected2: dword;
407    cancelsearch: boolean;
408
409    ischild: boolean; //determines if it's the main memorybrowser or a child
410
411    procedure FindwhatThiscodeAccesses(address: dword);
412    procedure UpdateBPlist;
413    procedure UpdateRegisterview;
414    procedure RefreshMB;
415    procedure AssemblePopup(x: string);
416
417    procedure plugintype1click(sender:tobject);
418    procedure plugintype6click(sender:tobject);
419    procedure setcodeanddatabase;
420    property showvalues: boolean read getShowValues write setShowValues;
421    property showDebugPanels: boolean read fShowDebugPanels write setShowDebugPanels;
422    property stacktraceSize: integer read FStacktraceSize write SetStacktraceSize;
423    procedure reloadStacktrace;
424    function GetReturnaddress: dword;
425  end;
426
427var
428  MemoryBrowser: TMemoryBrowser;
429  mbchildcount: integer; //global so all other children can increase it as well
430
431 
432implementation
433
434uses Valuechange,
435  {$ifdef net}
436  unit2,
437  addformunit,
438  {$else}
439  Mainunit,
440  {$endif}
441
442  {$ifndef net}
443  AddAddress,
444  findwindowunit,
445  frmstacktraceunit,
446  frmBreakThreadUnit,
447  FormDebugStringsUnit,
448  frmDissectWindowUnit,
449  frmEnumerateDLLsUnit,
450  frmThreadlistunit,
451  formmemoryregionsunit,
452  frmHeapsUnit,
453  frmFindstaticsUnit,
454  frmModifyRegistersUnit,
455  frmBreakpointlistunit,
456  savedisassemblyfrm,
457  {$endif}
458  advancedoptionsunit,
459  frmautoinjectunit,
460  formsettingsunit,
461  frmSaveMemoryRegionUnit,
462  frmLoadMemoryunit,
463  inputboxtopunit,
464  formAddToCodeList,
465  frmFillMemoryUnit,
466  frmCodecaveScannerUnit,
467  FoundCodeUnit,
468  frmFunctionListUnit,
469
470
471
472
473  {$ifndef net}symbolconfigunit,frmTracerUnit,Structuresfrm,dissectcodeunit,pointerscannerfrm,driverlist,ServiceDescriptorTables,{$endif}
474  frmDisassemblyscanunit, frmGDTunit, frmIDTunit, peINFOunit,
475  formChangedAddresses, frmFloatingPointPanelUnit,
476  frmReferencedStringsUnit;
477
478
479
480{$R *.DFM}
481
482
483procedure TEdit2.wmMouseWheel (var Msg : TWMMouseWheel);
484begin
485  with (parent as TMemorybrowser) do
486  begin
487    if msg.WheelDelta>0 then
488      memoryaddress:=memoryaddress-(8*rows8*4)
489    else
490      memoryaddress:=memoryaddress+(8*rows8*4);
491
492    refreshMB;
493  end;
494end;
495
496//property functions:
497function TMemoryBrowser.getShowValues: boolean;
498begin
499  result:=FShowValues;
500end;
501
502procedure TMemoryBrowser.setShowValues(newstate: boolean);
503begin
504  Showvaluesofstaticaddresses1.checked:=newstate;
505  FShowValues:=newstate;
506  disassemblerview.setCommentsTab(FShowValues);
507end;
508
509procedure TMemoryBrowser.setShowDebugPanels(state: boolean);
510begin
511  FShowDebugPanels:=state;
512  registerview.Visible:=state;
513  pnlStacktrace.Visible:=state;
514  splitter2.Visible:=state;
515  splitter3.Visible:=state;
516end;
517
518procedure TMemoryBrowser.SetStacktraceSize(size: integer);
519begin
520  FStacktraceSize:=size;
521  reloadStacktrace;
522end;
523
524//^^^^
525
526
527procedure TMemoryBrowser.WMGetMinMaxInfo(var Message: TMessage);
528var MMInfo: ^MINMAXINFO;
529begin
530  if panel1.visible then
531  begin
532    MMInfo:=ptr(message.LParam);
533    MMInfo.ptMinTrackSize:=point(340,panel1.Height+100);
534  end
535  else
536  begin
537    MMInfo:=ptr(message.LParam);
538    MMInfo.ptMinTrackSize:=point(340,100);
539  end;
540end;
541
542procedure TMemoryBrowser.UpdateBPlist;
543begin
544  {$ifndef net}
545  if frmBreakpointlist<>nil then
546    frmBreakpointlist.updatebplist;
547  {$endif}
548end;
549
550
551procedure TMemoryBrowser.UpdateRegisterview;
552begin
553//removed till 3.3
554end;
555
556
557
558procedure TMemoryBrowser.UpdateRWAddress(disasm: string);
559var seperator: integer;
560    fb: integer;
561    nb: integer;
562    address: string;
563    offset:dword;
564begin
565  //temporaryily obsolete
566 
567{  seperator:=pos(',',disasm);
568  if seperator>0 then
569  begin
570    fb:=pos('[',disasm);
571    nb:=pos(']',disasm);
572
573    if nb>fb then
574    begin
575      //if fb<seperator then label1.Font.Color:=clRed //write
576      //                else label1.font.color:=clGreen; //read
577      address:=copy(disasm,fb+1,nb-fb-1);
578
579      try
580        offset:=getaddress(address);
581      except
582
583      end;
584      //label1.Caption:=IntToHex(offset,8);
585    end;
586  end; }
587end;
588
589procedure TMemoryBrowser.Button4Click(Sender: TObject);
590begin
591  {$ifndef net}
592  debuggerthread.howtocontinue:=1;
593  debuggerthread.stepping:=false;
594  memorybrowser.Caption:='Advanced - Debug:Stepping';
595  {$endif}
596end;
597
598procedure TMemoryBrowser.Button2Click(Sender: TObject);
599begin
600  {$ifndef net}
601  debuggerthread.howtocontinue:=0;
602  debuggerthread.stepping:=false;
603  memorybrowser.Caption:='Advanced - Debug:Running';
604  {$endif}
605end;
606
607procedure TMemoryBrowser.Splitter1Moved(Sender: TObject);
608begin
609  disassemblerview.Update;
610end;
611
612procedure TMemoryBrowser.FormShow(Sender: TObject);
613var x: array of integer;
614
615begin
616  disassemblerview.Update;;
617  mbimage.Width:=0;  //clear the image
618  mbimage.Width:=clientwidth;
619
620  RefreshMB;
621
622  {$ifdef net}
623  registerview.Visible:=false;
624  stacktrace1.Visible:=false;
625  breakpointlist1.Visible:=false;
626  threadlist1.Visible:=false;
627  debugstrings1.Visible:=false;
628  n5.Visible:=false;
629  memoryregions1.Visible:=false;
630  heaps1.Visible:=false;
631  n6.Visible:=false;
632  enumeratedllsandsymbols1.Visible:=false;
633  n10.visible:=false;
634  showsymbols1.Visible:=false;
635  showmoduleaddresses1.Visible:=false;
636  symbolhandler1.Visible:=false;
637  debug1.Visible:=false;
638  view1.Visible:=false;
639
640  scanforcodecaves1.Visible:=false;
641  reservememory1.Visible:=false;
642  fillmemory1.Visible:=false;
643  createthread1.Visible:=false;
644  n8.visible:=false;
645  injectdll1.visible:=false;
646
647  search1.Visible:=false;
648  Changestateofregisteratthislocation1.Visible:=false;
649  ogglebreakpoint1.Visible:=false;
650  n9.Visible:=false;
651
652  dissectcode1.Visible:=false;
653  dissectdata2.visible:=false;
654  disectwindow1.visible:=false;
655
656  n12.visible:=false;
657  dissectdata1.Visible:=false;
658  findstaticpointers1.Visible:=false;
659  n11.Visible:=true;
660  injectdll1.Visible:=false;
661  autoinject1.Visible:=true;
662  {$endif}
663
664
665
666  Sericedescriptortable1.visible:=not Is64bitOS;
667  GDTlist1.Visible:=not is64bitos;
668  IDTlist1.Visible:=not is64bitos;
669
670
671end;
672
673procedure TMemoryBrowser.disassemblerviewDblClick(Sender: TObject);
674begin
675  assemble1.Click;
676end;
677
678procedure TMemoryBrowser.FormCreate(Sender: TObject);
679var x: array of integer;
680begin
681  displaytype:=dtByte;
682  scriptconsole1.ShortCut:=TextToShortCut('Ctrl+Shift+C');
683
684  strace:=tstringlist.create;
685
686
687{
688not enough time to add header supports
689
690
691}
692 { disassemblerheader.Visible:=false;
693  discanvas.Top:=discanvas.top-disassemblerheader.Height;
694  discanvas.Height:=discanvas.Height+disassemblerheader.Height;
695  //ronresize isn't repainting correctly   }
696{^^^^}
697
698  disassembler:=true;
699
700  disassemblerview:=TDisassemblerview.Create(self);
701  disassemblerview.Align:=alClient;
702  disassemblerview.Parent:=panel5;
703  disassemblerview.PopupMenu:=debuggerpopup;
704  disassemblerview.OnKeyDown:=FControl1keydown;
705  disassemblerview.OnDblClick:=disassemblerviewDblClick;
706
707  disassemblerview.TopAddress:=$00400000;
708   
709
710  fcontrol2:=tedit2.create(self);
711  fcontrol2.Width:=0;
712  fcontrol2.Height:=0;
713  fcontrol2.parent:=self;
714  fcontrol2.OnEnter:=FControl2Enter;
715  fcontrol2.onexit:=FControl2Exit;
716  fcontrol2.onKeydown:=FControl2keydown;
717  fcontrol2.onkeypress:=FControl2keypress;
718  fcontrol2.PopupMenu:=mainform.emptypopup;
719  fcontrol2.SendToBack;
720
721
722  MBImage:=TBitmap.Create;
723  MBImage.Canvas.Brush.Color:=clBtnFace;
724  MBImage.Width:=mbcanvas.Width*3;
725  MBImage.Height:=MBCanvas.Height*3;
726  MBImage.Canvas.Font.Name:='Courier';
727
728  textheight:=MBImage.Canvas.TextHeight('||||');
729  bytelength:=MBImage.Canvas.TextWidth('   ');
730  chrlength:=MBImage.Canvas.TextWidth(' ');
731
732  hexedit.Height:=textheight;
733  hexedit.Width:=chrlength*2;
734  textedit.Height:=hexedit.Height;
735  textedit.Width:=chrlength;
736
737  memoryaddress:=$00400000;
738  memorylabelcount:=0;
739
740  Highlightcolor:=clHighlight;
741
742  disassemblerHistory:=TStringList.create;
743  memorybrowserHistory:=TStringList.create;
744  assemblerHistory:=TStringList.create;
745
746  backlist:=TStack.create;
747
748  showvalues:=true;
749  sbShowFloats.left:=scrollbox1.Clientwidth-sbShowFloats.width;
750
751  FStacktraceSize:=4096;
752 
753
754  setlength(x, 6);
755
756  if loadformposition(self,x) then
757  begin
758    disassemblerview.setheaderWidth(0,x[0]);
759    disassemblerview.setheaderWidth(1,x[1]);
760    disassemblerview.setheaderWidth(2,x[2]);
761    disassemblerview.setheaderWidth(3,x[3]);
762
763    panel1.height:=x[4];
764    registerview.width:=x[5];
765
766    setlength(x,0);
767    posloadedfromreg:=true;
768  end;
769
770end;
771
772procedure TMemoryBrowser.Goto1Click(Sender: TObject);
773var newaddress: string;
774    canceled: boolean;
775begin
776  panel4.setfocus;
777  newaddress:=inputboxtop('Goto Address','Fill in the address you want to go to',IntTohex(memoryaddress,8),true,canceled,memorybrowserHistory);
778
779  memoryaddress:=getaddress(newaddress);
780
781  fcontrol2.SetFocus;
782
783  RefreshMB;
784end;
785
786procedure TMemoryBrowser.FormResize(Sender: TObject);
787begin
788  mbimage.Width:=0;
789  mbimage.height:=0;
790  mbimage.Width:=mbcanvas.Width;
791  mbimage.Height:=mbcanvas.Height;
792  refreshmb;
793  disassemblerview.Update;;
794end;
795
796procedure TMemoryBrowser.MemoryLabelClick(Sender: TObject);
797var address: dword;
798begin
799  address:=memoryaddress+(sender as TLabel).Tag;
800  showmessage(inttohex(address,8));
801
802end;
803
804procedure TMemoryBrowser.MBCanvasPaint(Sender: TObject);
805var cr: Trect;
806begin
807  cr:=mbcanvas.Canvas.ClipRect;
808  mbcanvas.Canvas.CopyRect(cr,mbimage.Canvas,cr);
809end;
810
811
812procedure TMemoryBrowser.Timer2Timer(Sender: TObject);
813begin
814  if Visible then
815  begin
816    refreshMB;
817    disassemblerview.Update;
818
819    //refresh the modulelist
820    lastmodulelistupdate:=(lastmodulelistupdate+1) mod 10;
821    if lastmodulelistupdate=0 then
822      symhandler.loadmodulelist;
823  end;
824end;
825
826
827procedure TMemoryBrowser.RefreshMB;
828var i: integer;
829    j,k: integer;
830    currentaddress: string[8];
831    bts: string[20];
832
833    start: integer;
834    stop: integer;
835    needed: integer;
836    available: integer;
837    rowsof8: integer;
838    teststr: string;
839
840    p: pchar;
841    a: int64;
842
843    range1ok: boolean;
844    range1start: dword;
845    range1length: dword;
846
847    range2ok: boolean;
848    range2start: dword;
849    range2length: dword;
850
851
852    buffer: array of byte;
853    bt: byte;
854    bytesread: dword;
855
856
857    rct: Trect;
858
859    mbi : _MEMORY_BASIC_INFORMATION;
860
861    range1module: tmoduleinfo;
862    range2module: tmoduleinfo;
863    module1ok,module2ok: boolean;
864    s: string;
865    selstart,selstop: integer;
866  procedure getBTSString(unreadable: boolean);
867  {
868  Because this same code snippet is used in range1 AND range 2 it's betetr to make it a subfunction
869  }
870  var x: string;
871  begin
872    bts:='';
873    case displayType of
874      dtByte:
875      begin
876        if unreadable then
877          bts:='??'
878        else
879          bts:=IntToHex(buffer[j+(i*8*rowsof8)],2);
880      end;
881
882      dtWord:
883      begin
884        if j mod 2 = 0 then
885        begin
886          if unreadable then
887            bts:='????'
888          else
889            bts:=IntToHex(pword(@buffer[j+(i*8*rowsof8)])^,4);
890           
891          while length(bts)<5 do
892            bts:=bts+' ';
893        end;
894      end;
895
896      dtDWord:
897      begin
898        if j mod 4 = 0 then
899        begin
900          if unreadable then
901            bts:='????????'
902          else
903            bts:=IntToHex(pdword(@buffer[j+(i*8*rowsof8)])^,8);
904           
905          while length(bts)<10 do
906            bts:=bts+' ';
907        end;
908      end;
909
910      dtDwordDec:
911      begin
912        if j mod 4 = 0 then
913        begin
914          if unreadable then
915            bts:='?????'
916          else
917            bts:=IntToStr(pinteger(@buffer[j+(i*8*rowsof8)])^);
918
919          if length(bts)>9 then
920            bts:=copy(bts,1,6)+'...';
921           
922          while length(bts)<10 do
923            bts:=bts+' ';
924        end;
925      end;
926
927      dtSingle:
928      begin
929        if j mod 4 = 0 then
930        begin
931          if unreadable then
932            bts:='???'
933          else
934            bts:=format('%f',[psingle(@buffer[j+(i*8*rowsof8)])^]);
935           
936          if length(bts)>9 then
937            bts:=copy(bts,1,6)+'...';
938
939          while length(bts)<10 do
940            bts:=bts+' ';
941        end;
942      end;
943
944      dtDouble:
945      begin
946        if j mod 8 = 0 then
947        begin
948          if unreadable then
949            bts:='???'
950          else
951            bts:=format('%f',[pDouble(@buffer[j+(i*8*rowsof8)])^]);
952           
953          if length(bts)>18 then
954            bts:=copy(bts,1,16)+'...';
955
956          while length(bts)<19 do
957            bts:=bts+' ';
958        end;
959      end;
960    end;
961  end;
962begin
963  //find the address in the module list
964
965  if selected<=selected2 then
966  begin
967    selstart:=selected;
968    selstop:=selected2;
969  end
970  else
971  begin
972    selstart:=selected2;
973    selstop:=selected;
974  end;
975
976
977  k:=0;
978  MBCanvas.Canvas.Font:=MBImage.Canvas.Font;
979
980  if length(addressestext)<((mbcanvas.Height) div (TextHeight))+2 then //resync
981  begin
982    setlength(addressestext,0);
983    setlength(addressestext,((mbcanvas.Height) div (TextHeight))+2);
984    setlength(memorystring,0);
985    setlength(memorystring,((mbcanvas.Height) div (TextHeight))+2);
986  end;
987
988  start:=20+mbimage.Canvas.TextWidth('00400000');
989  rowsof8:=0;
990
991  needed:=0;
992
993  available:=mbcanvas.Width-(start+20*rowsof8)-mbimage.Canvas.TextWidth('??');
994
995  while available>(needed) do
996  begin
997    inc(rowsof8);
998    teststr:='';
999    for i:=1 to rowsof8 do teststr:=teststr+'????????';
1000    needed:=10+mbcanvas.Canvas.TextWidth(teststr);
1001
1002    available:=mbcanvas.Width-(start+20*((8*rowsof8)-1))-mbcanvas.Canvas.TextWidth('??');
1003  end;
1004
1005  dec(rowsof8);
1006
1007  if rowsof8=0 then rowsof8:=1;
1008 
1009  rows8:=rowsof8;
1010
1011  if length(memorytext)<8*rowsof8 then
1012  begin
1013    setlength(memorytext,0);
1014    setlength(memorytext,8*rowsof8+1);
1015  end;
1016
1017   //fill local array
1018  setlength(buffer,(((mbcanvas.Height) div (TextHeight))+1)*(8*rowsof8)+257);
1019
1020  range1start:=memoryaddress;
1021  range1length:=2048-(range1start mod 2048);
1022  if range1length>((((mbcanvas.Height) div (TextHeight))+1)*(8*rowsof8)) then range1length:=((((mbcanvas.Height) div (TextHeight))+1)*(8*rowsof8));
1023
1024 // range1length:=(range1start+(((mbcanvas.Height-5) div (TextHeight))+1)*(8*rowsof8));// mod 2048;
1025
1026  range2start:=range1start+range1length;
1027  range2length:=((((mbcanvas.Height) div (TextHeight))+1)*(8*rowsof8))-range1length;
1028
1029  //get the modules (if they have any)
1030  module1ok:=symhandler.getmodulebyaddress(range1start,range1module);
1031  module2ok:=symhandler.getmodulebyaddress(range2start,range2module);
1032
1033
1034  zeromemory(@buffer[0],length(buffer));
1035  range1ok:=readprocessmemory(processhandle,pointer(range1start),@buffer[0],range1length,bytesread);
1036  if range2length>0 then range2ok:=readprocessmemory(processhandle,pointer(range2start),@buffer[range1length],range2length,bytesread) else range2ok:=false;
1037
1038  for i:=0 to ((mbcanvas.Height) div (TextHeight))+1 do
1039  begin
1040    //addresses
1041    mbcanvas.Canvas.font.Color:=clwindowtext;
1042    mbimage.Canvas.font.Color:=clwindowtext;
1043
1044    currentaddress:=IntToHex(dword(memoryaddress+i*8*rowsof8),8);
1045    mbcanvas.Canvas.TextOut(10,i*TextHeight+2,currentaddress);
1046    mbimage.Canvas.TextOut(10,i*TextHeight+2,currentaddress);
1047
1048    if addressestext[i]<>currentaddress then
1049    begin
1050
1051      addressestext[i]:=currentaddress;
1052    end;
1053
1054    //bytes
1055
1056    teststr:='';
1057
1058    p:=pointer(memoryaddress+i*8*rowsof8);
1059    a:=memoryaddress+i*8*rowsof8;
1060
1061    j:=0;
1062    while j<(8*rowsof8) do
1063    begin
1064      if a<int64(int64(range1start)+int64(range1length)) then
1065      begin
1066        if range1ok then
1067        begin
1068          //readable
1069          if (selecting or selectionmade) and (selstart<>selstop) and ((((memoryaddress+i*8*rowsof8)+j)>=selstart) and (((memoryaddress+i*8*rowsof8)+j)<=selstop)) then
1070          begin
1071            mbcanvas.Canvas.font.Color:=clred;
1072            mbimage.Canvas.font.Color:=clred;
1073          end
1074          else
1075          begin
1076            if (module1ok) then
1077            begin
1078              mbcanvas.Canvas.font.Color:=clgreen;
1079              mbimage.Canvas.font.Color:=clgreen;
1080            end
1081            else
1082            begin
1083              mbcanvas.Canvas.font.Color:=clwindowtext;
1084              mbimage.Canvas.font.Color:=clwindowtext;
1085            end;
1086          end;
1087
1088          GetBTSstring(false);
1089
1090
1091          mbcanvas.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1092          mbimage.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1093
1094          if buffer[j+(i*8*rowsof8)]<$20 then
1095          begin
1096            mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,' ');
1097            mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,' ');
1098          end else
1099          begin
1100            mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,chr(buffer[j+(i*8*rowsof8)]));
1101            mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,chr(buffer[j+(i*8*rowsof8)]));
1102          end;
1103        end
1104        else
1105        begin
1106          //unreadable
1107          if (selecting or selectionmade) and (selstart<>selstop) and ((((memoryaddress+i*8*rowsof8)+j)>=selstart) and (((memoryaddress+i*8*rowsof8)+j)<=selstop)) then
1108          begin
1109            mbcanvas.Canvas.font.Color:=clred;
1110            mbimage.Canvas.font.Color:=clred;
1111          end
1112          else
1113          begin
1114            mbcanvas.Canvas.font.Color:=clwindowtext;
1115            mbimage.Canvas.font.Color:=clwindowtext;
1116          end;
1117
1118          GetBTSstring(true);
1119          mbcanvas.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1120          mbimage.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1121
1122          mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,'?');
1123          mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,'?');
1124
1125//          teststr:=teststr+'?';
1126        end;
1127      end
1128      else
1129      begin
1130        //range 2
1131        if range2ok then
1132        begin
1133          if (selecting or selectionmade) and (selstart<>selstop) and ((((memoryaddress+i*8*rowsof8)+j)>=selstart) and (((memoryaddress+i*8*rowsof8)+j)<=selstop)) then
1134          begin
1135            mbcanvas.Canvas.font.Color:=clred;
1136            mbimage.Canvas.font.Color:=clred;
1137          end
1138          else
1139          begin
1140            if (module2ok) then
1141            begin
1142              mbcanvas.Canvas.font.Color:=clgreen;
1143              mbimage.Canvas.font.Color:=clgreen;
1144            end
1145            else
1146            begin
1147              mbcanvas.Canvas.font.Color:=clwindowtext;
1148              mbimage.Canvas.font.Color:=clwindowtext;
1149            end;
1150          end;
1151
1152          //readable
1153          //bts:=IntToHex(buffer[j+i*8*rowsof8],2);
1154          getBTSString(false);
1155          mbcanvas.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1156          mbimage.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1157
1158          if buffer[j+(i*8*rowsof8)]<$20 then
1159          begin
1160            mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,' ');
1161            mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,' ');
1162          end else
1163          begin
1164            mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,chr(buffer[j+(i*8*rowsof8)]));
1165            mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,chr(buffer[j+(i*8*rowsof8)]));
1166          end;
1167        end
1168        else
1169        begin
1170          //unreadable
1171          if (selecting or selectionmade) and (selstart<>selstop) and ((((memoryaddress+i*8*rowsof8)+j)>=selstart) and (((memoryaddress+i*8*rowsof8)+j)<=selstop)) then
1172          begin
1173            mbcanvas.Canvas.font.Color:=clred;
1174            mbimage.Canvas.font.Color:=clred;
1175          end
1176          else
1177          begin
1178            mbcanvas.Canvas.font.Color:=clwindowtext;
1179            mbimage.Canvas.font.Color:=clwindowtext;
1180          end;
1181
1182          GetBTSstring(true);
1183          mbcanvas.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1184          mbimage.Canvas.TextOut(start+20*j,i*textHeight+2,bts);
1185
1186          mbcanvas.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,'?');
1187          mbimage.Canvas.TextOut(start+20+20*((8*rowsof8)-1)+j*chrlength,i*textHeight+2,'?');
1188        end;
1189      end;
1190      inc(a);
1191      inc(j);
1192    end;
1193
1194
1195
1196  end;
1197
1198
1199  {$ifdef net}
1200  //no virtualquery, so no protectlabel
1201  protectlabel.Caption:='';
1202  {$else}
1203  //set the protectionlabel
1204  zeromemory(@mbi,sizeof(mbi));
1205  Virtualqueryex(processhandle,pointer(memoryaddress),mbi,sizeof(mbi));
1206  teststr:='AllocationProtect=';
1207
1208  if (mbi.AllocationProtect and PAGE_NOACCESS)>0 then teststr:=teststr+'No Access ';
1209  if (mbi.AllocationProtect and PAGE_READONLY)>0 then teststr:=teststr+'Read Only ';
1210  if (mbi.AllocationProtect and PAGE_READWRITE)>0 then teststr:=teststr+'Read/Write ';
1211  if (mbi.AllocationProtect and PAGE_WRITECOPY)>0 then teststr:=teststr+'Write Copy ';
1212  if (mbi.AllocationProtect and PAGE_EXECUTE)>0 then teststr:=teststr+'Execute ';
1213  if (mbi.AllocationProtect and PAGE_EXECUTE_READ)>0 then teststr:=teststr+'Execute/Read only ';
1214  if (mbi.AllocationProtect and PAGE_EXECUTE_READWRITE)>0 then teststr:=teststr+'Execute/Read/Write ';
1215  if (mbi.AllocationProtect and PAGE_EXECUTE_WRITECOPY)>0 then teststr:=teststr+'Execute/Write Copy ';
1216  if (mbi.AllocationProtect and PAGE_GUARD)>0 then teststr:=teststr+'Guarded ';
1217  if (mbi.AllocationProtect and PAGE_NOCACHE)>0 then teststr:=teststr+'Not Cached';
1218
1219  if (formsettings<>nil) and formsettings.cbKernelOpenProcess.checked and assigned(GetPhysicalAddress) and GetPhysicalAddress(processhandle,pointer(memoryaddress),a) then
1220    s:=teststr+' AllocationBase='+IntToHex(dword(mbi.AllocationBase),8)+' RegionSize='+IntTohex(mbi.RegionSize,1)+' Physical Address='+IntToHex(a,8)
1221  else
1222    s:=teststr+' AllocationBase='+IntToHex(dword(mbi.AllocationBase),8)+' RegionSize='+IntTohex(mbi.RegionSize,1);
1223
1224
1225  if module1ok then
1226    s:=s+' Module='+range1module.modulename;
1227
1228  protectlabel.caption:=s;
1229
1230  protectlabel.repaint;
1231  {$endif}
1232end;
1233
1234procedure TMemoryBrowser.MBCanvasMouseUp(Sender: TObject;
1235  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
1236var a: integer;
1237    i,j: integer;
1238    acr: dword;
1239    bt:byte;
1240
1241    temp:string;
1242begin
1243  if button=mbright then exit;
1244   
1245  selecting:=false;
1246
1247  if selected2<>selected then selectionmade:=true;
1248 
1249
1250  fcontrol2.SetFocus;
1251  hexedit.Visible:=false;
1252  textedit.Visible:=false;
1253
1254
1255
1256//find out if the user clicked on a byte, and if so which one
1257  a:=20+mbimage.Canvas.TextWidth('00400000');
1258  part:=0; //address
1259
1260  if x>a then
1261  begin  //didnt click on the address
1262    part:=2; //textfield ad the left side
1263    if x<(a+20*8*rows8) then //byteclick
1264    begin
1265      part:=1; //a byte
1266      srow:=y div textheight;
1267      scolumn:=(x-a) div 20;
1268
1269      i:=(srow*8*rows8)+scolumn;
1270      //caption:=Inttohex(memoryaddress+i,8);
1271      selected2:=memoryaddress+i;
1272
1273      if selected<>selected2 then exit;
1274
1275      //if ssLeft in shift then
1276      with HexEdit do
1277      begin
1278        if visible then
1279        begin
1280          if length(hexedit.text)=2 then
1281          begin
1282            bt:=strtoint('$'+hexedit.text);
1283            writeprocessmemory(processhandle,pointer(selected2),@bt,1,acr);
1284          end;
1285        end;
1286
1287        top:=(srow+1)*(textheight)+5;
1288        left:=1+a+20*(scolumn);
1289
1290        acr:=0;
1291        readprocessmemory(processhandle,pointer(selected2),@bt,1,acr);
1292
1293        if acr=1 then
1294        begin
1295          text:=IntToHex(bt,2);
1296          visible:=true;
1297          SelectAll;
1298          SetFocus;
1299        end else visible:=false;
1300      end;
1301    end
1302    else
1303    begin
1304      //not on a byte click
1305      for i:=1 to 8*rows8 do
1306        temp:=temp+'D';
1307
1308      srow:=((y-7) div textheight);
1309
1310
1311      i:=(x-(1+a+20*8*rows8));
1312
1313      scolumn:=i div mbcanvas.Canvas.TextWidth('D');
1314
1315      if scolumn<8*rows8 then
1316      begin
1317        i:=scolumn*mbcanvas.Canvas.TextWidth('D');
1318        selected2:=scolumn+memoryaddress+(8*rows8)*srow;
1319
1320        if selected<>selected2 then exit;
1321       
1322
1323        //if ssLeft in shift then
1324        with textedit do
1325        begin
1326          if visible then
1327          begin
1328            if length(textedit.Text)>0 then
1329            begin
1330              bt:=byte(textedit.Text[1]);
1331              if (editing2) and (bt>32) then
1332                writeprocessmemory(processhandle,pointer(selected2),@bt,1,acr);
1333            end;
1334          end;
1335
1336          textedit.top:=(srow+1)*(textheight)+3;
1337          textedit.Left:=1+a+20*8*rows8+i;   //  (1+(20+mbimage.Canvas.TextWidth('00400000'))+20*8*rows8+(scolumn*mbcanvas.Canvas.TextWidth('D'))  )
1338
1339          acr:=0;
1340          readprocessmemory(processhandle,pointer(selected2),@bt,1,acr);
1341
1342          if acr=1 then
1343          begin
1344            if bt>32 then text:=chr(bt) else text:='';
1345            visible:=true;
1346            editing2:=false;
1347            SelectAll;
1348            SetFocus;
1349          end else visible:=false;
1350        end;
1351      end;
1352    end;
1353  end;
1354
1355end;
1356
1357procedure TMemoryBrowser.MBCanvasMouseMove(Sender: TObject;
1358  Shift: TShiftState; X, Y: Integer);
1359var a,part,srow,scolumns,i: integer;
1360    temp: string;
1361begin
1362  a:=20+mbimage.Canvas.TextWidth('00400000');
1363
1364  if x>a then
1365  begin
1366    if x<(a+20*8*rows8) then //bytepoint
1367    begin
1368      mbcanvas.Cursor:=crHandpoint;
1369
1370      if selecting then
1371      begin
1372        part:=0; //address
1373        if x>a then
1374        begin  //didnt klick on the address
1375          part:=2; //textfield at the left side
1376          if x<(a+20*8*rows8) then //byteclick
1377          begin
1378            part:=1; //a byte
1379            srow:=((y-7) div textheight);
1380            scolumn:=(x-a) div 20;
1381
1382            i:=(srow*8*rows8)+scolumn;
1383
1384            if selected2<>memoryaddress+i then
1385            begin
1386              selected2:=memoryaddress+i;
1387
1388              //and repaint the selected region
1389              refreshmb;
1390            end;
1391          end;
1392        end;
1393      end;
1394    end else
1395    begin
1396      mbcanvas.Cursor:=crDefault;
1397      if selecting then
1398      begin
1399        //textclick?
1400        for i:=1 to 8*rows8 do
1401          temp:=temp+'D';
1402
1403        srow:=((y-7) div textheight);
1404
1405
1406        i:=(x-(1+a+20*8*rows8));
1407
1408        scolumn:=i div mbcanvas.Canvas.TextWidth('D');
1409
1410        if scolumn<8*rows8 then
1411        begin
1412          i:=scolumn*mbcanvas.Canvas.TextWidth('D');
1413          i:=scolumn+memoryaddress+(8*rows8)*srow;
1414          if selected2<>i then
1415          begin
1416            selected2:=i;
1417
1418            refreshmb;
1419          end;
1420        end;
1421      end;
1422
1423
1424    end;
1425
1426  end else mbcanvas.Cursor:=crdefault;
1427end;
1428
1429procedure TMemoryBrowser.MBCanvasDblClick(Sender: TObject);
1430begin
1431  if mbcanvas.Cursor=crHandpoint then
1432  begin
1433    if part=1 then
1434    begin
1435     //edit
1436      with Tvaluechangeform.Create(application) do
1437      begin
1438        address:=selected;
1439        ShowModal;
1440        refreshmb;
1441      end;
1442    end;
1443  end;
1444end;
1445
1446procedure TMemoryBrowser.memorypopupPopup(Sender: TObject);
1447begin
1448  goto1.Visible:=true;
1449  change1.Visible:=(mbcanvas.Cursor=crHandpoint);
1450
1451//  if part=0 then ...
1452end;
1453
1454procedure TMemoryBrowser.Replacewithnops1Click(Sender: TObject);
1455var codelength: integer;
1456    written: dword;
1457    bla:string;
1458    i: integer;
1459    nops: array of byte;
1460    a: dword;
1461    original: dword;
1462
1463    mbi : _MEMORY_BASIC_INFORMATION;
1464  //set the protectionlabel
1465begin
1466  //search dselected in the addresslist
1467
1468
1469  a:=disassemblerview.SelectedAddress;
1470
1471  disassemble(a,bla);
1472  codelength:=a-disassemblerview.SelectedAddress;
1473
1474  if advancedoptions.AddToCodeList(disassemblerview.SelectedAddress,codelength,true) then
1475  begin
1476    setlength(nops,codelength);
1477    for i:=0 to codelength-1 do
1478      nops[i]:=$90;  //$90=nop
1479
1480    zeromemory(@mbi,sizeof(mbi));
1481    Virtualqueryex(processhandle,pointer(disassemblerview.SelectedAddress),mbi,sizeof(mbi));
1482
1483   // get old security and set new security   (not needed in win9x but nt doesnt even allow writeprocessmemory to do this
1484    original:=0;
1485
1486    RewriteCode(processhandle,disassemblerview.SelectedAddress,@nops[0],codelength);
1487    refreshMB;
1488    disassemblerview.Update;;
1489  end;
1490end;
1491
1492procedure TMemoryBrowser.FControl2KeyDown(Sender: TObject; var Key: Word;
1493  Shift: TShiftState);
1494var i: short;
1495begin
1496  case key of
1497    vk_up       : begin
1498                    dec(memoryaddress,8*rows8);
1499                    refreshmb;
1500                  end;
1501
1502    vk_down     : begin
1503                    inc(memoryaddress,8*rows8);
1504                    refreshmb;
1505                  end;
1506
1507    vk_left     : begin
1508                    dec(memoryaddress);
1509                    refreshmb;
1510                  end;
1511    vk_right    : begin
1512                    inc(memoryaddress);
1513                    refreshmb;
1514                  end;
1515    vk_prior    : begin
1516                    dec(memoryaddress,8*rows8*((mbcanvas.Height) div (TextHeight)-1));
1517                    refreshMB;
1518                  end;
1519
1520    vk_next     : begin
1521                    inc(memoryaddress,8*rows8*((mbcanvas.Height) div (TextHeight)-1));
1522                    refreshMB;
1523                  end;
1524
1525    vk_space:
1526    begin
1527      if shift = [ssCtrl] then
1528        disassemblerview.SelectedAddress:=memoryaddress;
1529    end;
1530
1531    {$ifndef net}
1532    ord('F')    : begin
1533                    i:=getkeystate(vk_control);
1534                    if i<=-127 then search1.OnClick(self);
1535                  end;
1536    {$endif}
1537
1538    ord('1')    : if [ssCtrl] = shift then dispBytes.Click;
1539    ord('2')    : if [ssCtrl] = shift then dispWords.Click;
1540    ord('3')    : if [ssCtrl] = shift then dispDwords.Click;
1541    ord('4')    : if [ssCtrl] = shift then dispints.Click;
1542    ord('5')    : if [ssCtrl] = shift then dispFloat.Click;
1543    ord('6')    : if [ssCtrl] = shift then dispDouble.Click;
1544
1545    ord('G')    : begin
1546                    if ssCtrl in shift then goto1.click;
1547                  end;
1548
1549    ord('C')    : begin
1550                    if getkeystate(vk_control)<=-127 then
1551                      Cut1.OnClick(self);
1552                  end;
1553
1554    ord('V')    : begin
1555                    if getkeystate(vk_control)<=-127 then
1556                      Pastefromclipboard1.OnClick(self);
1557                  end;
1558
1559
1560    {$ifndef net}
1561    vk_f3       : begin
1562                    if findwindow<>nil then //easy way to find out if there was a scan before
1563                    begin
1564                      findwindow.editStart.Text:=inttohex(memoryaddress+1,8);
1565                      findwindow.firstscan:=false;
1566                    end;
1567                    findwindow.showmodal;
1568                  end;
1569    {$endif}
1570  end;
1571
1572  key:=0;
1573end;
1574
1575procedure TMemoryBrowser.FControl2KeyPress(Sender: TObject; var Key: Char);
1576begin
1577  key:=chr(0);
1578end;
1579
1580procedure TMemoryBrowser.FControl2Enter(Sender: TObject);
1581begin
1582//  panel4.bevelinner:=bvLowered;
1583//  mbcanvas.Canvas.DrawFocusRect(rect(0,0,100,100));
1584
1585end;
1586
1587procedure TMemoryBrowser.FControl2Exit(Sender: TObject);
1588begin
1589  panel4.BevelInner:=bvNone;
1590//  RefreshMB;
1591end;
1592
1593procedure TMemoryBrowser.FControl1Exit(Sender: TObject);
1594begin
1595
1596end;
1597
1598//key control for the disassembler
1599procedure TMemoryBrowser.FControl1KeyDown(Sender: TObject; var Key: Word;
1600  Shift: TShiftState);
1601var rct: trect;
1602    ignore: string;
1603    i: integer;
1604
1605    a,b: dword;
1606begin
1607  //if shift is not pressed and it's a up,down,left or right, then disable multiline section
1608  case key of
1609    vk_delete:
1610      Replacewithnops1.Click;
1611
1612
1613    vk_return:
1614    begin
1615      //assembler input
1616      assemble1.Click;
1617    end;
1618
1619    vk_space:
1620    begin
1621      if shift=[] then
1622        follow1.Click
1623      else
1624      if shift = [ssShift] then
1625        back1.click
1626      else
1627      if shift = [ssCtrl] then
1628      begin
1629        memoryaddress:=disassemblerview.SelectedAddress;
1630        RefreshMB;
1631      end;
1632    end;
1633
1634    VK_BACK:
1635    begin
1636      back1.click; //backspace and shift+space
1637    end;
1638
1639    ORD('A')..ORD('Z') , ORD('0')..ORD('9'):
1640    begin
1641      if key=ORD('C') then
1642      begin
1643        if shift = [ssCtrl] then //ctrl C
1644        begin
1645          //open the copy window asking what exactly to copy
1646          with tfrmSavedisassembly.create(self) do
1647          begin
1648            a:=min(disassemblerview.SelectedAddress, disassemblerview.SelectedAddress2);
1649            b:=max(disassemblerview.SelectedAddress, disassemblerview.SelectedAddress2);
1650
1651           
1652            disassemble(b); //b gets increased with size of selected instruction
1653            edit1.Text:=inttohex(a,8);
1654            edit2.Text:=inttohex(b-1,8);
1655            copymode:=true;
1656            showmodal;
1657            free;
1658            exit;
1659          end;
1660
1661        end;
1662      end;
1663
1664      if key=ORD('G') then
1665      begin
1666        if ssCtrl in shift then
1667        begin
1668          gotoaddress1.Click;
1669          disassemblerview.Update;
1670          exit;
1671        end;
1672      end;
1673
1674      if (ssalt in shift) or (ssctrl in shift) then exit;
1675
1676      assemblepopup(lowercase(chr(key)));
1677    end;
1678  end;
1679
1680  disassemblerview.Update;
1681
1682  key:=0;
1683end;
1684
1685procedure TMemoryBrowser.FControl1KeyPress(Sender: TObject; var Key: Char);
1686begin
1687  key:=chr(0);
1688end;
1689
1690procedure TMemoryBrowser.Gotoaddress1Click(Sender: TObject);
1691var newaddress: string;
1692    symbol :PImagehlpSymbol;
1693    oldoptions: dword;
1694    canceled: boolean;
1695begin
1696  newaddress:=InputBoxTop('Goto Address','Fill in the address you want to go to',IntTohex(disassemblerview.SelectedAddress,8),true,canceled,memorybrowserHistory);
1697
1698  try
1699    disassemblerview.SelectedAddress:=symhandler.getaddressfromname(newaddress);
1700  except
1701    disassemblerview.SelectedAddress:=getaddress(newaddress);
1702  end;
1703end;
1704
1705procedure TMemoryBrowser.Search1Click(Sender: TObject);
1706begin
1707  {$ifndef net}
1708  if findwindow=nil then findwindow:=TFindwindow.create(application);
1709  findwindow.firstscan:=true;
1710  findwindow.ShowModal;
1711  {$endif}
1712end;
1713
1714procedure TMemoryBrowser.Change1Click(Sender: TObject);
1715begin
1716  hexedit.Visible:=false;
1717  MBCanvasDblClick(MBCanvas);
1718end;
1719
1720procedure TMemoryBrowser.Addthisaddresstothelist1Click(Sender: TObject);
1721var i: integer;
1722    ad: dword;
1723begin
1724//this will add the selected recdord to the list
1725  if mbcanvas.Cursor=crHandpoint then
1726  begin
1727    //selected
1728    ad:=selected;
1729    if addform=nil then addform:=Taddform.create(self);
1730    addform.NewAddress.text:=inttohex(ad,8);
1731    addform.showmodal;
1732    //no free because it can be usefull the next time regarding the bits field
1733  end;
1734end;
1735
1736procedure TMemoryBrowser.Addthisopcodetothecodelist1Click(Sender: TObject);
1737var {start,stop: string;
1738    a,b: dword;
1739    i: integer;}
1740    desc: string;
1741begin
1742  frmAddToCodeList:=TfrmAddToCodeList.create(self);
1743  frmAddToCodeList.addtocodelist:=true;
1744  frmAddToCodeList.fromaddress:=disassemblerview.SelectedAddress;
1745  frmAddToCodeList.toaddress:=disassemblerview.SelectedAddress;
1746  disassemble(frmAddToCodeList.toaddress,desc);
1747  dec(frmAddToCodeList.toaddress);
1748  frmAddToCodeList.showmodal;
1749end;
1750
1751procedure TMemoryBrowser.Splitter1CanResize(Sender: TObject;
1752  var NewSize: Integer; var Accept: Boolean);
1753begin
1754  if newsize<80 then
1755  begin
1756    newsize:=80;
1757    accept:=false;
1758  end;
1759
1760  if newsize>memorybrowser.Height-80 then
1761  begin
1762    newsize:=memorybrowser.Height-80;
1763    accept:=false;
1764  end;
1765
1766end;
1767
1768procedure TMemoryBrowser.ScrollBar2Scroll(Sender: TObject;
1769  ScrollCode: TScrollCode; var ScrollPos: Integer);
1770var delta: integer;
1771begin
1772  fcontrol2.SetFocus;
1773  case scrollcode of
1774    scLineUp:   dec(memoryaddress,8*rows8);
1775    scLineDown: inc(memoryaddress,8*rows8);
1776    scPageDown: inc(memoryaddress,8*rows8*((mbcanvas.Height) div (TextHeight)-1));
1777    scPageUp:   dec(memoryaddress,8*rows8*((mbcanvas.Height) div (TextHeight)-1));
1778    sctrack:
1779    begin
1780      delta:=scrollpos-50;
1781      memoryaddress:=memoryaddress+(8*rows8)*delta;
1782     // if not formsettings.cbKernelReadWriteProcessMemory.checked then memoryaddress:=trunc(scrollpos/10000*$FFFFFFFF);
1783    end;
1784  end;
1785
1786  refreshmb;
1787  scrollpos:=50;
1788end;
1789
1790procedure TMemoryBrowser.FormClose(Sender: TObject;
1791  var Action: TCloseAction);
1792begin
1793  {$ifndef net}
1794  if (debuggerthread<>nil) and (debuggerthread.userisdebugging) then
1795  begin
1796    WaitForSingleObject(semaphore,infinite);
1797    debuggerthread.removebreakpoint;
1798    releasesemaphore(semaphore,1,nil);
1799
1800    debuggerthread.DRRegs.Dr0:=0;
1801    debuggerthread.DRRegs.Dr1:=0;
1802    debuggerthread.DRRegs.Dr2:=0;
1803    debuggerthread.DRRegs.Dr3:=0;
1804
1805    debuggerthread.continuehow:=wdco_run;
1806
1807    setlength(debuggerthread.userbreakpoints,0);
1808    setlength(debuggerthread.int3userbreakpoints,0);
1809    debuggerthread.int3CEBreakpoint.address:=0;
1810
1811    debuggerthread.continueprocess:=true;
1812    debuggerthread.userisdebugging:=false;
1813  end;
1814  {$endif}
1815
1816
1817  if ischild then
1818  begin
1819    //do stuff particulary for the children
1820    action:=cafree;
1821  end
1822  else
1823  begin
1824    //do stuff for the main debugger
1825    if frmFloatingPointPanel<>nil then
1826      frmFloatingPointPanel.Visible:=false;
1827
1828  end;
1829
1830end;
1831
1832procedure TMemoryBrowser.Run1Click(Sender: TObject);
1833begin
1834  {$ifndef net}
1835  if kdebugger.isactive then
1836  begin
1837    kdebugger.continue(co_run);
1838  end
1839  else
1840  if debuggerthread<>nil then
1841  begin
1842    debuggerthread.continuehow:=wdco_run;   //note: I could also have the debuggerthread suspend itself, and resume it here
1843    debuggerthread.continueprocess:=true;
1844  end;
1845  caption:='Memory Viewer - Running'; 
1846  {$endif}
1847end;
1848
1849procedure TMemoryBrowser.Step1Click(Sender: TObject);
1850begin
1851  {$ifndef net}
1852  if kdebugger.isactive then
1853  begin
1854    kdebugger.continue(co_stepinto);
1855  end
1856  else
1857  if debuggerthread<>nil then
1858  begin
1859    debuggerthread.continuehow:=wdco_stepinto; //single step
1860    debuggerthread.continueprocess:=true;
1861  end;
1862
1863  caption:='Memory Viewer - Running';
1864  {$endif}
1865end;
1866
1867procedure TMemoryBrowser.StepOver1Click(Sender: TObject);
1868var x: dword;
1869    i,j: integer;
1870    s,s1,s2,temp:string;
1871    int3: byte;
1872    original,a,written:dword;
1873begin
1874  int3:=$cc;
1875  //place a invisble for the user breakpoint on the following upcode
1876
1877  x:=lastdebugcontext.Eip;
1878  s:=disassemble(x,temp);
1879  i:=posex('-',s);
1880  i:=posex('-',s,i+1);
1881  s:=copy(s,i+2,length(s));
1882
1883  i:=pos(' ',s);
1884  s1:=copy(s,1,i-1);
1885  s2:=copy(s,i+1,length(s));
1886
1887  if not ((s1='call') or (s1='loop')) then //not a call or loop
1888  begin
1889    Step1.Click;
1890    exit;
1891  end;
1892
1893  if kdebugger.isactive then
1894  begin
1895    kdebugger.continue(co_stepover);
1896  end
1897  else
1898  if debuggerthread<>nil then
1899  begin
1900    debuggerthread.continuehow:=wdco_stepOver; //step over
1901
1902
1903
1904    if formsettings.rbDebugAsBreakpoint.checked then
1905    begin
1906      debuggerthread.DRRegs.Dr3:=x;
1907
1908      with debuggerthread do
1909      for i:=0 to length(threadlist)-1 do
1910      begin
1911        suspendthread(debuggerthread.threadlist[i][1]);
1912        setthreadcontext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs);
1913        resumethread(debuggerthread.threadlist[i][1]);
1914      end;
1915    end else
1916    begin
1917      // use the int3CEBreakpoint
1918      //see if there is already a Breakpoint with this address
1919      if debuggerthread.int3CEBreakpoint.address>0 then
1920        RewriteCode(processhandle,debuggerthread.int3CEBreakpoint.address,@debuggerthread.int3CEBreakpoint.originalbyte,1);
1921
1922      for i:=0 to length(debuggerthread.int3userbreakpoints)-1 do
1923        if debuggerthread.int3userbreakpoints[i].address=x then
1924        begin
1925          //dont need to set a breakpoint
1926          debuggerthread.continueprocess:=true;
1927          caption:='Memory Viewer - Running';
1928          exit;
1929        end;
1930
1931      debuggerthread.int3CEBreakpoint.address:=x;
1932      readprocessmemory(processhandle,pointer(x),@debuggerthread.int3CEBreakpoint.originalbyte,1,written);
1933
1934      Rewritecode(processhandle,x,@int3,1);
1935    end;
1936
1937    debuggerthread.continueprocess:=true;
1938
1939  end;
1940  caption:='Memory Viewer - Running';
1941end;
1942
1943procedure TMemoryBrowser.Runtill1Click(Sender: TObject);
1944var x: dword;
1945    i: integer;
1946    temp:string;
1947    int3: byte;
1948    original,a,written:dword;
1949begin
1950  {$ifndef net}
1951  int3:=$cc;
1952  //place a invisble for the user breakpoint on the following upcode
1953
1954  if kdebugger.isactive then
1955  begin
1956    kdebugger.continue(co_runtill, disassemblerview.SelectedAddress);
1957  end
1958  else
1959  if debuggerthread<>nil then
1960  begin
1961    debuggerthread.continuehow:=wdco_stepOver; //step over
1962    x:=disassemblerview.SelectedAddress;
1963    disassemble(x,temp);
1964
1965    if formsettings.rbDebugAsBreakpoint.checked then
1966    begin
1967      debuggerthread.DRRegs.Dr3:=x;
1968
1969      with debuggerthread do
1970      for i:=0 to length(threadlist)-1 do
1971      begin
1972        suspendthread(debuggerthread.threadlist[i][1]);
1973        setthreadcontext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs);
1974        resumethread(debuggerthread.threadlist[i][1]);
1975      end;
1976    end else
1977    begin
1978      if debuggerthread.int3CEBreakpoint.address>0 then
1979      begin
1980        //restore with original
1981        RewriteCode(processhandle,debuggerthread.int3CEBreakpoint.address,@debuggerthread.int3CEBreakpoint.originalbyte,1);
1982      end;
1983
1984      for i:=0 to length(debuggerthread.int3userbreakpoints)-1 do
1985        if debuggerthread.int3userbreakpoints[i].address=x then
1986        begin
1987          //dont need to set a breakpoint
1988          debuggerthread.continueprocess:=true;
1989          caption:='Memory Viewer - Running';
1990          exit;
1991        end;
1992
1993      debuggerthread.int3CEBreakpoint.address:=x;
1994      readprocessmemory(processhandle,pointer(x),@debuggerthread.int3CEBreakpoint.originalbyte,1,written);
1995
1996      Rewritecode(processhandle,x,@int3,1);
1997    end;
1998
1999    debuggerthread.continueprocess:=true;
2000
2001  end;
2002  caption:='Memory Viewer - Running';
2003
2004  {$endif}
2005end;
2006
2007procedure TMemoryBrowser.Stacktrace1Click(Sender: TObject);
2008begin
2009  {$ifndef net}
2010  frmstacktrace:=tfrmstacktrace.create(self);
2011  frmstacktrace.Show;
2012  {$endif}
2013end;
2014
2015procedure TMemoryBrowser.Threadlist1Click(Sender: TObject);
2016begin
2017  {$ifndef net}
2018  if frmThreadlist<>nil then exit;
2019
2020  if not startdebuggerifneeded then exit;
2021  frmThreadlist:=tfrmthreadlist.create(self);
2022  frmThreadlist.show;
2023  {$endif}
2024
2025end;
2026
2027procedure TMemoryBrowser.AssemblePopup(x:string);
2028var assemblercode,desc: string;
2029    bytes: tassemblerbytes;
2030    a,b,original,written:dword;
2031    originalsize:dword;
2032    replace: boolean;
2033    c: word;
2034
2035    res: word;
2036    i: integer;
2037    canceled: boolean;
2038begin
2039  //make sure it doesnt have a breakpoint
2040  {$ifndef net}
2041  if debuggerthread<>nil then
2042  begin
2043    for i:=0 to length(debuggerthread.int3userbreakpoints)-1 do
2044      if debuggerthread.int3userbreakpoints[i].address=disassemblerview.SelectedAddress then
2045      begin
2046        beep; //Best sound effect cheat engine has
2047        exit;
2048      end;
2049  end;
2050  {$endif}
2051
2052  originalsize:=disassemblerview.SelectedAddress;
2053  assemblercode:=disassemble(originalsize,desc);
2054  dec(originalsize,disassemblerview.SelectedAddress);
2055
2056  if x<>'' then
2057    assemblercode:=x
2058  else
2059  begin
2060    assemblercode:=copy(assemblercode,pos('-',assemblercode)+2,length(assemblercode));
2061    assemblercode:=copy(assemblercode,pos('-',assemblercode)+2,length(assemblercode));
2062  end;
2063
2064
2065
2066//  copy
2067
2068  assemblercode:=InputboxTop('Cheat Engine single-linge assembler','Type your assembler code here: (address='+inttohex(disassemblerview.SelectedAddress,8)+')',assemblercode,x='', canceled, assemblerHistory);
2069  if not canceled then
2070  begin
2071
2072    try
2073      if Assemble(assemblercode,disassemblerview.SelectedAddress,bytes) then
2074      begin
2075        if originalsize<>length(bytes) then
2076        begin
2077          if formsettings.replacewithnops.checked then
2078          begin
2079            if formsettings.askforreplacewithnops.checked then
2080            begin
2081              c:=messagedlg('The generated code is '+IntToStr(length(bytes))+' byte(s) long, but the selected opcode is '+IntToStr(originalsize)+' byte(s) long! Do you want to replace the incomplete opcode(s) with NOP''s?',mtConfirmation,mbYesNoCancel,0);
2082              replace:=c=mryes;
2083              if c=mrCancel then exit;
2084            end else replace:=true;
2085
2086            if replace then
2087            begin
2088              while originalsize>length(bytes) do
2089              begin
2090                setlength(bytes,length(bytes)+1);
2091                bytes[length(bytes)-1]:=$90;
2092              end;
2093
2094              a:=disassemblerview.SelectedAddress+length(bytes);
2095
2096              b:=disassemblerview.SelectedAddress;
2097              while b<a do disassemble(b,desc);
2098
2099              a:=b-disassemblerview.SelectedAddress;
2100              while length(bytes)<a do
2101              begin
2102                setlength(bytes,length(bytes)+1);
2103                bytes[length(bytes)-1]:=$90;
2104              end;
2105            end;
2106
2107
2108          end;
2109        end;
2110
2111        //note to self, check the size of the current opcode and give the option to replace the missing or too many bytes with nops
2112        //and put in a option to disable showing that message, and use a default action
2113
2114        // get old security and set new security   (not needed in win9x but nt doesnt even allow writeprocessmemory to do this
2115        original:=0;
2116
2117        RewriteCode(processhandle,disassemblerview.SelectedAddress,@bytes[0],length(bytes));
2118        refreshMB;
2119        disassemblerview.Update;
2120      end else raise exception.create('I don''t understand what you mean with '+assemblercode);
2121    except
2122      raise exception.create('I don''t understand what you mean with '+assemblercode);
2123    end;
2124
2125  end;
2126
2127end;
2128
2129procedure TMemoryBrowser.Assemble1Click(Sender: TObject);
2130begin
2131  AssemblePopup('');
2132end;
2133
2134procedure TMemoryBrowser.HexEditKeyPress(Sender: TObject; var Key: Char);
2135begin
2136  case key of
2137    chr(8)   : ;
2138    chr(16)  : ;
2139    'A'..'F' : ;
2140    'a'..'f' : key:=uppercase(key)[1];
2141    '0'..'9' : ;
2142    else key:=chr(0);
2143  end;
2144
2145  if editing then key:=#0;
2146  editing:=false;
2147end;
2148
2149procedure TMemoryBrowser.HexEditExit(Sender: TObject);
2150var bt: byte;
2151    aw: dword;
2152begin
2153//change
2154  if not hexedit.Visible then exit;
2155
2156  if length(hexedit.Text)<2 then
2157  begin
2158    hexedit.Visible:=false;
2159    beep;
2160    exit;
2161  end;
2162
2163  bt:=strtoint('$'+hexedit.text);
2164
2165  writeprocessmemory(processhandle,pointer(selected),@bt,1,aw);
2166  refreshmb;
2167
2168  hexedit.Visible:=false;
2169end;
2170
2171procedure TMemoryBrowser.HexEditKeyDown(Sender: TObject; var Key: Word;
2172  Shift: TShiftState);
2173var  a: integer;
2174     bt: byte;
2175     acr: dword;
2176procedure handleright;
2177begin
2178  if (length(hexedit.text)<2) and (key in [vk_right and vk_space] ) then
2179  begin
2180    if key=vk_right then exit;
2181    beep;
2182    key:=0;
2183    exit;
2184  end;
2185
2186  if key=vk_right then
2187    if (hexedit.SelStart<>2) and (hexedit.SelLength<>2) then exit;
2188
2189  bt:=strtoint('$'+hexedit.text);
2190  writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2191  refreshmb;
2192
2193  inc(scolumn);
2194  scolumn:=scolumn mod (8*rows8);
2195  if (scolumn)=0 then
2196  begin
2197    //move down
2198    inc(srow);
2199
2200    if (((srow+1)*(textheight)+3)+hexedit.Height)>panel4.Height then
2201    begin
2202      dec(srow);
2203      hexedit.top:=(srow+1)*(textheight)+3;
2204      inc(memoryaddress,8*rows8);
2205      refreshmb;
2206    end else hexedit.Top:=(srow+1)*(textheight)+3;
2207  end;
2208
2209  hexedit.left:=1+a+20*(scolumn);
2210  inc(selected);
2211
2212  acr:=0;
2213  readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2214
2215  if acr=1 then
2216  begin
2217    hexedit.text:=IntToHex(bt,2);
2218    hexedit.visible:=true;
2219    hexedit.SelectAll;
2220    hexedit.SetFocus;
2221  end else hexedit.visible:=false;
2222  key:=0;
2223  editing:=false;
2224end;
2225begin
2226  selecting:=false;
2227  selectionmade:=false;
2228  selected2:=selected;
2229 
2230  a:=20+mbimage.Canvas.TextWidth('00400000');
2231  case key of
2232    ord('C')    : begin
2233                    if (getkeystate(vk_control) shr 15) and 1 = 1 then
2234                    begin
2235                      editing:=false;
2236                      key:=0;
2237                      hexedit.Visible:=false;
2238                      fcontrol2.SetFocus;
2239                      Cut1.OnClick(self);
2240                    end
2241                    else
2242                    begin
2243                      if (length(hexedit.text)=1) and (hexedit.SelLength=0) then
2244                      begin
2245                        hexedit.text:=hexedit.Text+char(key);
2246                        handleright;
2247                        editing:=true;
2248                      end;
2249                    end;
2250                  end;
2251
2252    ord('V')    : begin
2253                    if (getkeystate(vk_control) shr 15) and 1= 1 then
2254                    begin
2255                      editing:=false;
2256                      key:=0;
2257                      hexedit.Visible:=false;
2258                      fcontrol2.SetFocus;
2259                      Pastefromclipboard1.OnClick(self);
2260                    end;
2261                  end;
2262                 
2263
2264    vk_add:   begin
2265                 acr:=0;
2266                 if readprocessmemory(processhandle,pointer(selected),@bt,1,acr) then
2267                 begin
2268                   inc(bt);
2269                   if writeprocessmemory(processhandle,pointeR(selected),@bt,1,acr) then
2270                   begin
2271                     hexedit.Text:=IntToHex(bt,2);
2272                     hexedit.SelectAll;
2273                   end;
2274                 end;
2275                 editing:=true;
2276                 key:=0;
2277                 disassemblerview.Update;
2278               end;
2279
2280    vk_subtract:begin
2281                 acr:=0;
2282                 if readprocessmemory(processhandle,pointer(selected),@bt,1,acr) then
2283                 begin
2284                   dec(bt);
2285                   if writeprocessmemory(processhandle,pointeR(selected),@bt,1,acr) then
2286                   begin
2287                     hexedit.Text:=IntToHex(bt,2);
2288                     hexedit.SelectAll;
2289                   end;
2290                 end;
2291                 editing:=true;
2292                 key:=0;
2293                 disassemblerview.Update;
2294               end;
2295
2296    vk_escape: begin
2297                 hexedit.Visible:=false;
2298                 fcontrol2.SetFocus;
2299               end;
2300
2301    vk_return: begin
2302                 if length(hexedit.Text)<2 then
2303                 begin
2304                   beep;
2305                   key:=0;
2306                   exit;
2307                 end;
2308
2309                 hexedit.Visible:=false;
2310                 bt:=strtoint('$'+hexedit.text);
2311                 writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2312                 refreshmb;
2313                 key:=0;
2314               end;
2315
2316    vk_up:     begin
2317                 if length(hexedit.text)<2 then
2318                 begin
2319                   beep;
2320                   exit;
2321                 end;
2322
2323                 dec(srow);
2324                 if srow<0 then
2325                 begin
2326                   srow:=0;
2327                   hexedit.Top:=(srow+1)*(textheight)+3;
2328
2329                   dec(memoryaddress,8*rows8);
2330                   refreshmb;
2331                 end else hexedit.Top:=(srow+1)*(textheight)+3;
2332
2333                 bt:=strtoint('$'+hexedit.text);
2334                 writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2335                 refreshmb;
2336
2337
2338                 dec(selected,8*rows8);
2339
2340                 acr:=0;
2341                 readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2342
2343                 if acr=1 then
2344                 begin
2345                   hexedit.text:=IntToHex(bt,2);
2346                   hexedit.visible:=true;
2347                   hexedit.SelectAll;
2348                   hexedit.SetFocus;
2349                 end else hexedit.visible:=false;
2350                 key:=0;
2351
2352               end;
2353
2354    vk_down:   begin
2355                 if length(hexedit.text)<2 then
2356                 begin
2357                   beep;
2358                   exit;
2359                 end;
2360
2361                 inc(srow);
2362                 if (((srow+1)*(textheight)+3)+hexedit.Height)>panel4.Height then
2363                 begin
2364                   dec(srow);
2365                   hexedit.top:=(srow+1)*(textheight)+3;
2366                   inc(memoryaddress,8*rows8);
2367                   refreshmb;
2368                 end else hexedit.Top:=(srow+1)*(textheight)+3;
2369
2370                 bt:=strtoint('$'+hexedit.text);
2371                 writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2372                 refreshmb;
2373
2374
2375                 inc(selected,8*rows8);
2376
2377                 acr:=0;
2378                 readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2379
2380                 if acr=1 then
2381                 begin
2382                   hexedit.text:=IntToHex(bt,2);
2383                   hexedit.visible:=true;
2384                   hexedit.SelectAll;
2385                   hexedit.SetFocus;
2386                 end else hexedit.visible:=false;
2387                 key:=0;
2388
2389               end;
2390
2391
2392    vk_left:   begin
2393                 if length(hexedit.Text)<2 then
2394                 begin
2395                   if (hexedit.selstart=0) then beep;
2396                   exit;
2397                 end;
2398
2399                 if hexedit.SelStart>0 then exit;
2400
2401                 bt:=strtoint('$'+hexedit.text);
2402                 writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2403                 refreshmb;
2404
2405                 dec(scolumn);
2406                 if scolumn=-1 then scolumn:=8*rows8-1;
2407                 if scolumn=8*rows8-1 then
2408                 begin
2409                   //move up
2410                   dec(srow);
2411                   if srow<0 then
2412                   begin
2413                     srow:=0;
2414                     hexedit.Top:=(srow+1)*(textheight)+3;
2415
2416                     dec(memoryaddress,8*rows8);
2417                     refreshmb;
2418                   end else hexedit.Top:=(srow+1)*(textheight)+3;
2419
2420                 end;
2421
2422                 hexedit.left:=1+a+20*(scolumn);
2423                 dec(selected);
2424
2425                 acr:=0;
2426                 readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2427
2428                 if acr=1 then
2429                 begin
2430                   hexedit.text:=IntToHex(bt,2);
2431                   hexedit.visible:=true;
2432                   hexedit.SelectAll;
2433                   hexedit.SetFocus;
2434                 end else hexedit.visible:=false;
2435                 key:=0;
2436               end;
2437
2438
2439    vk_space,vk_right:
2440    begin
2441      handleright;
2442    end;
2443
2444    else
2445    begin
2446      if key in [ord('0')..ord('9'),ord('A')..ord('F'),96..105] then
2447      begin
2448        if key in [96..105] then ///numpad fix
2449          key:=key-96+ord('0');
2450         
2451        if (length(hexedit.text)=1) and (hexedit.SelLength=0) then
2452        begin
2453          hexedit.text:=hexedit.Text+char(key);
2454          handleright;
2455          editing:=true;
2456
2457        end;
2458      end
2459      else
2460      key:=0;
2461    end;
2462  end;
2463end;
2464
2465procedure TMemoryBrowser.EAXLabelDblClick(Sender: TObject);
2466var x: dword;
2467    i: integer;
2468    regname,input: string;
2469    value: dword;
2470
2471begin
2472  //edit the selected register
2473  {$ifndef net}
2474  if (debuggerthread<>nil) and (not debuggerthread.running) then
2475  begin
2476    with debuggerthread do
2477    begin
2478      i:=tlabel(sender).Tag;
2479      case i of
2480      0: regname:='EAX';
2481      1: regname:='EBX';
2482      2: regname:='ECX';
2483      3: regname:='EDX';
2484      4: regname:='ESI';
2485      5: regname:='EDI';
2486      6: regname:='EBP';
2487      7: regname:='ESP';
2488      8: regname:='EIP';
2489      9: regname:='CS';
2490      10: regname:='SS';
2491      11: regname:='DS';
2492      12: regname:='ES';
2493      13: regname:='FS';
2494      14: regname:='GS';
2495      20: regname:='CF';
2496      21: regname:='PF';
2497      22: regname:='AF';
2498      23: regname:='ZF';
2499      24: regname:='SF';
2500      25: regname:='DF';
2501      end;
2502
2503      input:=copy(tlabel(sender).Caption,pos(' ',tlabel(sender).Caption)+1,8);
2504      if i<20 then
2505      begin
2506        if not inputquery('Change register','What is the new value of '+regname+'?',input) then exit;
2507      end
2508      else
2509      begin
2510        if not inputquery('Change register','What is the new value of '+regname+'? (0 or 1)',input) then exit;
2511        input:=trim(input);
2512        if (input<>'0') and (input<>'1') then
2513          raise exception.create(input+' is not a valid value');
2514
2515      end;
2516
2517      value:=StrToInt('$'+input);
2518
2519
2520      context.ContextFlags:=CONTEXT_FULL; //
2521      getthreadcontext(pausedthreadhandle,context);
2522      case tlabel(sendeR).Tag of
2523        0: context.Eax:=value;    //eax
2524        1: context.Ebx:=value;    //ebx
2525        2: context.Ecx:=value;    //ecx
2526        3: context.Edx:=value;    //edx
2527        4: context.Esi:=value;    //esi
2528        5: context.Edi:=value;    //edi
2529        6: context.Ebp:=value;    //ebp
2530        7: context.Esp:=value;    //esp
2531        8: context.Eip:=value;    //eip
2532        9: context.segcs:=value;    //cs
2533        10: context.segss:=value;    //ss
2534        11: context.segds:=value;    //ds
2535        12: context.seges:=value;    //es
2536        13: context.segfs:=value;    //fs
2537        14: context.seggs:=value;    //gs
2538
2539        20: setbit(0,context.eflags,value); //0=cf
2540        21: setbit(2,context.eflags,value); //2=pf
2541        22: setbit(4,context.eflags,value); //4=af
2542        23: setbit(6,context.eflags,value); //6=zf
2543        24: setbit(7,context.eflags,value); //7=sf
2544        25: setbit(10,context.eflags,value); //10=df
2545        26: setbit(11,context.eflags,value); //11=of
2546      end;
2547
2548      if setthreadcontext(pausedthreadhandle,context) then
2549      begin
2550        if tlabel(sender).Tag>=9 then
2551          tlabel(sender).Caption:=regname+' '+inttohex(value,4)
2552        else
2553          tlabel(sender).Caption:=regname+' '+inttohex(value,8)
2554      end;
2555    end;
2556
2557  end;
2558  {$endif}
2559end;
2560
2561procedure TMemoryBrowser.Break1Click(Sender: TObject);
2562var threadhandle: thandle;
2563begin
2564  {$ifndef net}
2565  if not startdebuggerifneeded then exit;
2566
2567  threadhandle:=debuggerthread.threadlist[0,1];
2568
2569  if length(debuggerthread.threadlist)>=1 then
2570  begin
2571    //multiple threads!!! Ask user which one
2572    frmbreakthread:=tfrmbreakthread.create(self);
2573    if frmbreakthread.showmodal=mrOK then  threadhandle:=frmbreakthread.threadhandle else
2574    begin
2575      frmbreakthread.free;
2576      frmbreakthread:=nil;
2577      exit;
2578    end;
2579
2580    frmbreakthread.free;
2581    frmbreakthread:=nil;
2582
2583  end;
2584
2585  if not breakthread(threadhandle) then raise exception.Create('Can''t set breakpoint');
2586
2587  {$endif}
2588end;
2589
2590procedure TMemoryBrowser.Reservememory1Click(Sender: TObject);
2591var count: string;
2592    memsize: integer;
2593    baseaddress: pointer;
2594    x: dword;
2595    s: string;
2596begin
2597{$ifndef net}
2598  count:='4096';
2599  if inputquery('Allocate memory','How much memory do you want to add to this process. ',count) then
2600  begin
2601    try
2602      memsize:=StrToInt(count);
2603    except
2604      raise exception.Create('How much is '+count+'?');
2605    end;
2606
2607    baseaddress:=nil;
2608    baseaddress:=VirtualAllocEx(processhandle,nil,memsize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
2609    if baseaddress<>nil then
2610    begin
2611
2612
2613      if (disassemblerview.SelectedAddress<>0) and (memsize>7) and (messagedlg('At least '+IntToStr(memsize)+' bytes have been allocated at '+IntToHex(dword(baseaddress),8)+#13#10+'Do you want replace the currently selected address with a jump to that address, and copy the overwritten instructions to there?',mtConfirmation,[mbyes,mbno],0)=mryes) then
2614        CreateCodecave(dword(baseaddress),disassemblerview.SelectedAddress,memsize)
2615      else
2616        messagedlg('At least '+IntToStr(memsize)+' bytes have been allocated at '+IntToHex(dword(baseaddress),8),mtinformation,[mbok],0);
2617
2618
2619      if messagedlg('Do you want to go there now?',mtConfirmation,[mbyes,mbno],0) = mryes then
2620        disassemblerview.SelectedAddress:=dword(baseaddress);
2621
2622
2623    end else raise exception.Create('Error allocating memory!');
2624
2625
2626  end;
2627  {$endif}
2628end;
2629
2630procedure TMemoryBrowser.Savememoryregion1Click(Sender: TObject);
2631begin
2632//will save a cheat engine memory region file .CEM
2633//header:
2634//'CHEATENGINE'
2635//4 bytes:Version
2636//4 bytes:beginaddress
2637//4 bytes:size
2638  TFrmSaveMemoryRegion.create(self).showmodal;
2639end;
2640
2641procedure TMemoryBrowser.Loadmemolryregion1Click(Sender: TObject);
2642begin
2643  if openmemory.Execute then
2644  begin
2645    tfrmloadmemory.Create(self).Showmodal(openmemory.filename);
2646  end;
2647end;
2648
2649procedure TMemoryBrowser.HexEditDblClick(Sender: TObject);
2650begin
2651  change1.Click;
2652end;
2653
2654procedure TMemoryBrowser.Debugstrings1Click(Sender: TObject);
2655begin
2656  {$ifndef net}
2657  startdebuggerifneeded;
2658
2659  formdebugstrings.show;
2660  {$endif}
2661end;
2662
2663procedure TMemoryBrowser.TextEditExit(Sender: TObject);
2664var bt: byte;
2665    aw: dword;
2666begin
2667//change
2668  if not textedit.Visible then exit;
2669
2670  if length(hexedit.Text)<2 then
2671  begin
2672    hexedit.Visible:=false;
2673    beep;
2674    exit;
2675  end;
2676
2677  if length(textedit.text)=1 then
2678  begin
2679    bt:=byte(textedit.text[1]);
2680    if bt>32 then
2681      writeprocessmemory(processhandle,pointer(selected),@bt,1,aw);
2682  end;
2683
2684  refreshmb;
2685
2686  textedit.Visible:=false;
2687end;
2688
2689procedure TMemoryBrowser.TextEditKeyDown(Sender: TObject; var Key: Word;
2690  Shift: TShiftState);
2691var bt: byte;
2692    acr: dword;
2693    a: integer;
2694procedure handleright;
2695begin
2696  if (length(textedit.text)=0) then
2697  begin
2698    if key=vk_right then exit;
2699    beep;
2700    key:=0;
2701    exit;
2702  end;
2703
2704  if editing2 then
2705  begin
2706    bt:=byte(textedit.text[1]);
2707    if bt>32 then
2708      writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2709    refreshmb;
2710  end;
2711
2712  inc(scolumn);
2713  scolumn:=scolumn mod (8*rows8);
2714  if (scolumn)=0 then
2715  begin
2716    //move down
2717    inc(srow);
2718
2719    if (((srow+1)*(textheight)+3)+textedit.Height)>panel4.Height then
2720    begin
2721      dec(srow);
2722      textedit.top:=(srow+1)*(textheight)+3;
2723      inc(memoryaddress,8*rows8);
2724      refreshmb;
2725    end else textedit.Top:=(srow+1)*(textheight)+3;
2726  end;
2727
2728  textedit.left:=(1+a+20*8*rows8+(scolumn*mbcanvas.Canvas.TextWidth('D')));
2729  inc(selected);
2730
2731  acr:=0;
2732  readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2733
2734  if acr=1 then
2735  begin
2736    if bt>32 then textedit.text:=chr(bt) else textedit.text:=' ';
2737    editing2:=false;
2738    textedit.visible:=true;
2739    textedit.SelectAll;
2740    textedit.SetFocus;
2741  end else hexedit.visible:=false;
2742  key:=0;
2743end;
2744begin
2745  a:=20+mbimage.Canvas.TextWidth('00400000');
2746
2747  case key of
2748    ord('C'):
2749    begin
2750      if getkeystate(vk_control)<=-127 then
2751      begin
2752        editing:=false;
2753        key:=0;
2754        hexedit.Visible:=false;
2755        fcontrol2.SetFocus;
2756
2757        Cut1.OnClick(self);
2758      end else editing2:=true;
2759    end;
2760
2761    ord('V'):
2762    begin
2763      if getkeystate(vk_control)<=-127 then
2764      begin
2765        editing:=false;
2766        key:=0;
2767        hexedit.Visible:=false;
2768        fcontrol2.SetFocus;
2769        Pastefromclipboard1.OnClick(self);
2770      end else editing2:=true;
2771    end;
2772
2773    vk_escape:
2774    begin
2775      textedit.Visible:=false;
2776      fcontrol2.SetFocus;
2777    end;
2778
2779    vk_return:
2780    begin
2781      if length(textedit.Text)<1 then
2782      begin
2783        beep;
2784        key:=0;
2785        exit;
2786      end;
2787
2788      textedit.Visible:=false;
2789      bt:=byte(textedit.text[1]);
2790      writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2791      refreshmb;
2792      key:=0;
2793    end;
2794
2795
2796    vk_up:
2797    begin
2798      if length(textedit.text)<1 then
2799      begin
2800        beep;
2801        exit;
2802      end;
2803
2804      dec(srow);
2805      if srow<0 then
2806      begin
2807        srow:=0;
2808        textedit.Top:=(srow+1)*(textheight)+3;
2809        dec(memoryaddress,8*rows8);
2810        refreshmb;
2811      end
2812      else textedit.Top:=(srow+1)*(textheight)+3;
2813
2814      if editing2 then
2815      begin
2816        bt:=byte(textedit.text[1]);
2817        if bt>32 then
2818          writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2819      end;
2820
2821      refreshmb;
2822
2823      dec(selected,8*rows8);
2824
2825      acr:=0;
2826      readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2827
2828      if acr=1 then
2829      begin
2830        if bt>32 then textedit.text:=chr(bt) else textedit.text:=' ';
2831        editing2:=false;
2832        textedit.visible:=true;
2833        textedit.SelectAll;
2834        textedit.SetFocus;
2835      end else textedit.visible:=false;
2836      key:=0;
2837    end;
2838
2839    vk_down:
2840    begin
2841      if length(textedit.text)=0 then
2842      begin
2843        beep;
2844        exit;
2845      end;
2846
2847      inc(srow);
2848      if (((srow+1)*(textheight)+3)+textedit.Height)>panel4.Height then
2849      begin
2850        dec(srow);
2851        textedit.top:=(srow+1)*(textheight)+3;
2852        inc(memoryaddress,8*rows8);
2853        refreshmb;
2854      end else textedit.Top:=(srow+1)*(textheight)+3;
2855
2856      if editing2 then
2857      begin
2858        bt:=byte(textedit.text[1]);
2859        if bt>32 then
2860          writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2861        refreshmb;
2862      end;
2863
2864      inc(selected,8*rows8);
2865
2866      acr:=0;
2867      readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2868
2869      if acr=1 then
2870      begin
2871        if bt>32 then textedit.text:=chr(bt) else textedit.Text:=' ';
2872        editing2:=false;
2873        textedit.visible:=true;
2874        textedit.SelectAll;
2875        textedit.SetFocus;
2876      end else textedit.visible:=false;
2877      key:=0;
2878
2879    end;
2880
2881
2882    vk_left:
2883    begin
2884      if length(textedit.Text)<1 then
2885      begin
2886        beep;
2887        exit;
2888      end;
2889
2890      bt:=byte(textedit.text[1]);
2891      if editing2 then
2892      if bt>32 then
2893        writeprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2894
2895      refreshmb;
2896
2897      dec(scolumn);
2898      if scolumn=-1 then scolumn:=8*rows8-1;
2899
2900      if scolumn=8*rows8-1 then
2901      begin
2902        //move up
2903        dec(srow);
2904        if srow<0 then
2905        begin
2906          srow:=0;
2907          textedit.Top:=(srow+1)*(textheight)+3;
2908
2909          dec(memoryaddress,8*rows8);
2910          refreshmb;
2911        end else textedit.Top:=(srow+1)*(textheight)+3;
2912      end;
2913
2914      textedit.left:=(1+a+20*8*rows8+(scolumn*mbcanvas.Canvas.TextWidth('D')));            //1+a+20*(scolumn);
2915      dec(selected);
2916
2917      acr:=0;
2918      readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
2919
2920      if acr=1 then
2921      begin
2922        if bt>32 then textedit.text:=chr(bt) else textedit.text:=' ';
2923        editing2:=false;
2924        textedit.visible:=true;
2925        textedit.SelectAll;
2926        textedit.SetFocus;
2927      end else textedit.visible:=false;
2928      key:=0;
2929    end;
2930
2931    vk_right:
2932    begin
2933      handleright;
2934    end;
2935
2936    else begin
2937           editing2:=true;
2938         end;
2939  end;
2940end;
2941
2942procedure TMemoryBrowser.CreateThread1Click(Sender: TObject);
2943var startaddress,parameter: dword;
2944    ThreadID: dword;
2945    start:string;
2946    param:string;
2947begin
2948  start:=IntToHex(disassemblerview.SelectedAddress,8);
2949  param:='0';
2950  if not InputQuery('Create remote thread','What will be the startaddress of this thread?',start) then exit;
2951  try
2952    startaddress:=StrToInt('$'+start);
2953  except
2954    raise exception.Create('Please enter a valid hexadecimal addres');
2955  end;
2956
2957  if not InputQuery('Create remote thread','You want to give an additional 32-bit parameter? (Will show up in EBX)',param) then exit;
2958  try
2959    parameter:=StrToInt('$'+param);
2960  except
2961    raise exception.Create('Please enter a valid hexadecimal value');
2962  end;
2963
2964  if CreateRemoteThread(processhandle,nil,0,pointer(startaddress),pointer(parameter),0,threadid)=0 then raise exception.Create('Creation of the remote thread failed') else showmessage('Thread Created');
2965end;
2966
2967procedure TMemoryBrowser.MemoryRegions1Click(Sender: TObject);
2968begin
2969  {$ifndef net}
2970  formmemoryregions:=tformmemoryregions.Create(self);
2971  formmemoryregions.show;
2972  {$endif}
2973end;
2974
2975procedure TMemoryBrowser.TextEditKeyPress(Sender: TObject; var Key: Char);
2976var bt: byte;
2977acr:dword;
2978a:integer;
2979begin
2980  a:=20+mbimage.Canvas.TextWidth('00400000');
2981  if editing2 then
2982  begin
2983    bt:=byte(key);
2984    if bt>=32 then
2985      writeprocessmemory(processhandle,pointer(selected),@bt,1,acr)
2986    else
2987    begin
2988      key:=#0;
2989      exit;
2990    end;
2991
2992    inc(scolumn);
2993    scolumn:=scolumn mod (8*rows8);
2994    if (scolumn)=0 then
2995    begin
2996      //move down
2997      inc(srow);
2998
2999      if (((srow+1)*(textheight)+3)+textedit.Height)>panel4.Height then
3000      begin
3001        dec(srow);
3002        textedit.top:=(srow+1)*(textheight)+3;
3003        inc(memoryaddress,8*rows8);
3004        refreshmb;
3005      end else textedit.Top:=(srow+1)*(textheight)+3;
3006    end;
3007
3008    textedit.left:=(1+a+20*8*rows8+(scolumn*mbcanvas.Canvas.TextWidth('D')));
3009    inc(selected);
3010
3011    acr:=0;
3012    readprocessmemory(processhandle,pointer(selected),@bt,1,acr);
3013
3014    if acr=1 then
3015    begin
3016      if bt>32 then textedit.text:=chr(bt) else textedit.text:=' ';
3017      editing2:=false;
3018      textedit.visible:=true;
3019      textedit.SelectAll;
3020      textedit.SetFocus;
3021    end else hexedit.visible:=false;
3022    key:=#0;
3023  end;
3024
3025  refreshmb;
3026end;
3027
3028procedure TMemoryBrowser.FillMemory1Click(Sender: TObject);
3029begin
3030  frmFillMemory:=TFrmFillMemory.create(self);
3031  with frmFillMemory do
3032  begin
3033    edit1.Text:=IntToHex(disassemblerview.SelectedAddress,8);
3034    edit2.Text:=IntToHex(disassemblerview.SelectedAddress+1,8);
3035    frmFillMemory.showmodal;
3036  end;
3037
3038end;
3039
3040procedure TMemoryBrowser.Disectwindow1Click(Sender: TObject);
3041begin
3042  {$ifndef net}
3043  frmdissectWindow:=tfrmdissectWindow.create(self);
3044  frmdissectWindow.showmodal;
3045  {$endif}
3046end;
3047
3048procedure TMemoryBrowser.Savedisassemledoutput1Click(Sender: TObject);
3049var x,y: string;
3050    start,stop: dword;
3051    output: textfile;
3052
3053begin
3054  with tfrmSavedisassembly.create(self) do
3055  begin
3056    start:=min(disassemblerview.SelectedAddress,disassemblerview.SelectedAddress2);
3057    stop:=max(disassemblerview.SelectedAddress,disassemblerview.SelectedAddress2);
3058    disassemble(stop);
3059    edit1.Text:=inttohex(start,8);
3060    edit2.Text:=inttohex(stop,8);
3061    show;
3062  end;
3063end;
3064
3065procedure TMemoryBrowser.Heaps1Click(Sender: TObject);
3066begin
3067  {$ifndef net}
3068  if processid=0 then raise exception.Create('Please target a process first');
3069  if (frmMemoryAllocHandler<>nil) and (frmMemoryAllocHandler.hookedprocessid<>processid) then
3070    freeandnil(frmMemoryAllocHandler);
3071
3072
3073
3074  if frmheaps=nil then
3075    frmheaps:=tfrmheaps.create(self);
3076
3077  frmheaps.show;
3078  {$endif}
3079
3080end;
3081
3082procedure TMemoryBrowser.EnumeratedllsandSymbols1Click(Sender: TObject);
3083begin
3084  {$ifndef net}
3085  symhandler.reinitialize;
3086 
3087  if frmEnumerateDLLs=nil then
3088  begin
3089    frmEnumerateDLLs:=tfrmEnumerateDLLs.create(self);
3090    frmEnumerateDLLs.Show;
3091  end
3092  else frmEnumerateDLLs.enumerate;
3093  {$endif}
3094end;
3095
3096procedure TMemoryBrowser.InjectDLL1Click(Sender: TObject);
3097var dll: string;
3098    functionname: string;
3099    dllList: tstringlist;
3100begin
3101  functionname:='';
3102  dll:='';
3103
3104  if opendlldialog.Execute then
3105  begin
3106    dll:=opendlldialog.Filename;
3107    if MessageDlg('Do you want to execute a function of the dll?',mtConfirmation        ,[mbyes,mbno],0)=mryes then
3108    begin
3109      dllList:=tstringlist.Create;
3110
3111      try
3112        peinfo_getExportList(opendlldialog.filename, dllList);
3113        with TfrmFunctionList.create(self,dllList) do
3114        begin
3115          if showmodal=mrok then
3116            if itemindex<>-1 then
3117              functionname:=functions[itemindex];
3118
3119          free;
3120        end;
3121      finally
3122        dllList.free;
3123      end;
3124    end;
3125
3126    InjectDll(dll,functionname);
3127    symhandler.reinitialize;
3128    showmessage('DLL Injected');
3129  end;
3130end;
3131
3132procedure TMemoryBrowser.AutoInject1Click(Sender: TObject);
3133begin
3134  tfrmautoinject.create(self).show;
3135end;
3136
3137procedure TMemoryBrowser.Dissectcode1Click(Sender: TObject);
3138begin
3139  {$ifndef net}
3140  if frmdissectcode=nil then
3141    frmdissectcode:=tfrmDissectcode.create(self);
3142
3143  frmdissectcode.Show;
3144  {$endif}
3145end;
3146
3147procedure TMemoryBrowser.Createjumptocodecave1Click(Sender: TObject);
3148var x: string;
3149    codecaveaddress: dword;
3150    size: dword;
3151begin
3152  x:='';
3153  if inputquery('Create Code-Cave','Give the address of the code-cave you want to use. (Use allocate memory if you couldn''t find one)',x) then
3154  begin
3155    try
3156      codecaveaddress:=StrToInt('$'+x);
3157    except
3158      raise exception.Create('Please give me a valid address');
3159    end;
3160
3161    x:='40';
3162    if inputquery('Create Code-Cave','How big is the code-cave (or how much do you think you''ll use?)',x) then
3163    begin
3164      try
3165        size:=StrToInt(x);
3166      except
3167        raise exception.Create('And how many bytes are that?');
3168      end;
3169
3170      CreateCodecave(codecaveaddress,disassemblerview.SelectedAddress,size);
3171
3172    end;
3173
3174
3175  end;
3176end;
3177
3178procedure TMemoryBrowser.Findstaticpointers1Click(Sender: TObject);
3179begin
3180{$ifndef net}
3181  if frmfindstatics=nil then
3182    frmfindstatics:=tfrmfindstatics.create(self);
3183
3184  frmfindstatics.show;
3185{$endif}
3186end;
3187
3188procedure TMemoryBrowser.Scanforcodecaves1Click(Sender: TObject);
3189begin
3190  if frmcodecavescanner=nil then
3191    frmcodecavescanner:=tfrmCodecaveScanner.create(self);
3192
3193  frmCodecavescanner.show;
3194end;
3195
3196procedure TMemoryBrowser.Changestateofregisteratthislocation1Click(
3197  Sender: TObject);
3198begin
3199{$ifndef net}
3200  if foundcodedialog<>nil then
3201    raise exception.Create('I can''t do that! You are currently using one of the code finder options, please, stop it first');
3202
3203  if (formsettings.cbKdebug.checked) and (kdebugger.isactive) and (kdebugger.nrofbreakpoints=4) then raise exception.Create('You have reached the maximum of 4 debugregs. Disable at least one breakpoint first'); //all spots filled up
3204
3205  if (not formsettings.cbKdebug.checked) then
3206    if (not startdebuggerifneeded) then exit;
3207
3208  tfrmModifyRegisters.create(self,disassemblerview.SelectedAddress).showmodal;
3209{$endif}
3210end;
3211
3212procedure TMemoryBrowser.ogglebreakpoint1Click(Sender: TObject);
3213begin
3214{$ifndef net}
3215  if (formsettings.cbKdebug.checked) and (debuggerthread=nil) then
3216  begin
3217    KDebugger.StartDebugger;
3218    KDebugger.ToggleBreakpoint(disassemblerview.SelectedAddress);
3219  end
3220  else
3221  begin
3222    //normal debugger
3223    togglebreakpoint(disassemblerview.SelectedAddress);
3224    disassemblerview.Update;
3225  end;
3226
3227
3228{$endif}
3229end;
3230
3231procedure TMemoryBrowser.Breakpointlist1Click(Sender: TObject);
3232begin
3233{$ifndef net}
3234  if frmbreakpointlist=nil then
3235  begin
3236    frmbreakpointlist:=tfrmBreakpointlist.create(self);
3237    frmBreakpointlist.show;
3238  end
3239  else
3240    frmbreakpointlist.bringtofront;
3241{$endif}
3242end;
3243
3244
3245procedure TMemoryBrowser.Makepagewritable1Click(Sender: TObject);
3246var x: dword;
3247begin
3248{$ifndef net}
3249  VirtualProtectEx(processhandle,pointer(memoryaddress),4096,PAGE_EXECUTE_READWRITE,x);
3250//  if (memoryaddress>80000000) and (DarkByteKernel<>0) then
3251//    MakeWritableEx(processhandle,memoryaddress,4096,false);
3252{$endif}
3253end;
3254
3255procedure TMemoryBrowser.Dissectdata1Click(Sender: TObject);
3256begin
3257{$ifndef net}
3258  with tfrmpointerscanner.create(self) do
3259    show;
3260{$endif}
3261end;
3262
3263procedure TMemoryBrowser.Showsymbols1Click(Sender: TObject);
3264begin
3265  showsymbols1.Checked:=not showsymbols1.Checked;
3266  symhandler.showsymbols:=showsymbols1.Checked;
3267  disassemblerview.Update;
3268end;
3269
3270procedure TMemoryBrowser.Showmoduleaddresses1Click(Sender: TObject);
3271begin
3272  Showmoduleaddresses1.Checked:=not Showmoduleaddresses1.checked;
3273  symhandler.showmodules:=Showmoduleaddresses1.Checked;
3274  disassemblerview.Update;
3275end;
3276
3277
3278procedure TMemoryBrowser.Dissectdata2Click(Sender: TObject);
3279begin
3280{$ifndef net}
3281  if length(frmStructures)>0 then
3282  begin
3283    frmStructures[0].edtAddress.Text:=inttohex(memorybrowser.memoryaddress,8);
3284    frmStructures[0].Show;
3285  end
3286  else
3287  begin
3288    //create it
3289    with tfrmstructures.create(self) do
3290    begin
3291      edtAddress.Text:=inttohex(memoryaddress,8);
3292      update(false);
3293      show;
3294    end;
3295  end;
3296
3297
3298
3299{$endif}
3300end;
3301
3302procedure TMemoryBrowser.Symbolhandler1Click(Sender: TObject);
3303begin
3304{$ifndef net}
3305  if frmSymbolhandler=nil then
3306    frmSymbolhandler:=TfrmSymbolhandler.create(self);
3307
3308  frmSymbolhandler.show;
3309{$endif}
3310end;
3311
3312procedure TMemoryBrowser.Allocatenonpagedmemory1Click(Sender: TObject);
3313var count: string;
3314    memsize: integer;
3315    baseaddress: pointer;
3316    x: dword;
3317    s: string;
3318begin
3319{$ifndef net}
3320  count:='4096';
3321  if inputquery('Allocate memory','How much memory do you wish to allocate?. ',count) then
3322  begin
3323    try
3324      memsize:=StrToInt(count);
3325    except
3326      raise exception.Create('How much is '+count+'?');
3327    end;
3328
3329    baseaddress:=nil;
3330    baseaddress:=KernelAlloc(memsize);
3331    if baseaddress<>nil then
3332    begin
3333      if (disassemblerview.SelectedAddress<>0) and (memsize>7) and (messagedlg('At least '+IntToStr(memsize)+' bytes have been allocated at '+IntToHex(dword(baseaddress),8)+#13#10+'Do you want replace the currently selected address with a jump to that address, and copy the overwritten instructions to there?',mtConfirmation,[mbyes,mbno],0)=mryes) then
3334        CreateCodecave(dword(baseaddress),disassemblerview.SelectedAddress,memsize)
3335      else
3336        messagedlg('At least '+IntToStr(memsize)+' bytes have been allocated at '+IntToHex(dword(baseaddress),8),mtinformation,[mbok],0);
3337
3338
3339      if messagedlg('Do you want to go there now?',mtConfirmation,[mbyes,mbno],0) = mryes then
3340        disassemblerview.SelectedAddress:=dword(baseaddress);
3341    end else raise exception.Create('Error allocating memory!');
3342  end;
3343  {$endif}
3344end;
3345
3346procedure TMemoryBrowser.Getaddress1Click(Sender: TObject);
3347var p: pointer;
3348    s: string;
3349    ws: widestring;
3350    pws: pwidechar;
3351begin
3352  if inputquery('Get kernel address','Give the name of the function you want to find (Case sensitive,certain words can cause blue screens)',s) then
3353  begin
3354    ws:=s;
3355    pws:=@ws[1];
3356    p:=GetKProcAddress(pws);
3357
3358    disassemblerview.SelectedAddress:=dword(p);
3359  end;
3360end;
3361
3362procedure TMemoryBrowser.Findmemory1Click(Sender: TObject);
3363begin
3364  search1.Click;
3365end;
3366
3367procedure TMemoryBrowser.Assemblycode1Click(Sender: TObject);
3368var s:string;
3369
3370begin
3371  s:='';
3372  if inputquery('Assembly scan','Input the assembly code to find. wilcards(*) supported.',s) then
3373  begin
3374    if s='' then exit;
3375    with TfrmDisassemblyscan.create(self) do
3376    begin
3377      startaddress:=disassemblerview.SelectedAddress;
3378      stringtofind:=s;
3379      show;
3380    end;
3381
3382  end;
3383end;
3384
3385procedure TMemoryBrowser.Driverlist1Click(Sender: TObject);
3386begin
3387  {$ifndef net}
3388  with tfrmdriverlist.create(self) do
3389    show;
3390  {$endif}
3391end;
3392
3393procedure TMemoryBrowser.plugintype6click(sender:tobject);
3394var
3395  x: TPluginfunctionType6;
3396  selectedaddress: dword;
3397begin
3398  x:=TPluginfunctionType6(tmenuitem(sender).Tag);
3399  if x<>nil then
3400  begin
3401    selectedaddress:=disassemblerview.SelectedAddress;
3402    x.callback(@selectedaddress);
3403    disassemblerview.SelectedAddress:=selectedaddress;
3404  end;
3405end;
3406
3407procedure TMemoryBrowser.plugintype1click(sender:tobject);
3408{$ifndef net}
3409var x: TPluginfunctionType1;
3410address: dword;
3411{$endif}
3412begin
3413{$ifndef net}
3414  x:=TPluginfunctionType1(tmenuitem(sender).Tag);
3415  if x<>nil then
3416  begin
3417    address:=disassemblerview.TopAddress;
3418    x.callback(@address,@disassemblerview.SelectedAddress,@memoryaddress);
3419    disassemblerview.TopAddress:=address;
3420    refreshmb;
3421  end;
3422{$endif}
3423end;
3424
3425procedure TMemoryBrowser.Sericedescriptortable1Click(Sender: TObject);
3426begin
3427{$ifndef net}
3428  if frmServiceDescriptorTables=nil then
3429    frmServiceDescriptorTables:=TfrmServiceDescriptorTables.create(self);
3430
3431  frmServiceDescriptorTables.show;
3432{$endif}
3433end;
3434
3435procedure TMemoryBrowser.MBCanvasMouseDown(Sender: TObject;
3436  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
3437var a: integer;
3438    i,j: integer;
3439    acr: dword;
3440    bt:byte;
3441
3442    temp:string;
3443    hadselection: boolean;
3444begin
3445  if button=mbright then
3446  begin
3447    if selecting or selectionmade then exit;
3448  end;
3449
3450  selecting:=button=mbleft;
3451
3452  hadselection:=selectionmade;
3453  selectionmade:=false;
3454
3455  fcontrol2.SetFocus;
3456  hexedit.Visible:=false;
3457  textedit.Visible:=false;
3458
3459//find out if the user clicked on a byte, and if so which one
3460  a:=20+mbimage.Canvas.TextWidth('00400000');
3461  part:=0; //address
3462
3463  if x>a then
3464  begin  //didnt click on the address
3465    part:=2; //textfield ad the left side
3466    if x<(a+20*8*rows8) then //byteclick
3467    begin
3468      if displaytype<>dtByte then
3469      begin
3470        selecting:=false; //not for this type
3471        exit;
3472      end;
3473     
3474      part:=1; //a byte
3475      srow:=(y div textheight);
3476      scolumn:=(x-a) div 20;
3477
3478      i:=(srow*8*rows8)+scolumn;
3479      //caption:=Inttohex(memoryaddress+i,8);
3480      selected:=memoryaddress+i;
3481
3482    end
3483    else
3484    begin
3485      //not on a byte click
3486      for i:=1 to 8*rows8 do
3487        temp:=temp+'D';
3488
3489      srow:=y div textheight;
3490
3491
3492      i:=(x-(1+a+20*8*rows8));
3493
3494      scolumn:=i div mbcanvas.Canvas.TextWidth('D');
3495
3496      if scolumn<8*rows8 then
3497      begin
3498        i:=scolumn*mbcanvas.Canvas.TextWidth('D');
3499        selected:=scolumn+memoryaddress+(8*rows8)*srow;
3500
3501      end;
3502    end;
3503  end;
3504
3505  selected2:=selected;
3506
3507  if hadselection then RefreshMB;
3508end;
3509
3510procedure TMemoryBrowser.Cut1Click(Sender: TObject);
3511var i: dword;
3512    start,stop: dword;
3513    x: byte;
3514    br: dword;
3515    s: string;
3516
3517    cl: tclipboard;
3518begin
3519  if selected>selected2 then
3520  begin
3521    start:=selected2;
3522    stop:=selected;
3523  end
3524  else
3525  begin
3526    start:=selected;
3527    stop:=selected2;
3528  end;
3529
3530  s:='';
3531  for i:=start to stop do
3532  begin
3533    if readprocessmemory(processhandle,pointer(i),@x,1,br) then
3534    begin
3535      s:=s+inttohex(x,2)+' ';
3536    end
3537    else s:=s+'?? ';
3538  end;
3539
3540  if s<>'' then
3541    s:=copy(s,1,length(s)-1);
3542
3543  cl:=tclipboard.Create;
3544  cl.AsText:=s;
3545  cl.Free;
3546end;
3547
3548procedure TMemoryBrowser.Pastefromclipboard1Click(Sender: TObject);
3549var cl: tclipboard;
3550    s: string;
3551    i: integer;
3552    x,bw: dword;
3553    b: tbytes;
3554begin
3555  cl:=tclipboard.Create;
3556  s:=cl.AsText;
3557  cl.free;
3558
3559
3560  setlength(b,0);
3561  try
3562    ConvertStringToBytes(s,true,b);
3563    x:=selected;
3564    for i:=0 to length(b)-1 do
3565    begin
3566      if b[i]<>-1 then
3567        writeprocessmemory(processhandle,pointer(x),@b[i],1,bw);
3568
3569      inc(x);
3570    end;
3571  except
3572
3573  end;
3574
3575  setlength(b,0);
3576  refreshmb;
3577end;
3578
3579procedure TMemoryBrowser.Setsymbolsearchpath1Click(Sender: TObject);
3580var searchpath: string;
3581begin
3582{$ifndef net}
3583  if symhandler.isloaded then
3584  begin
3585    searchpath:=symhandler.getsearchpath;
3586    if inputquery('Symbol handler','Please specify the new symbol searchpath (; seperates paths)',searchpath) then
3587    begin
3588      symhandler.setsearchpath(searchpath);
3589
3590      symhandler.reinitialize;
3591
3592      symhandler.waitforsymbolsloaded;
3593
3594    end;
3595  end;
3596{$endif}
3597end;
3598
3599procedure TMemoryBrowser.Kernelmodesymbols1Click(Sender: TObject);
3600begin
3601{$ifndef net}
3602
3603  Kernelmodesymbols1.Checked:=not Kernelmodesymbols1.Checked;
3604
3605  symhandler.kernelsymbols:=Kernelmodesymbols1.Checked;
3606  symhandler.reinitialize;
3607  symhandler.waitforsymbolsloaded;
3608{$endif}
3609end;
3610
3611procedure TMemoryBrowser.Breakandtraceinstructions1Click(Sender: TObject);
3612begin
3613//  if debugger<>nil then
3614{$ifndef net}
3615
3616  frmtracer:=TFrmTracer.create(self);
3617  frmtracer.show;
3618{$endif}
3619end;
3620
3621procedure TMemoryBrowser.debuggerpopupPopup(Sender: TObject);
3622var x: dword;
3623begin
3624  Breakandtraceinstructions1.Enabled:=processhandle<>0;
3625  ogglebreakpoint1.Enabled:=processhandle<>0;
3626  Changestateofregisteratthislocation1.Enabled:=processhandle<>0;
3627  follow1.visible:=isjumporcall(disassemblerview.SelectedAddress,x);
3628  back1.Visible:=backlist.Count>0;
3629
3630  pluginhandler.handledisassemblerContextPopup(disassemblerview.SelectedAddress);
3631end;
3632
3633procedure TMemoryBrowser.GDTlist1Click(Sender: TObject);
3634begin
3635  Tfrmgdtinfo.create(self).show;
3636end;
3637
3638procedure TMemoryBrowser.IDTlist1Click(Sender: TObject);
3639begin
3640  TfrmIDT.create(self).show;
3641end;
3642
3643procedure TMemoryBrowser.ScriptEngine1Click(Sender: TObject);
3644var x: tfrmautoinject;
3645begin
3646  x:=tfrmautoinject.create(self);
3647  x.cplusplus:=true;
3648  x.show;
3649end;
3650
3651procedure TMemoryBrowser.FormDestroy(Sender: TObject);
3652var h0,h1,h2,h3: integer;
3653begin
3654  if strace<>nil then
3655    strace.free;
3656
3657  disassemblerHistory.free;
3658  memorybrowserHistory.free;
3659  assemblerHistory.free;
3660
3661  //save position of window and other stuff
3662  //membrowser comes after formsettings so is destroyed before formsettings, so valid
3663  if (not ischild) then
3664  begin
3665    saveformposition(self,[
3666                            disassemblerview.getheaderwidth(0),
3667                            disassemblerview.getheaderwidth(1),
3668                            disassemblerview.getheaderwidth(2),
3669                            disassemblerview.getheaderwidth(3),
3670                            panel1.height,
3671                            registerview.width
3672                    ]);   
3673  end;
3674
3675end;
3676
3677procedure TMemoryBrowser.Newwindow1Click(Sender: TObject);
3678begin
3679  with tmemorybrowser.create(nil) do
3680  begin
3681    inc(mbchildcount);
3682    name:='MemoryBrowser'+inttostr(mbchildcount);
3683    debug1.Visible:=false;
3684    //registerview.Visible:=false;
3685    //splitter2.Visible:=false;
3686    sbShowFloats.Visible:=false;
3687    caption:=caption+'* ('+inttostr(mbchildcount)+')';
3688
3689    ischild:=true;
3690    show;
3691  end;
3692end;
3693
3694
3695procedure TMemoryBrowser.Follow1Click(Sender: TObject);
3696{
3697will change the selected disassembler address to the address this instructions jump so if it is an jump instruction
3698}
3699var address: dword;
3700begin
3701  if isjumporcall(disassemblerview.SelectedAddress,address) then
3702  begin
3703    backlist.Push(pointer(disassemblerview.SelectedAddress));
3704    disassemblerview.SelectedAddress:=address;
3705  end;
3706end;
3707
3708
3709
3710procedure TMemoryBrowser.CopyBytesAndOpcodesClick(Sender: TObject);
3711var a,b: dword;
3712    _tag: integer;
3713begin
3714  _tag:=(sender as tmenuitem).Tag;
3715
3716  with tfrmSavedisassembly.create(self) do
3717  begin
3718
3719    a:=min(disassemblerview.SelectedAddress, disassemblerview.SelectedAddress2);
3720    b:=max(disassemblerview.SelectedAddress, disassemblerview.SelectedAddress2);
3721   
3722    disassemble(b); //b gets increased with size of selected instruction
3723    edit1.Text:=inttohex(a,8);
3724    edit2.Text:=inttohex(b-1,8);
3725    copymode:=true;
3726
3727    checkbox1.checked:=true;
3728    checkbox2.checked:=(_tag=0) or (_tag=1);
3729    checkbox3.checked:=(_tag=0) or (_tag=2);
3730   
3731    button1.click;
3732    waittilldone;
3733
3734    free;
3735  end;
3736
3737
3738end;
3739
3740procedure TMemoryBrowser.DissectPEheaders1Click(Sender: TObject);
3741begin
3742  with TfrmPEInfo.create(self) do
3743    show;
3744end;
3745
3746procedure TMemoryBrowser.SetCodeAndDataBase;
3747var modulelist: tstringlist;
3748    base: dword;
3749    header: pointer;
3750    headersize: dword;
3751    br: dword;
3752begin
3753  modulelist:=tstringlist.Create;
3754  symhandler.getModuleList(modulelist);
3755
3756  if modulelist.Count>0 then
3757  begin
3758    base:=dword(modulelist.Objects[0]);
3759    getmem(header,4096);
3760    try
3761      if readprocessmemory(processhandle,pointer(base),header,4096,br) then
3762      begin
3763        headersize:=peinfo_getheadersize(header);
3764        if headersize=0 then exit;
3765       
3766        if headersize>4096 then
3767        begin
3768          if headersize>1024*512 then exit;
3769
3770          freemem(header);
3771          getmem(header,headersize);
3772          if not readprocessmemory(processhandle,pointer(base),header,headersize,br) then exit;
3773        end;
3774
3775        disassemblerview.SelectedAddress:=base+peinfo_getEntryPoint(header);
3776
3777        memoryaddress:=base+peinfo_getdatabase(header);
3778      end;
3779    finally
3780      freemem(header);
3781    end;
3782  end;
3783  modulelist.free;
3784end;
3785
3786procedure TMemoryBrowser.Back1Click(Sender: TObject);
3787begin
3788  if backlist.Count>0 then
3789    disassemblerview.SelectedAddress:=dword(backlist.pop);
3790end;
3791
3792procedure TMemoryBrowser.Showvaluesofstaticaddresses1Click(
3793  Sender: TObject);
3794begin
3795  showvalues:=not showvalues;
3796end;
3797
3798procedure TMemoryBrowser.FindwhatThiscodeAccesses(address: dword);
3799var i: integer;
3800begin
3801  //check if the old window exists, if so, mark it as deactivated
3802  if frmChangedAddresses<>nil then
3803    frmChangedAddresses.changedlist.color:=clGray;
3804
3805  //create new window, and leave the old one alive
3806  frmChangedAddresses:=TfrmChangedAddresses.Create(self);
3807 
3808  if (formsettings.cbKdebug.checked) and (debuggerthread=nil) then
3809  begin
3810    KDebugger.StartDebugger;  //if it wasn't enabled yet
3811    try
3812      KDebugger.SetBreakpoint(address, bt_OnInstruction, 1, bo_FindWhatCodeAccesses);
3813    except
3814      on e: exception do
3815      begin
3816        freeandnil(frmChangedAddresses);
3817        raise e;
3818      end;
3819    end;
3820  end
3821  else
3822  begin
3823    //New method:
3824    if not startdebuggerifneeded then exit;
3825    if debuggerthread.userisdebugging then raise exception.create('You can''t use this function while you are debugging the application yourself. (Close the memory view window forces a close of manual debugging)');
3826
3827    if frmChangedAddresses<>nil then
3828      frmChangedAddresses.changedlist.color:=clGray;
3829
3830    frmChangedAddresses:=TfrmChangedAddresses.Create(self);
3831
3832    debuggerthread.Suspend;
3833
3834    debuggerthread.DRRegs.ContextFlags:=CONTEXT_DEBUG_REGISTERS;
3835    debuggerthread.DRRegs.Dr0:=address;
3836    debuggerthread.DRRegs.Dr7:=reg0set or reg1set or reg2set or reg3set;
3837
3838    for i:=0 to length(debuggerthread.threadlist)-1 do
3839    begin
3840      suspendthread(debuggerthread.threadlist[i][1]);
3841      if not setthreadcontext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs) then showmessage('failed 1');
3842      resumethread(debuggerthread.threadlist[i][1]);
3843    end;
3844
3845
3846    debuggerthread.breakpointaddress:=address;
3847    debuggerthread.breakpointset:=true;
3848
3849    debuggerthread.Resume;
3850  end;
3851  frmChangedAddresses.show;
3852end;
3853
3854procedure TMemoryBrowser.Findoutwhataddressesthisinstructionaccesses1Click(
3855  Sender: TObject);
3856begin
3857  findWhatthisCodeAccesses(disassemblerview.SelectedAddress);
3858end;
3859
3860procedure TMemoryBrowser.sbShowFloatsClick(Sender: TObject);
3861var x: tpoint;
3862z: trect;
3863begin
3864  if frmFloatingPointPanel=nil then
3865    frmFloatingPointPanel:=TfrmFloatingPointPanel.create(self);
3866
3867  frmFloatingPointPanel.Left:=self.left+self.Width;
3868  frmFloatingPointPanel.Top:=self.top+(self.ClientOrigin.y-self.top)-(frmFloatingPointPanel.ClientOrigin.y-frmFloatingPointPanel.top);
3869  frmFloatingPointPanel.ClientHeight:=scrollbox1.Height;
3870  frmFloatingPointPanel.show;//pop to foreground
3871end;
3872
3873procedure TMemoryBrowser.ScriptConsole1Click(Sender: TObject);
3874begin
3875  with TfrmCScript.create(self) do
3876    show;
3877end;
3878
3879procedure TMemoryBrowser.DisplayTypeClick(Sender: TObject);
3880var x: tmenuitem;
3881begin
3882//vtByte, vtWord, vtDword, vtDwordDec, vtSingle, vtDouble
3883  if (sender is TMenuItem) then
3884  begin
3885    x:=TMenuItem(sender);
3886    case x.tag of
3887      0: DisplayType:=dtByte;
3888      1: DisplayType:=dtWord;
3889      2: DisplayType:=dtDword;
3890      3: DisplayType:=dtDwordDec;
3891      4: DisplayType:=dtsingle;
3892      5: DisplayType:=dtDouble;
3893    end;
3894
3895
3896    mbimage.Canvas.FillRect(rect(0,0,mbimage.Width,mbimage.Height));
3897    MBCanvas.Invalidate;
3898    MBCanvas.Repaint;
3899    refreshMB;
3900  end;
3901end;
3902
3903procedure TMemoryBrowser.Showjumplines1Click(Sender: TObject);
3904begin
3905  showjumplines1.checked:=not showjumplines1.checked;
3906  disassemblerview.showjumplines:=showjumplines1.checked;
3907
3908  Onlyshowjumplineswithinrange1.Enabled:=showjumplines1.checked;
3909end;
3910
3911procedure TMemoryBrowser.Onlyshowjumplineswithinrange1Click(
3912  Sender: TObject);
3913begin
3914  Onlyshowjumplineswithinrange1.checked:=not Onlyshowjumplineswithinrange1.checked;
3915  if Onlyshowjumplineswithinrange1.checked then
3916    disassemblerview.ShowJumplineState:=jlsOnlyWithinRange
3917  else
3918    disassemblerview.ShowJumplineState:=jlsAll;
3919
3920end;
3921
3922procedure TMemoryBrowser.Watchmemoryallocations1Click(Sender: TObject);
3923begin
3924  if processid=0 then raise exception.Create('Please target a process first');
3925  if (frmMemoryAllocHandler<>nil) and (frmMemoryAllocHandler.hookedprocessid<>processid) then
3926    freeandnil(frmMemoryAllocHandler);
3927
3928
3929  if frmMemoryAllocHandler=nil then
3930    frmMemoryAllocHandler:=TfrmMemoryAllocHandler.Create(self);
3931
3932  frmMemoryAllocHandler.Show;
3933end;
3934
3935procedure TMemoryBrowser.Continueanddetachdebugger1Click(Sender: TObject);
3936begin
3937  if debuggerthread<>nil then
3938  begin
3939    debuggerthread.Terminate;
3940    debuggerthread.continuehow:=wdco_run;   //note: I could also have the debuggerthread suspend itself, and resume it here
3941    debuggerthread.continueprocess:=true;
3942    caption:='Memory Viewer - Detaching';
3943    debuggerthread.WaitFor;
3944    open_process;
3945    caption:='Memory Viewer - Detached';
3946  end;
3947end;
3948
3949procedure TMemoryBrowser.Panel2Resize(Sender: TObject);
3950begin
3951  mbcanvas.Height:=panel4.Height-2-9;
3952  mbcanvas.Width:=panel4.Width;
3953
3954  mbimage.Width:=mbcanvas.Width;
3955  mbimage.Height:=mbcanvas.Height;
3956
3957  mbimage.Canvas.FillRect(rect(0,0,mbimage.Width,mbimage.Height));
3958  MBCanvas.Invalidate;
3959  MBCanvas.Repaint;
3960  refreshMB;
3961
3962  if hexedit.visible or textedit.visible then fcontrol2.SetFocus;
3963end;
3964
3965procedure TMemoryBrowser.Panel2MouseDown(Sender: TObject;
3966  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
3967begin
3968  fcontrol2.SetFocus;
3969end;
3970
3971procedure TMemoryBrowser.ScrollBox1Resize(Sender: TObject);
3972begin
3973  sbShowFloats.Top:=scrollbox1.ClientHeight div 2-sbShowFloats.Height div 2;
3974end;
3975
3976procedure TMemoryBrowser.reloadStacktrace;
3977var s: pdwordarray;
3978    x: dword;
3979   
3980    i: integer;
3981    address, bytes, details: string;
3982    li: tlistitem;
3983    c: TListcolumn;
3984begin
3985  lvStacktraceData.Items.BeginUpdate;
3986  try
3987    if stacktrace2.Checked then
3988    begin
3989      //setup view for stacktrace if it isn't setup yet
3990      if lvStacktraceData.columns.Count=3 then
3991      begin
3992        lvstacktracedata.Columns.BeginUpdate;
3993        try
3994          lvstacktracedata.Columns.Clear;
3995          c:=lvstacktracedata.Columns.Add;
3996          c.Caption:='Return Address';
3997          c.Width:=lvstacktracedata.Canvas.TextWidth('DDDDDDDD');
3998          c.AutoSize:=true;
3999
4000
4001          c:=lvstacktracedata.Columns.Add;
4002          c.Caption:='Parameters';
4003          c.Width:=200;
4004          c.AutoSize:=true;
4005
4006        finally
4007          lvstacktracedata.Columns.EndUpdate;
4008        end;
4009      end;
4010
4011      if frmstacktrace=nil then
4012        frmstacktrace:=tfrmstacktrace.create(self);
4013
4014
4015      lvstacktracedata.Items.Count:=frmstacktrace.ListView1.Items.Count;
4016    end
4017    else
4018    begin
4019      //setup view for stackview if it isn't setup yet
4020      if lvStacktraceData.columns.Count<>3 then
4021      begin
4022        lvstacktracedata.Columns.BeginUpdate;
4023        try
4024          lvstacktracedata.Columns.Clear;
4025          c:=lvstacktracedata.Columns.Add;
4026          c.Caption:='Address';
4027          c.Width:=80;
4028          c:=lvstacktracedata.Columns.Add;
4029          c.Caption:='DWORD';
4030          c.Width:=80;
4031          c:=lvstacktracedata.Columns.Add;
4032          c.Caption:='Value';
4033          c.Width:=100;
4034          c.AutoSize:=true;
4035        finally
4036          lvstacktracedata.Columns.EndUpdate;
4037        end;
4038      end;
4039
4040      if all1.checked =false then
4041      begin
4042        //just get the list
4043        getmem(s,FStacktraceSize);
4044        try
4045          readprocessmemory(processhandle, pointer(lastdebugcontext.Esp),s, FStacktraceSize,x);
4046          strace.Clear;
4047          ce_stacktrace(lastdebugcontext.esp, lastdebugcontext.ebp, lastdebugcontext.eip, s,x, strace,false,Nonsystemmodulesonly1.checked or modulesonly1.Checked,Nonsystemmodulesonly1.checked,0);
4048
4049          lvstacktracedata.Items.Count:=strace.Count;
4050        finally
4051          freemem(s);
4052        end;
4053      end else
4054      begin
4055        lvstacktracedata.Items.Count:=4096 div 4;
4056      end;
4057
4058    end;
4059  finally
4060    lvStacktraceData.Items.EndUpdate;
4061  end;
4062{
4063  lvStacktraceData.Items.BeginUpdate;
4064  lvStacktraceData.count:=0;
4065
4066  lvStacktraceData.Items.EndUpdate;
4067
4068  trace:=tstringlist.Create;
4069  getmem(s,FStacktraceSize);
4070  try
4071    readprocessmemory(processhandle, pointer(lastdebugcontext.Esp),s, FStacktraceSize,x);
4072    ce_stacktrace(lastdebugcontext.esp, lastdebugcontext.ebp, lastdebugcontext.eip, s,x, trace,false,Nonsystemmodulesonly1.checked or modulesonly1.Checked,Nonsystemmodulesonly1.checked,0);
4073
4074    for i:=0 to trace.count-1 do
4075    begin
4076      seperatestacktraceline(trace[i], address,bytes,details);
4077      li:=lvStacktrace.Items.Add;
4078      li.Caption:=address;
4079      li.SubItems.Add(bytes);
4080      li.SubItems.Add(details);
4081    end;
4082  finally
4083    freemem(s);
4084    trace.free;
4085  end;}
4086
4087end;
4088
4089procedure TMemoryBrowser.Maxstacktracesize1Click(Sender: TObject);
4090var
4091  s: string;
4092begin
4093  s:=inttostr(stacktraceSize);
4094  InputQuery('Stacktrace','New size:',s);
4095  try
4096    stacktraceSize:=strtoint(s);
4097    Maxstacktracesize1.Caption:='Max stacktrace size: '+inttostr(stacktracesize);
4098  except
4099  end;
4100end;
4101
4102procedure TMemoryBrowser.All1Click(Sender: TObject);
4103begin
4104  all1.checked:=true;
4105  Modulesonly1.Checked:=false;
4106  Nonsystemmodulesonly1.Checked:=false;
4107  stacktrace2.Checked:=false;
4108  reloadstacktrace;
4109end;
4110
4111procedure TMemoryBrowser.Modulesonly1Click(Sender: TObject);
4112begin
4113  all1.checked:=false;
4114  Modulesonly1.Checked:=true;
4115  Nonsystemmodulesonly1.Checked:=false;
4116  stacktrace2.Checked:=false;
4117  reloadstacktrace;
4118end;
4119
4120procedure TMemoryBrowser.Nonsystemmodulesonly1Click(Sender: TObject);
4121begin
4122  all1.checked:=false;
4123  Modulesonly1.Checked:=false;
4124  Nonsystemmodulesonly1.Checked:=true;
4125  stacktrace2.Checked:=false;
4126  reloadstacktrace;
4127end;
4128
4129procedure TMemoryBrowser.stacktrace2Click(Sender: TObject);
4130begin
4131  all1.checked:=false;
4132  Modulesonly1.Checked:=false;
4133  Nonsystemmodulesonly1.Checked:=false;
4134  stacktrace2.Checked:=true;
4135  reloadstacktrace;
4136end;
4137
4138procedure TMemoryBrowser.Referencedstrings1Click(Sender: TObject);
4139begin
4140  if (frmDissectCode=nil) or (frmDissectCode.dissectcode=nil) then
4141  begin
4142    if MessageDlg('You will need to run the dissect code routine first before this window is usable. Run it now?', mtConfirmation, [mbyes, mbno], 0)=mryes then
4143    begin
4144      Dissectcode1Click(sender);
4145      frmDissectCode.ondone:=odOpenReferedStringList;
4146      frmDissectCode.btnStart.click;
4147    end;
4148  end else
4149  begin
4150    if frmReferencedStrings=nil then
4151      frmReferencedStrings:=tfrmReferencedStrings.Create(self);
4152
4153    frmReferencedStrings.Show;
4154  end;
4155end;
4156
4157
4158function TMemoryBrowser.GetReturnaddress: dword;
4159var
4160  haserror: boolean;
4161  stack: array [0..1023] of dword;
4162  x: dword;
4163  i: integer;
4164begin
4165  result:=0;
4166
4167  //do a stacktrace and find the return address
4168  if frmstacktrace=nil then
4169    frmstacktrace:=tfrmstacktrace.create(self);
4170
4171  if frmStacktrace.ListView1.Items.Count>0 then
4172  begin
4173    result:=symhandler.getAddressFromName(frmStacktrace.ListView1.Items[0].SubItems[2], false,haserror);
4174    if haserror then result:=0;
4175  end;
4176
4177  if result=0 then
4178  begin
4179
4180    //go through the stack and find a entry that falls in executable memory
4181    ReadProcessMemory(processhandle, pointer(lastdebugcontext.Esp), @stack[0], 4096, x);
4182    for i:=0 to (x div 4) do
4183    begin
4184      if symhandler.inModule(stack[i]) and isExecutableAddress(stack[i]) then
4185      begin
4186        result:=stack[i]; //best guess, it's an address specifier, it falls inside a module, and it's executable
4187        exit;
4188      end;
4189    end;
4190  end;
4191end;
4192
4193procedure TMemoryBrowser.Executetillreturn1Click(Sender: TObject);
4194var x: dword;
4195begin
4196  x:=getreturnaddress;
4197  if x>0 then
4198  begin
4199    disassemblerview.SelectedAddress:=x;
4200    Runtill1.Click;
4201  end else beep; //not possible
4202end;
4203
4204procedure TMemoryBrowser.lvStacktraceDataData(Sender: TObject; Item: TListItem);
4205var
4206  value,x: dword;
4207  a: dword;
4208  address,bytes,details: string;
4209  v: TVariableType;
4210begin
4211  if stacktrace2.checked then
4212  begin
4213    //show frmstacktrace
4214    if frmStacktrace=nil then
4215      frmstacktrace:=TfrmStacktrace.Create(self); //should never happen
4216
4217    if item.Index<frmStacktrace.ListView1.Items.Count then
4218    begin
4219      item.Caption:=frmStacktrace.ListView1.Items[item.index].SubItems[2]; //returnaddress
4220      item.SubItems.Add(frmStacktrace.ListView1.Items[item.index].SubItems[3]); //subitems address
4221    end;
4222  end
4223  else
4224  if all1.checked then
4225  begin
4226    //show for each dword what it is
4227    a:=lastdebugcontext.Esp+item.Index*4;
4228    item.Caption:=inttohex(a,8);
4229    if readprocessmemory(processhandle, pointer(a), @value, sizeof(value),x) then
4230    begin
4231      item.SubItems.Add(inttohex(value,8));
4232      v:=FindTypeOfData(a,@value,sizeof(value));
4233      case v of
4234        vtSingle:
4235          item.SubItems.Add(format('%.4f',[psingle(@value)^]));
4236
4237        vtPointer:
4238        begin
4239          item.SubItems.Add(symhandler.getNameFromAddress(value));
4240        end;
4241
4242        else
4243          item.SubItems.Add(inttostr(value));
4244
4245      end;
4246    end;
4247  end else
4248  begin
4249    //show strace
4250    if strace<>nil then
4251    begin
4252      if item.index<strace.count then
4253      begin
4254        seperatestacktraceline(strace[item.index], address,bytes,details);
4255        item.Caption:=address;
4256        item.SubItems.Add(bytes);
4257        item.SubItems.Add(details);
4258      end;
4259    end;
4260  end;
4261end;
4262
4263procedure TMemoryBrowser.lvStacktraceDataDblClick(Sender: TObject);
4264var
4265  hasError: boolean;
4266  x: dword;
4267
4268  column : integer;
4269  cursorpos: tpoint;
4270  tvrect: trect;
4271  i: integer;
4272
4273  currentleft: integer;
4274  s: string;
4275begin
4276  if stacktrace2.checked then
4277  begin
4278    //go to the selected address
4279    x:=symhandler.getAddressFromName(lvStacktraceData.Selected.Caption,false,haserror);
4280    if not haserror then
4281      disassemblerview.SelectedAddress:=x;
4282  end
4283  else
4284  begin
4285    //depending on what column is selected go to the disassembler/hexview part
4286    cursorpos:=mouse.CursorPos;
4287    GetWindowRect(lvStacktraceData.Handle, tvrect);
4288
4289    //get the relative position
4290    cursorpos.X:=cursorpos.X-tvrect.Left;
4291    cursorpos.Y:=cursorpos.Y-tvrect.Top;
4292
4293    column:=0;
4294
4295    currentleft:=0;
4296    for i:=0 to lvStacktraceData.Columns.count-1 do
4297    begin
4298      if (cursorpos.X>currentleft) and (cursorpos.X<(currentleft+lvStacktraceData.Columns[i].width)) then
4299      begin
4300        column:=i;
4301        break;
4302      end;
4303      inc(currentleft, lvStacktraceData.Columns[i].width);
4304    end;
4305
4306    if column=0 then
4307      s:=lvStacktraceData.Selected.Caption
4308    else
4309      s:=lvStacktraceData.Selected.SubItems[column-1];
4310
4311    x:=symhandler.getAddressFromName(lvStacktraceData.Selected.Caption,false,haserror);
4312    if not haserror then
4313    begin
4314      if isExecutableAddress(x) then
4315        disassemblerview.SelectedAddress:=x
4316      else
4317      begin
4318        memoryaddress:=x;
4319        RefreshMB;
4320      end;
4321    end;
4322
4323  end;
4324end;
4325
4326end.
Note: See TracBrowser for help on using the browser.