root/Cheat Engine/frmautoinjectunit.pas @ 311

Revision 311, 35.6 kB (checked in by dark_byte, 8 months ago)

mass commit for beta 6

Line 
1unit frmautoinjectunit;
2
3interface
4
5uses
6  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
7  Dialogs, StdCtrls, ExtCtrls, Menus,cefuncproc,  StrUtils, types,
8  ComCtrls,
9  {$ifdef net}
10  netapis,
11  {$else}
12  newkernelhandler,
13  {$endif}
14  {$ifndef standalonetrainerwithassembler}
15  disassembler,
16  mainunit2,
17  psvAutoAssembler,
18  psvCPlusPlus,
19  underc,
20  SynEdit, SynEditSearch, SynHighlighterAA, SynHighlighterCPP,
21  {$endif}
22  assemblerunit, autoassembler, symbolhandler;
23
24type TSynEditFix = class (TSynEdit)
25  private
26    procedure PasteFromClipboard;
27end;
28
29
30type
31  TfrmAutoInject = class(TForm)
32    MainMenu1: TMainMenu;
33    File1: TMenuItem;
34    Panel1: TPanel;
35    Button1: TButton;
36    Load1: TMenuItem;
37    Save1: TMenuItem;
38    OpenDialog1: TOpenDialog;
39    SaveDialog1: TSaveDialog;
40    Exit1: TMenuItem;
41    Assigntocurrentcheattable1: TMenuItem;
42    emplate1: TMenuItem;
43    Codeinjection1: TMenuItem;
44    CheatTablecompliantcodee1: TMenuItem;
45    APIHook1: TMenuItem;
46    SaveAs1: TMenuItem;
47    PopupMenu1: TPopupMenu;
48    Coderelocation1: TMenuItem;
49    TabControl1: TTabControl;
50    New1: TMenuItem;
51    N2: TMenuItem;
52    Syntaxhighlighting1: TMenuItem;
53    closemenu: TPopupMenu;
54    Close1: TMenuItem;
55    Inject1: TMenuItem;
56    Injectincurrentprocess1: TMenuItem;
57    Injectintocurrentprocessandexecute1: TMenuItem;
58    Find1: TMenuItem;
59    Paste1: TMenuItem;
60    Copy1: TMenuItem;
61    Cut1: TMenuItem;
62    Undo1: TMenuItem;
63    N6: TMenuItem;
64    FindDialog1: TFindDialog;
65    undotimer: TTimer;
66    View1: TMenuItem;
67    AAPref1: TMenuItem;
68    procedure Button1Click(Sender: TObject);
69    procedure Load1Click(Sender: TObject);
70    procedure Save1Click(Sender: TObject);
71    procedure Exit1Click(Sender: TObject);
72    procedure FormClose(Sender: TObject; var Action: TCloseAction);
73    procedure Codeinjection1Click(Sender: TObject);
74    procedure Panel1Resize(Sender: TObject);
75    procedure CheatTablecompliantcodee1Click(Sender: TObject);
76    procedure assemblescreenChange(Sender: TObject);
77    procedure Assigntocurrentcheattable1Click(Sender: TObject);
78    procedure APIHook1Click(Sender: TObject);
79    procedure SaveAs1Click(Sender: TObject);
80    procedure FormShow(Sender: TObject);
81    procedure assemblescreenKeyDown(Sender: TObject; var Key: Word;
82      Shift: TShiftState);
83    procedure Coderelocation1Click(Sender: TObject);
84    procedure New1Click(Sender: TObject);
85    procedure FormCreate(Sender: TObject);
86    procedure TabControl1Change(Sender: TObject);
87    procedure Syntaxhighlighting1Click(Sender: TObject);
88    procedure TabControl1ContextPopup(Sender: TObject; MousePos: TPoint;
89      var Handled: Boolean);
90    procedure Close1Click(Sender: TObject);
91    procedure Injectincurrentprocess1Click(Sender: TObject);
92    procedure Injectintocurrentprocessandexecute1Click(Sender: TObject);
93    procedure Cut1Click(Sender: TObject);
94    procedure Copy1Click(Sender: TObject);
95    procedure Paste1Click(Sender: TObject);
96    procedure Find1Click(Sender: TObject);
97    procedure FindDialog1Find(Sender: TObject);
98    procedure AAPref1Click(Sender: TObject);
99    procedure FormDestroy(Sender: TObject);
100  private
101    { Private declarations }
102    {$ifndef standalonetrainerwithassembler}
103    AAHighlighter: TSynAASyn;
104    CPPHighlighter: TSynCppSyn;
105    assembleSearch: TSynEditSearch;
106    {$endif}
107
108    updating: boolean;
109    pagecontrol: tpagecontrol;
110    oldtabindex: integer;
111    scripts: array of record
112               script: string;
113               filename: string;
114               undoscripts: array [0..4] of record
115                              oldscript: string;
116                              startpos: integer;
117                            end;
118               currentundo: integer;
119             end;
120             
121    selectedtab: integer;
122
123    fcplusplus: boolean;
124
125    undolist: array [0..5] of string;
126    procedure setcplusplus(state: boolean);
127    procedure injectscript(createthread: boolean);
128  public
129    { Public declarations }
130    {$ifndef standalonetrainerwithassembler}
131    assemblescreen: TSynEditFix;
132    {$endif}
133    editscript: boolean;
134    editscript2: boolean;
135    callbackroutine: procedure(script: string; changed: boolean) of object;
136    injectintomyself: boolean;
137    property cplusplus: boolean read fcplusplus write setcplusplus;
138  end;
139
140  procedure Getjumpandoverwrittenbytes(address,addressto: dword; jumppart,originalcodepart: tstrings);
141  procedure generateAPIHookScript(script: tstrings; address: string; addresstogoto: string; addresstostoreneworiginalfunction: string=''; nameextension:string='0');
142
143implementation
144
145{$R *.dfm}
146
147{$ifndef standalonetrainerwithassembler}
148uses frmAAEditPrefsUnit,memorybrowserformunit,APIhooktemplatesettingsfrm,{$ifdef net}unit2{$else}mainunit{$endif};
149{$endif}
150
151procedure TSynEditFix.PasteFromClipboard;
152begin
153  inherited;
154  repaint;
155end;
156
157procedure TfrmAutoInject.setcplusplus(state: boolean);
158begin
159{$ifndef standalonetrainerwithassembler}
160  fcplusplus:=state;
161  if state then
162  begin
163    assemblescreen.Highlighter:=CPPHighlighter;
164
165    //change gui to c++ style
166    button1.Caption:='Execute script';
167    opendialog1.DefaultExt:='CEC';
168    opendialog1.Filter:='Cheat Engine Script (*.CEC)|*.CEC|All Files (*.*)|*.*';
169    savedialog1.DefaultExt:='CEC';
170    savedialog1.Filter:='Cheat Engine Script (*.CEC)|*.CEC|All Files (*.*)|*.*';
171    Assigntocurrentcheattable1.visible:=false;
172    emplate1.Visible:=false;
173    caption:='Script engine';
174    inject1.Visible:=true;
175    helpcontext:=19; //c-script help
176  end
177  else
178  begin
179    assemblescreen.Highlighter:=AAHighlighter;
180
181
182    //change gui to autoassembler style
183    button1.caption:='Write code';
184    opendialog1.DefaultExt:='CEA';
185    opendialog1.Filter:='Cheat Engine Assembly (*.CEA)|*.CEA|All Files (*.*)|*.*';
186    savedialog1.DefaultExt:='CES';
187    savedialog1.Filter:='Cheat Engine Assembly (*.CEA)|*.CEA|All Files (*.*)|*.*';
188    Assigntocurrentcheattable1.Visible:=true;
189    emplate1.Visible:=true;
190    caption:='Auto assembler';
191    inject1.Visible:=false;
192    helpcontext:=18; //auto asm help
193  end;
194{$endif}
195end;
196
197
198procedure TfrmAutoInject.Button1Click(Sender: TObject);
199var enable,disable: integer;
200    a,b: integer;
201
202    aa: TCEAllocArray;
203    i: integer;
204
205    //variables for injectintomyself:
206    check: boolean;
207    oldProcessID: dword;
208    oldProcessHandle: thandle;
209begin
210{$ifndef standalonetrainerwithassembler}
211  if cplusplus then
212  begin
213    //scriptengine stuff
214    if not editscript and scriptengine.beginScript then
215    begin
216      try
217       // for i:=0 to assemblescreen.Lines.Count-1 do
218          if not scriptengine.execute_command(assemblescreen.text) then
219            raise exception.Create('Error interpreting script:'+scriptengine.getError);
220
221
222
223      finally
224        scriptengine.endScript;
225      end;
226
227      showmessage('script executed');
228    end;
229
230
231  end
232  else
233  begin
234    if editscript then
235    begin
236      //check if both scripts are valid before allowing the edit
237
238      setlength(aa,1);
239      getenableanddisablepos(assemblescreen.Lines,a,b);
240      if (a=-1) and (b=-1) then raise exception.create('The code needs an [ENABLE] and a [DISABLE] section if you want to use this script as a table entry');
241
242      check:=autoassemble(assemblescreen.lines,false,true,true,injectintomyself,aa) and
243             autoassemble(assemblescreen.lines,false,false,true,injectintomyself,aa);
244
245      if check then
246      begin
247        modalresult:=mrok; //not modal anymore, but can still be used to pass info
248        if editscript2 then close; //can only be used when not modal
249      end
250      else
251      begin
252        if messagedlg('Not all code is injectable. Are you sure you wan''t to edit it to this?',mtWarning,[mbyes,mbno],0)=mryes then
253        begin
254          modalresult:=mrok; //not modal anymore, but can still be used to pass info
255          if editscript2 then close;
256        end;
257      end;
258    end else autoassemble(assemblescreen.lines,true);
259  end;
260{$endif}
261end;
262
263procedure TfrmAutoInject.Load1Click(Sender: TObject);
264begin
265{$ifndef standalonetrainerwithassembler}
266  if opendialog1.Execute then
267  begin
268    assemblescreen.Clear;
269    assemblescreen.Lines.LoadFromFile(opendialog1.filename);
270    savedialog1.FileName:=opendialog1.filename;
271  end;
272{$endif}
273end;
274
275procedure TfrmAutoInject.Save1Click(Sender: TObject);
276var f: tfilestream;
277    s: string;
278begin
279{$ifndef standalonetrainerwithassembler}
280  if (savedialog1.filename='') and (not savedialog1.Execute) then exit;   //filename was empty and the user clicked cancel
281
282  f:=tfilestream.Create(savedialog1.filename,fmcreate);
283  try
284    s:=assemblescreen.text;
285    f.Write(s[1],length(assemblescreen.text));
286  finally
287    f.Free;
288  end;
289{$endif}
290end;
291
292procedure TfrmAutoInject.Exit1Click(Sender: TObject);
293begin
294  close;
295end;
296
297procedure TfrmAutoInject.FormClose(Sender: TObject;
298  var Action: TCloseAction);
299begin
300{$ifndef standalonetrainerwithassembler}
301  if not editscript then
302  begin
303    action:=cafree;
304  end
305  else
306  begin
307    if editscript2 then
308    begin
309      //call finish routine with script
310
311      if modalresult=mrok then
312        callbackroutine(assemblescreen.text,true)
313      else
314        callbackroutine(assemblescreen.text,false);
315
316      action:=cafree;
317    end;
318  end;
319{$endif}
320end;
321
322procedure TfrmAutoInject.Codeinjection1Click(Sender: TObject);
323function inttostr(i:int64):string;
324begin
325  if i=0 then result:='' else result:=sysutils.IntToStr(i);
326end;
327
328var address: string;
329    addressdw: dword;
330    originalcode: array of string;
331    originalbytes: array of byte;
332    codesize: integer;
333    a,b: dword;
334    x: string;
335    i,j,k: integer;
336    prev_usesymbols: boolean;
337    injectnr: integer;
338
339    enablepos: integer;
340    disablepos: integer;
341    enablecode: tstringlist;
342    disablecode: tstringlist;
343begin
344{$ifndef standalonetrainerwithassembler}
345  a:=memorybrowser.disassemblerview.SelectedAddress;
346
347  address:=inttohex(a,8);
348  if inputquery('Code inject template','On what address do you want the jump?',address) then
349  begin
350    try
351      a:=strtoint('$'+address);
352    except
353
354      a:=symhandler.getaddressfromname(address);
355
356    end;
357
358    b:=a;
359
360    injectnr:=0;
361    for i:=0 to assemblescreen.Lines.Count-1 do
362    begin
363      j:=pos('alloc(newmem',lowercase(assemblescreen.lines[i]));
364      if j<>0 then
365      begin
366        x:=copy(assemblescreen.Lines[i],j+12,length(assemblescreen.Lines[i]));
367        x:=copy(x,1,pos(',',x)-1);
368        try
369          k:=strtoint(x);
370          if injectnr<=k then
371            injectnr:=k+1;
372        except
373          inc(injectnr);
374        end;
375      end;
376    end;
377
378
379    //disassemble the old code
380    setlength(originalcode,0);
381    codesize:=0;
382
383    while codesize<5 do
384    begin
385      setlength(originalcode,length(originalcode)+1);
386      originalcode[length(originalcode)-1]:=disassemble(a,x);
387      i:=posex('-',originalcode[length(originalcode)-1]);
388      i:=posex('-',originalcode[length(originalcode)-1],i+1);
389      originalcode[length(originalcode)-1]:=copy(originalcode[length(originalcode)-1],i+2,length(originalcode[length(originalcode)-1]));
390      codesize:=a-b;
391    end;
392
393    setlength(originalbytes,codesize);
394    ReadProcessMemory(processhandle, pointer(b), @originalbytes[0], codesize, a);
395
396    enablecode:=tstringlist.Create;
397    disablecode:=tstringlist.Create;
398    try
399      with enablecode do
400      begin
401        add('alloc(newmem'+inttostr(injectnr)+',2048) //2kb should be enough');
402        add('label(returnhere'+inttostr(injectnr)+')');
403        add('label(originalcode'+inttostr(injectnr)+')');
404        add('label(exit'+inttostr(injectnr)+')');
405        add('');
406        add(address+':');
407        add('jmp newmem'+inttostr(injectnr)+'');
408        while codesize>5 do
409        begin
410          add('nop');
411          dec(codesize);
412        end;
413
414        add('returnhere'+inttostr(injectnr)+':');
415        add('');
416        add('newmem'+inttostr(injectnr)+': //this is allocated memory, you have read,write,execute access');
417        add('//place your code here');
418
419        add('');
420        add('');
421        add('originalcode'+inttostr(injectnr)+':');
422        for i:=0 to length(originalcode)-1 do
423          add(originalcode[i]);
424        add('');
425        add('exit'+inttostr(injectnr)+':');
426        add('jmp returnhere'+inttostr(injectnr)+'');
427      end;
428
429      with disablecode do
430      begin
431        add('dealloc(newmem'+inttostr(injectnr)+')');
432        add(address+':');
433        for i:=0 to length(originalcode)-1 do
434          add(originalcode[i]);
435        x:='db';
436        for i:=0 to length(originalbytes)-1 do
437          x:=x+' '+inttohex(originalbytes[i],2);
438        add('//Alt: '+x);
439      end;
440
441      getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
442      //skip first comment(s)
443      if enablepos>=0 then
444      begin
445        while enablepos<assemblescreen.lines.Count-1 do
446        begin
447          if pos('//',trim(assemblescreen.Lines[enablepos+1]))=1 then inc(enablepos) else break;
448        end;
449      end;
450
451      for i:=enablecode.Count-1 downto 0 do
452        assemblescreen.Lines.Insert(enablepos+1,enablecode[i]);
453
454      getenableanddisablepos(assemblescreen.lines,enablepos,disablepos);
455      //skip first comment(s)
456      if disablepos>=0 then
457      begin
458        while disablepos<assemblescreen.lines.Count-1 do
459        begin
460          if pos('//',trim(assemblescreen.Lines[disablepos+1]))=1 then inc(enablepos) else break;
461            inc(disablepos);
462        end;
463        //only if there actually is a disable section place this code
464        for i:=disablecode.Count-1 downto 0 do
465          assemblescreen.Lines.Insert(disablepos+1,disablecode[i]);
466      end;
467    finally
468      enablecode.free;
469      disablecode.Free;
470    end;
471
472  end;
473
474{$endif}
475end;
476
477procedure TfrmAutoInject.Panel1Resize(Sender: TObject);
478begin
479  button1.Left:=panel1.Width div 2-button1.Width div 2;
480end;
481
482
483procedure TfrmAutoInject.CheatTablecompliantcodee1Click(Sender: TObject);
484var e,d: integer;
485begin
486{$ifndef standalonetrainerwithassembler}
487  getenableanddisablepos(assemblescreen.lines,e,d);
488
489  if e=-1 then //-2 is 2 or more, so bugged, and >=0 is has one
490  begin
491    assemblescreen.Lines.Insert(0,'[ENABLE]');
492    assemblescreen.Lines.Insert(1,'//code from here to ''[DISABLE]'' will be used to enable the cheat');
493    assemblescreen.Lines.Insert(2,'');
494  end;
495
496  if d=-1 then
497  begin
498    assemblescreen.Lines.Add(' ');
499    assemblescreen.Lines.Add(' ');
500    assemblescreen.Lines.Add('[DISABLE]');
501    assemblescreen.Lines.Add('//code from here till the end of the code will be used to disable the cheat');
502  end;
503{$endif} 
504end;
505
506procedure TfrmAutoInject.assemblescreenChange(Sender: TObject);
507{$ifndef standalonetrainerwithassembler}
508{
509var
510  TempMS: TMemoryStream;
511  FSyntax: TpsvAARTF;
512  FSyntax2: TpsvCppRTF;
513  pos, top: Integer;
514  OnChange: TNotifyEvent;
515  }
516{$endif}
517begin
518
519{$ifndef standalonetrainerwithassembler}
520{  undotimer.enabled:=false;
521  undotimer.enabled:=true; //if no change for 2 seconds the script gets stored
522
523  if (Length(assemblescreen.Text) <= 0) then
524    exit;
525
526
527  assemblescreen.Lines.BeginUpdate;
528  pos := assemblescreen.selstart;
529  top := SendMessage(assemblescreen.Handle, EM_GETFIRSTVISIBLELINE, 0, 0);
530  OnChange := assemblescreen.OnChange;
531  TempMS := TMemoryStream.Create;
532
533  assemblescreen.OnChange := nil;
534
535
536
537  try
538    if fcplusplus then
539      FSyntax2 := TpsvCppRTF.Create
540    else
541      FSyntax := TpsvAARTF.Create;
542     
543    try
544
545      try
546
547        if cplusplus then
548        begin
549          FSyntax2.SetText(assemblescreen.Text);
550          FSyntax2.ConvertToRTFStream(TempMS);
551        end
552        else
553        begin
554          FSyntax.SetText(assemblescreen.Text);
555          FSyntax.ConvertToRTFStream(TempMS);
556        end;
557
558        TempMS.Position := 0;
559        assemblescreen.PlainText := False;
560
561
562        assemblescreen.Lines.LoadFromStream(TempMS);
563        SendMessage(assemblescreen.Handle, EM_LINESCROLL, 0, top);
564       
565      finally
566        if fcplusplus then
567          fsyntax2.free
568        else
569          FSyntax.Free;
570      end;
571
572
573    except
574      assemblescreen.SelAttributes := assemblescreen.DefAttributes;
575    end;
576
577  finally
578    assemblescreen.PlainText := True;
579    assemblescreen.SelStart := Pos;
580
581    TempMS.Free;
582    assemblescreen.Lines.EndUpdate;
583    assemblescreen.OnChange := OnChange;
584  end;   }
585{$endif}
586
587end;
588
589
590
591procedure TfrmAutoInject.Assigntocurrentcheattable1Click(Sender: TObject);
592var a,b: integer;
593    aa:TCEAllocArray;
594    registeredsymbols: TStringlist;
595begin
596{$ifndef standalonetrainerwithassembler}
597  {$ifndef net}
598  registeredsymbols:=tstringlist.Create;
599  registeredsymbols.CaseSensitive:=false;
600  registeredsymbols.Duplicates:=dupIgnore;
601 
602  try
603    setlength(aa,0);
604    getenableanddisablepos(assemblescreen.Lines,a,b);
605    if (a=-1) and (b=-1) then raise exception.create('The code needs a [ENABLE] and a [DISABLE] section if you want to add it to a table');
606
607    if autoassemble(assemblescreen.lines,false,true,true,false,aa,registeredsymbols) and
608       autoassemble(assemblescreen.lines,false,false,true,false,aa,registeredsymbols) then
609    begin
610      //add a entry with type 255
611      mainform.AddAutoAssembleScript(assemblescreen.text);
612
613
614    end
615    else showmessage('Failed to add to table. Not all code is injectable');
616  finally
617    registeredsymbols.Free;
618  end;
619  {$endif}
620  {$endif}
621end;
622
623procedure Getjumpandoverwrittenbytes(address,addressto: dword; jumppart,originalcodepart: tstrings);
624//pre: jumppart and originalcodepart are declared objects
625var x,y: dword;
626    z: string;
627    i: integer;
628begin
629{$ifndef standalonetrainerwithassembler}
630  x:=address;
631  y:=address;
632
633  while x-y<5 do
634  begin
635    z:=disassemble(x);
636    z:=copy(z,pos('-',z)+1,length(z));
637    z:=copy(z,pos('-',z)+1,length(z));
638
639    originalcodepart.add(z);
640  end;
641
642  jumppart.Add('jmp '+inttohex(addressto,8));
643
644  for i:=5 to x-y-1 do
645    jumppart.Add('nop');
646{$endif}
647end;
648
649
650procedure generateAPIHookScript(script: tstrings; address: string; addresstogoto: string; addresstostoreneworiginalfunction: string=''; nameextension:string='0');
651var originalcode: array of string;
652    i: integer;
653    codesize: integer;
654    a,b: dword;
655    x: string;
656
657    enablepos,disablepos: integer;
658    disablescript: tstringlist;
659    enablescript: tstringlist;
660
661    originalcodebuffer: Pbytearray;
662begin
663{$ifndef standalonetrainerwithassembler}
664  //disassemble the old code
665  setlength(originalcode,0);
666
667
668
669  try
670    a:=symhandler.getAddressFromName(address);
671  except
672    on e: exception do
673      raise exception.create(address+':'+e.message);
674  end;
675
676  try
677    b:=symhandler.getAddressFromName(addresstogoto);
678  except
679    on e: exception do
680      raise exception.create(addresstogoto+':'+e.message);
681  end;
682
683  disablescript:=tstringlist.Create;
684  enablescript:=tstringlist.Create;
685
686
687  codesize:=0;
688  b:=a;
689  while codesize<5 do
690  begin
691    setlength(originalcode,length(originalcode)+1);
692    originalcode[length(originalcode)-1]:=disassemble(a,x);
693    i:=posex('-',originalcode[length(originalcode)-1]);
694    i:=posex('-',originalcode[length(originalcode)-1],i+1);
695    originalcode[length(originalcode)-1]:=copy(originalcode[length(originalcode)-1],i+2,length(originalcode[length(originalcode)-1]));
696    codesize:=a-b;
697  end;
698
699  getmem(originalcodebuffer,codesize);
700  if ReadProcessMemory(processhandle,pointer(b), originalcodebuffer, codesize, a) then
701  begin
702    disablescript.Add(address+':');
703    x:='db';
704
705    for i:=0 to a-1 do
706      x:=x+' '+inttohex(originalcodebuffer[i],2);
707
708    disablescript.Add(x);     
709  end;
710
711  freemem(originalcodebuffer);
712
713
714
715  with enablescript do
716  begin
717    add('alloc(originalcall'+nameextension+',2048) //2kb should be enough');
718    add('label(returnhere'+nameextension+')');
719    add('');
720    if addresstostoreneworiginalfunction<>'' then
721    begin
722      add(addresstostoreneworiginalfunction+':');
723      add('dd originalcall'+nameextension);
724    end;
725    add('');
726    add('originalcall'+nameextension+':');
727
728    for i:=0 to length(originalcode)-1 do
729      add(originalcode[i]);
730    add('jmp returnhere'+nameextension+'');
731
732    add('');
733   
734    add(address+':');
735    add('jmp '+addresstogoto);
736    while codesize>5 do
737    begin
738      add('nop');
739      dec(codesize);
740    end;
741    add('returnhere'+nameextension+':');
742
743    add('');
744  end;
745
746
747  getenableanddisablepos(script,enablepos,disablepos);
748
749  if disablepos<>-1 then
750  begin
751    for i:=0 to disablescript.Count-1 do
752      script.Insert(disablepos+i+1,disablescript[i]);
753  end;
754
755  getenableanddisablepos(script,enablepos,disablepos); //idiots putting disable first
756
757  if enablepos<>-1 then
758  begin
759    for i:=0 to enablescript.Count-1 do
760      script.Insert(enablepos+i+1,enablescript[i]);
761  end
762  else
763    script.AddStrings(enablescript);
764
765  disablescript.free;
766  enablescript.free;
767 
768{$endif}
769end;
770
771
772
773procedure TfrmAutoInject.APIHook1Click(Sender: TObject);
774function inttostr(i:int64):string;
775begin
776  if i=0 then result:='' else result:=sysutils.IntToStr(i);
777end;
778
779var address: string;
780    addressdw: dword;
781    originalcode: array of string;
782    codesize: integer;
783    a,b,c: dword;
784    x: string;
785    i,j,k: integer;
786    prev_usesymbols: boolean;
787    injectnr: integer;
788
789begin
790{$ifndef standalonetrainerwithassembler}
791  a:=memorybrowser.disassemblerview.SelectedAddress;
792
793  address:=inttohex(a,8);
794
795  with tfrmapihooktemplatesettings.create(self) do
796//  if inputquery('Give the address of the api you want to hook',address) and inputquery('Give the address of the replacement function',address) then
797  begin
798    try
799      injectnr:=0;
800      for i:=0 to assemblescreen.Lines.Count-1 do
801      begin
802        j:=pos('alloc(newmem',lowercase(assemblescreen.lines[i]));
803        if j<>0 then
804        begin
805          x:=copy(assemblescreen.Lines[i],j+12,length(assemblescreen.Lines[i]));
806          x:=copy(x,1,pos(',',x)-1);
807          try
808            k:=strtoint(x);
809            if injectnr<=k then
810              injectnr:=k+1;
811          except
812            inc(injectnr);
813          end;
814        end;
815      end;
816
817      edit1.text:=address;
818      if showmodal<>mrok then exit;
819
820
821      generateAPIHookScript(assemblescreen.Lines,edit1.Text, edit2.Text, edit3.Text, inttostr(injectnr));
822
823
824    finally
825      free;
826    end;
827  end;
828
829{$endif}
830end;
831
832procedure TfrmAutoInject.SaveAs1Click(Sender: TObject);
833begin
834  if savedialog1.Execute then
835    save1.Click;   
836end;
837
838procedure TfrmAutoInject.FormShow(Sender: TObject);
839begin
840{$ifndef standalonetrainerwithassembler}
841  if editscript then
842    button1.Caption:=strOK;
843
844  assemblescreen.SetFocus;
845{$endif}
846end;
847
848procedure TfrmAutoInject.assemblescreenKeyDown(Sender: TObject;
849  var Key: Word; Shift: TShiftState);
850begin
851{   if (ssCtrl in Shift) and (key=ord('A'))  then
852   begin
853     TMemo(Sender).SelectAll;
854     Key := 0;
855   end; }
856end;
857
858procedure TfrmAutoInject.Coderelocation1Click(Sender: TObject);
859var starts,stops: string;
860    start,stop,current,x: dword;
861    i,j: integer;
862
863    labels: tstringlist;
864    output: tstringlist;
865    s: string;
866
867    a,b: string;
868    prev: dword;
869
870    ok: boolean;
871
872begin
873{$ifndef standalonetrainerwithassembler}
874  starts:=inttohex(memorybrowser.disassemblerview.SelectedAddress,8);
875  stops:=inttohex(memorybrowser.disassemblerview.SelectedAddress+128,8);
876
877  if inputquery('Start address:','Code relocation template',starts) then
878  begin
879    start:=strtoint('$'+starts);
880    if inputquery('End address (last bytes are included if necesary)','Code relocation template',stops) then
881    begin
882      stop:=strtoint('$'+stops);
883
884      output:=tstringlist.Create;
885      labels:=tstringlist.create;
886      labels.Duplicates:=dupIgnore;
887      labels.Sorted:=true;
888     
889      output.add('alloc(newmem,'+inttostr(abs(integer(stop-start))*2)+')');
890      output.add('');
891      output.add('newmem:');
892
893
894      try
895        current:=start;
896
897        while current<stop do
898        begin
899          prev:=current;
900          s:=disassemble(current);
901          i:=posex('-',s);
902          i:=posex('-',s,i+1);
903          s:=copy(s,i+2,length(s));
904
905          i:=pos(' ',s);
906          a:=copy(s,1,i-1);
907          b:=copy(s,i+1,length(s));
908
909
910          if length(a)>1 then
911          begin
912            if (lowercase(a)='loop') or (lowercase(a[1])='j') or (lowercase(a)='call') then
913            begin
914              try
915                x:=symhandler.getAddressFromName(b);
916                if (x>=start) and (x<=stop) then
917                begin
918                  labels.Add('orig_'+inttohex(x,8));
919                  s:=a+' orig_'+inttohex(x,8);
920                end;
921              except
922                //nolabel
923              end;
924            end;
925          end;
926
927          output.add('orig_'+inttohex(prev,8)+':');
928          output.add(s);
929        end;
930
931        labels.Sort;
932        //now clean up output so that the result is a readable program
933        for i:=0 to labels.Count-1 do
934          output.Insert(2+i,'label('+labels[i]+')');
935
936        output.Insert(2+labels.Count,'');
937
938        i:=2+labels.Count+1;
939        while i<output.Count do
940        begin
941          if pos('orig_',output[i])>0 then
942          begin
943            //determine if it's valid or not
944            ok:=false;
945            for j:=0 to labels.Count-1 do
946              if labels[j]+':'=output[i] then
947              begin
948                ok:=true;
949                break;
950              end;
951
952            if not ok then
953              output.Delete(i)
954            else
955            begin
956              output.Insert(i,'');
957              inc(i,2);
958            end;
959          end
960          else inc(i);
961        end;
962
963        assemblescreen.Lines.AddStrings(output);
964
965      finally
966        output.free;
967      end;
968
969    end;
970
971  end;
972{$endif}
973end;
974
975procedure TfrmAutoInject.New1Click(Sender: TObject);
976begin
977{$ifndef standalonetrainerwithassembler}
978  scripts[length(scripts)-1].script:=assemblescreen.Text;
979  setlength(scripts,length(scripts)+1);
980
981  scripts[length(scripts)-1].script:='';
982  scripts[length(scripts)-1].undoscripts[0].oldscript:='';
983  scripts[length(scripts)-1].currentundo:=0;
984
985  assemblescreen.Text:='';
986
987  if length(scripts)=2 then //first time new
988    tabcontrol1.Tabs.Add('Script 1');
989
990  tabcontrol1.Tabs.Add('Script '+inttostr(length(scripts)));
991  tabcontrol1.TabIndex:=length(scripts)-1;
992  oldtabindex:=tabcontrol1.TabIndex;
993{$endif}
994end;
995
996procedure TfrmAutoInject.FormCreate(Sender: TObject);
997begin
998{$ifndef standalonetrainerwithassembler}
999  setlength(scripts,1);
1000  scripts[0].currentundo:=0;
1001  oldtabindex:=0;
1002{  assemblescreen.SelStart:=0;
1003  assemblescreen.SelLength:=0; }
1004
1005  AAHighlighter:=TSynAASyn.Create(self);
1006  CPPHighlighter:=TSynCppSyn.create(self);
1007  assembleSearch:=TSyneditSearch.Create(self);
1008
1009
1010  assemblescreen:=TSynEditFix.Create(self);
1011  assemblescreen.Highlighter:=AAHighlighter;
1012  assemblescreen.SearchEngine:=assembleSearch;
1013  assemblescreen.Options:=SYNEDIT_DEFAULT_OPTIONS;
1014  assemblescreen.WantTabs:=true;
1015  assemblescreen.TabWidth:=2;
1016
1017
1018  assemblescreen.Gutter.Visible:=true;
1019  assemblescreen.Gutter.ShowLineNumbers:=true;
1020  assemblescreen.Gutter.LeftOffset:=1;
1021  assemblescreen.Gutter.RightOffset:=1;
1022  assemblescreen.Gutter.DigitCount:=3;
1023
1024  assemblescreen.Align:=alClient;
1025  assemblescreen.PopupMenu:=PopupMenu1;
1026  assemblescreen.Parent:=tabcontrol1;
1027{$endif}
1028end;
1029
1030procedure TfrmAutoInject.TabControl1Change(Sender: TObject);
1031begin
1032{$ifndef standalonetrainerwithassembler}
1033  scripts[oldtabindex].script:=assemblescreen.text;
1034  scripts[oldtabindex].filename:=opendialog1.FileName;
1035
1036  assemblescreen.text:=scripts[TabControl1.TabIndex].script;
1037  opendialog1.FileName:=scripts[TabControl1.TabIndex].filename;
1038
1039  oldtabindex:=tabcontrol1.TabIndex;
1040{$endif}
1041end;
1042
1043procedure TfrmAutoInject.Syntaxhighlighting1Click(Sender: TObject);
1044var s: string;
1045begin
1046{$ifndef standalonetrainerwithassembler}
1047  Syntaxhighlighting1.checked:=not Syntaxhighlighting1.checked;
1048  if Syntaxhighlighting1.checked then //enable
1049    assemblescreen.Highlighter:=AAHighlighter
1050  else //disabl
1051    assemblescreen.Highlighter:=nil;
1052{$endif}
1053end;
1054
1055procedure TfrmAutoInject.TabControl1ContextPopup(Sender: TObject;
1056  MousePos: TPoint; var Handled: Boolean);
1057begin
1058  //selectedtab:=TabControl1.IndexOfTabAt(mousepos.x,mousepos.y);
1059  //closemenu.Popup(mouse.CursorPos.X,mouse.cursorpos.Y);   
1060end;
1061
1062procedure TfrmAutoInject.Close1Click(Sender: TObject);
1063var i: integer;
1064begin
1065{$ifndef standalonetrainerwithassembler}
1066  if messagedlg('Are you sure you want to close '+TabControl1.Tabs[selectedtab]+' ?',mtConfirmation,[mbyes,mbno],0)=mryes then
1067  begin
1068    scripts[oldtabindex].script:=assemblescreen.text; //save current script
1069    tabcontrol1.Tabs.Delete(selectedtab);
1070
1071    for i:=selectedtab to length(scripts)-2 do
1072      scripts[i]:=scripts[i+1];
1073
1074    setlength(scripts,length(scripts)-1);
1075
1076    if oldtabindex=selectedtab then //it was the current one
1077    begin
1078      oldtabindex:=length(scripts)-1;
1079      tabcontrol1.TabIndex:=oldtabindex;
1080      assemblescreen.text:=scripts[oldtabindex].script;
1081      assemblescreen.OnChange(assemblescreen);
1082    end;
1083
1084    if (length(scripts)=1) then
1085      tabcontrol1.Tabs.Delete(0);
1086
1087//    tabcontrol1.tabs[selectedtab]
1088
1089  end;
1090{$endif}
1091end;
1092
1093procedure TfrmAutoInject.injectscript(createthread: boolean);
1094var i: integer;
1095    setenvscript: tstringlist;
1096    CEAllocArray: TCEAllocArray;
1097    callscriptscript: tstringlist;
1098
1099    totalmem: dword;
1100    totalwritten: dword;
1101    address: pointer;
1102    mi: TModuleInfo;
1103    hasjustloadedundercdll: boolean;
1104
1105    aawindowwithstub: tfrmautoinject;
1106    setenv_done: dword;
1107    setenv_done_value: dword;
1108    s: string;
1109
1110    ignore: dword;
1111    th: thandle;
1112begin
1113{$ifndef standalonetrainerwithassembler}
1114  //this will inject the script dll and generate a assembler script the user can use to call the script
1115  //first set the environment var for uc_home
1116  s:=assemblescreen.text;
1117  if not symhandler.getmodulebyname('undercdll.dll',mi) then
1118  begin
1119    //dll was not loaded yet
1120
1121    setenvscript:=tstringlist.Create;
1122
1123    with setenvscript do
1124    begin
1125      add('[enable]');
1126      Add('alloc(envname,8)');
1127      add('alloc(envvar,512)');
1128      add('alloc(myscript,512)');
1129
1130      add('envname:');
1131      add('db ''UC_HOME'',0');
1132      add('envvar:');
1133      add('db '''+cheatenginedir+''' ,0');
1134      add('myscript:');
1135      add('push envvar');
1136      add('push envname');
1137      add('call SetEnvironmentVariableA');
1138      add('ret');
1139
1140      //cleanup part:
1141      add('[disable]');
1142      add('dealloc(myscript)');
1143      add('dealloc(envvar)');
1144      add('dealloc(envname)');
1145    end;
1146
1147    setlength(CEAllocArray,1);
1148    if autoassemble(setenvscript,false,true,false,false,CEAllocArray) then //enabled
1149    begin
1150      for i:=0 to length(ceallocarray)-1 do
1151        if ceallocarray[i].varname='myscript' then
1152        begin
1153          th:=createremotethread(processhandle,nil,0,pointer(ceallocarray[i].address),nil,0,ignore);
1154          if th<>0 then
1155            waitforsingleobject(th,4000); //4 seconds max
1156           
1157          break;
1158        end;
1159
1160
1161
1162      //wait done
1163      autoassemble(setenvscript,false,false,false,false,CEAllocArray); //disable for the deallocs
1164    end;
1165
1166    setenvscript.free;
1167
1168
1169    injectdll(cheatenginedir+'undercdll.dll','');
1170    symhandler.reinitialize;
1171    hasjustloadedundercdll:=true;
1172  end else hasjustloadedundercdll:=false;
1173
1174  //now allocate memory for the script and write it to there
1175  totalmem:=length(assemblescreen.text);
1176  address:=VirtualAllocEx(processhandle,nil,totalmem+512,mem_commit,page_execute_readwrite);
1177  if address=nil then raise exception.create('Failed allocating memory for the script');
1178  if not WriteProcessMemory(processhandle,address,@s[1],totalmem,totalwritten) then
1179    raise exception.create('failed writing the script to the process');
1180
1181
1182
1183  callscriptscript:=tstringlist.create;
1184  try
1185    with callscriptscript do
1186    begin
1187      add('label(result)');
1188      add(inttohex((dword(address)+totalmem+$20) - (dword(address) mod $10),8)+':');
1189      add('pushfd');
1190      add('pushad');
1191      add('push '+inttohex(dword(address),8));
1192      add('call underc_executescript');
1193      add('mov [result],eax');
1194      add('popad');
1195      add('popfd');
1196      add('mov eax,[result]');
1197      add('ret');
1198      add('result:');
1199      add('dd 0');
1200    end;
1201
1202    if hasjustloadedundercdll then
1203    begin
1204      //lets wait before injecting the callscript script
1205      symhandler.waitforsymbolsloaded;
1206      if not symhandler.getmodulebyname('undercdll.dll',mi) then
1207        raise exception.Create('Failure loading undercdll');
1208    end;
1209    if not autoassemble(callscriptscript,false,true,false,false,CEAllocArray) then raise exception.Create('Failed creating calling stub for script located at address '+inttohex(dword(address),8));
1210  finally
1211    callscriptscript.free;
1212  end;
1213
1214  aawindowwithstub:=tfrmautoinject.create(memorybrowser);
1215  with aawindowwithstub.assemblescreen.Lines do
1216  begin
1217    if createthread then
1218    begin
1219      add('createthread(myscript)');
1220      add('alloc(myscript,256)');
1221      add('myscript:');
1222    end;
1223
1224    add('//Call this code to execute the script from assembler');
1225    add('call '+inttohex((dword(address)+totalmem+$20) - (dword(address) mod $10),8));
1226    add('');
1227    add('//eax==0 when successfully executed');
1228    add('//''call underc_geterror'' to get a pointer to the last generated error buffer');
1229
1230    if createthread then
1231      add('ret //interesing thing with createthread is that the return param points to exitthread');
1232  end;
1233  aawindowwithstub.show;
1234{$endif}
1235end;
1236
1237
1238
1239procedure TfrmAutoInject.Injectincurrentprocess1Click(Sender: TObject);
1240begin
1241  injectscript(false);
1242
1243
1244end;
1245
1246procedure TfrmAutoInject.Injectintocurrentprocessandexecute1Click(
1247  Sender: TObject);
1248begin
1249  injectscript(true);
1250end;
1251
1252procedure TfrmAutoInject.Cut1Click(Sender: TObject);
1253begin
1254{$ifndef standalonetrainerwithassembler}
1255  assemblescreen.CutToClipboard;
1256{$endif}
1257end;
1258
1259procedure TfrmAutoInject.Copy1Click(Sender: TObject);
1260begin
1261{$ifndef standalonetrainerwithassembler}
1262  assemblescreen.CopyToClipboard;
1263{$endif}
1264end;
1265
1266procedure TfrmAutoInject.Paste1Click(Sender: TObject);
1267begin
1268{$ifndef standalonetrainerwithassembler}
1269  assemblescreen.PasteFromClipboard;
1270{$endif}
1271end;
1272
1273procedure TfrmAutoInject.Find1Click(Sender: TObject);
1274begin
1275  finddialog1.Execute;
1276
1277end;
1278
1279procedure TfrmAutoInject.FindDialog1Find(Sender: TObject);
1280var start,l: integer;
1281    p: integer;
1282begin
1283{$ifndef standalonetrainerwithassembler}
1284  //scan the text for the given text
1285  start:=assemblescreen.selstart;
1286  l:=length(assemblescreen.text)-start;
1287
1288
1289  assemblescreen.SearchReplace(finddialog1.FindText,'',[]);
1290{$endif}
1291end;
1292
1293//follow is just a emergency fix since undo is messed up. At least it's better than nothing
1294procedure TfrmAutoInject.AAPref1Click(Sender: TObject);
1295begin
1296{$ifndef standalonetrainerwithassembler}
1297  with TfrmAAEditPrefs.create(self) do
1298  begin
1299    try
1300      if execute(assemblescreen) then
1301      begin
1302        //save these settings
1303      end;
1304    finally
1305      free;
1306    end;
1307  end;
1308{$endif}
1309end;
1310
1311procedure TfrmAutoInject.FormDestroy(Sender: TObject);
1312begin
1313  if editscript or editscript2 then
1314  begin
1315    saveformposition(self,[]);
1316
1317  end;
1318end;
1319
1320end.
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
Note: See TracBrowser for help on using the browser.