ceplugin 0.6.0

Rust bindings to the Cheat Engine plugin SDK
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
#ifndef VMMHELPER_H_
#define VMMHELPER_H_

#include "common.h"
#include "vmreadwrite.h"
#include "vmxcontrolstructures.h"

extern volatile unsigned char *MSRBitmap;

unsigned long long vmmstart;
unsigned long long nextstack;
PPDPTE_PAE pagedirlvl4;
PPDPTE_PAE pagedirptrvirtual;
PPDE2MB_PAE pagedirvirtual; //wrong name, should be pagedir
PPDE2MB_PAE pagedirvirtual2;
PPDE2MB_PAE pagedirvirtual3;
PPDE2MB_PAE pagedirvirtual4;
PPDE2MB_PAE pagedirvirtual5;


int debugmode,breakpointset;
int globals_have_been_configured;


//global int 1 redirection vars
int int1redirection;
int int1redirection_idtbypass;
UINT64 int1redirection_idtbypass_cs;
UINT64 int1redirection_idtbypass_rip;

int int3redirection;
int int3redirection_idtbypass;
UINT64 int3redirection_idtbypass_cs;
UINT64 int3redirection_idtbypass_rip;

int int14redirection;
int int14redirection_idtbypass;
UINT64 int14redirection_idtbypass_cs;
UINT64 int14redirection_idtbypass_rip;


typedef struct _vmregisters /* DO NOT CHANGE THIS ORDER */
{
  UINT64         r15;
  UINT64         r14;
  UINT64         r13;
  UINT64         r12;
  UINT64         r11;
  UINT64         r10;
  UINT64         r9;
  UINT64         r8;
  UINT64         rbp;
  UINT64         rsi;
  UINT64         rdi;
  UINT64         rdx;
  UINT64         rcx;
  UINT64         rbx;
  UINT64         rax; //not valid in AMD
} VMRegisters;

#ifdef DEBUG
typedef struct _vmstate
{
  VMRegisters registers;
  UINT64 rsp;
  UINT64 rip;
  UINT64 rflags;
  WORD es;
  WORD cs;
  WORD ss;
  WORD ds;
  WORD fs;
  WORD gs;
  WORD ldtr;
  WORD tr;

  UINT64 es_base;
  UINT64 cs_base;
  UINT64 ss_base;
  UINT64 ds_base;
  UINT64 fs_base;
  UINT64 gs_base;
  UINT64 ldtr_base;
  UINT64 tr_base;

  unsigned long long efer;

  DWORD exit_reason;
  DWORD exit_interruptioninfo;
  DWORD exit_interruptionerror;
  DWORD idtvector_information;
  DWORD idtvector_error;

  //exit
  WORD exit_cs;
  WORD exit_ss;
  UINT64 exit_cs_base;
  UINT64 exit_ss_base;
  UINT64 exit_rip;
  UINT64 exit_rsp;
  UINT64 exit_rflags;

} VMState, *PVMState;

VMState vmstates[4];
int vmstates_pos;

#endif

typedef volatile struct _vmcb
{
	WORD InterceptCR0_15Read;
	WORD InterceptCR0_15Write;
	WORD InterceptDR0_15Read;
	WORD InterceptDR0_15Write;
	DWORD InterceptExceptions;
	union{
	  DWORD InstructionIntercept1;
	  struct {
	    unsigned InterceptINTR       :1;
      unsigned InterceptNMI        :1;
      unsigned InterceptSMI        :1;
      unsigned InterceptINIT       :1;
      unsigned InterceptVINTR      :1;
      unsigned InterceptCR0WritesThatChangeTSorMP        :1;
      unsigned InterceptIDTRRead       :1;
      unsigned InterceptGDTRRead       :1;
      unsigned InterceptLDTRRead       :1;
      unsigned InterceptTRRead         :1;
      unsigned InterceptIDTRWrite       :1;
      unsigned InterceptGDTRWrite       :1;
      unsigned InterceptLDTRWrite       :1;
      unsigned InterceptTRWrite       :1;
      unsigned InterceptRDTSC       :1;
      unsigned InterceptRDPMC       :1;

      unsigned InterceptPUSHF       :1;
      unsigned InterceptPOPF       :1;
      unsigned InterceptCPUID       :1;
      unsigned InterceptRSM       :1;
      unsigned InterceptIRET       :1;
      unsigned InterceptINT       :1;
      unsigned InterceptINVD       :1;
      unsigned InterceptPAUSE       :1;
      unsigned InterceptHLT       :1;
      unsigned InterceptINVLPG       :1;
      unsigned InterceptINVLPGA       :1;
      unsigned IOIO_PROT      :1;
      unsigned MSR_PROT       :1;
      unsigned InterceptTaskSwitches       :1;
      unsigned FERR_FREEZE       :1;
      unsigned InterceptShutdown       :1;

	  };
	};

	union{
	  DWORD InstructionIntercept2;
	  struct {
	    unsigned InterceptVMRUN      :1;
      unsigned InterceptVMMCALL        :1;
      unsigned InterceptVMLOAD        :1;
      unsigned InterceptVMSAVE      :1;
      unsigned InterceptSTGI      :1;
      unsigned InterceptCLGI       :1;
      unsigned InterceptSKINIT       :1;
      unsigned InterceptRDTSCP       :1;
      unsigned InterceptICEBP       :1;
      unsigned InterceptWBINVD         :1;
      unsigned InterceptMONITOR       :1;
      unsigned InterceptMWAIT       :1;
      unsigned InterceptMWAIT_IfArmed      :1;
      unsigned InterceptXSETBV       :1;
	  };
	};

	BYTE reserved1[40];
	WORD  PauseFilterThreshold; //3c = correct
	WORD  PauseFilterCount;
	QWORD IOPM_BASE_PA; //physical base address of IOPM
	QWORD MSRPM_BASE_PA;
	QWORD TSC_OFFSET;
	DWORD GuestASID; //58=correct
	BYTE  TLB_CONTROL;
	BYTE  reserved2[3];
	BYTE  V_TPR;  //60=correct
	unsigned V_IRQ : 1;
	unsigned reserved4: 7;
	unsigned V_INTR_PRIO: 4;
	unsigned V_IGN_TPR: 1;
	unsigned reserved5: 3;
	unsigned V_INTR_MASKING : 1;
	unsigned reserved6: 7;
	BYTE  V_INTR_VECTOR; //64=correct
	unsigned reserved6_1: 24;


	union{
	  QWORD InterruptShadow;
	  struct {
	    unsigned INTERRUPT_SHADOW :1;
	  };
	};

	QWORD EXITCODE; //70 correct
	QWORD EXITINFO1;
	QWORD EXITINFO2;
	QWORD EXITINTINFO;

	union{
	  QWORD Enable_Nested_Paging;  //90 correct
	  struct {
	    unsigned NP_ENABLE :1;
	  };
	};

	BYTE reserved7[16];

	//a8
	union {
	  QWORD EVENTINJ;
	  struct {
	    unsigned inject_Vector : 8;
	    unsigned inject_Type : 3;
	    unsigned inject_EV : 1;
	    unsigned reserved: 19;
	    unsigned inject_Valid: 1;
	    DWORD    inject_ERRORCODE;
	  };
	};
	QWORD N_CR3;

	union{
	  QWORD Enable_LBR_Virtualization;
	  struct {
	    unsigned LBR_VIRTUALIZATION_ENABLE: 1;
	  };
	};
	DWORD VMCB_CLEAN_BITS;
	DWORD reserved8;

	QWORD nRIP;  //c8
	BYTE NumberOfBytesFetched;
	BYTE GuestInstructionBytes[15];
	//E0
	BYTE reserved9[800];

	//400:
    //State Save Area
    WORD  es_selector;
    WORD  es_attrib;
    DWORD es_limit;
    QWORD es_base;

    WORD  cs_selector;
    WORD  cs_attrib;
    DWORD cs_limit;
    QWORD cs_base;

    WORD  ss_selector;
    WORD  ss_attrib;
    DWORD ss_limit;
    QWORD ss_base;

    WORD  ds_selector;
    WORD  ds_attrib;
    DWORD ds_limit;
    QWORD ds_base;

    WORD  fs_selector;
    WORD  fs_attrib;
    DWORD fs_limit;
    QWORD fs_base;

    WORD  gs_selector;
    WORD  gs_attrib;
    DWORD gs_limit;
    QWORD gs_base;

    WORD  gdtr_selector;
    WORD  gdtr_attrib;
    DWORD gdtr_limit;
    QWORD gdtr_base;

    WORD  ldtr_selector;
    WORD  ldtr_attrib;
    DWORD ldtr_limit;
    QWORD ldtr_base;

    WORD  idtr_selector;
    WORD  idtr_attrib;
    DWORD idtr_limit;
    QWORD idtr_base;

    WORD  tr_selector;
    WORD  tr_attrib;
    DWORD tr_limit;
    QWORD tr_base;

    BYTE  reserved10[43];
    BYTE  CPL;
    DWORD reserved11;
    QWORD EFER;

    BYTE reserved12[112];
    QWORD CR4;
    QWORD CR3;
    QWORD CR0;
    QWORD DR7;
    QWORD DR6;
    QWORD RFLAGS;
    QWORD RIP; //0x578

    BYTE reserved13[88];
    QWORD RSP;

    BYTE reserved14[24];
    QWORD RAX;
    QWORD STAR;
    QWORD LSTAR;
    QWORD CSTAR;
    QWORD SFMASK;
    QWORD KernelGsBase;
    QWORD SYSENTER_CS;
    QWORD SYSENTER_ESP;
    QWORD SYSENTER_EIP;
    QWORD CR2;

    BYTE reserved15[32];
    QWORD G_PAT;
    QWORD DBGCTL;
    QWORD BR_FROM;
    QWORD BR_TO;
    QWORD LASTEXCPFROM;
    QWORD LASTEXCPTO; //690


} __attribute__((__packed__)) vmcb, *pvmcb;

typedef volatile struct _cpuinfo
{
  DWORD active;
  DWORD cpunr;
  DWORD apicid;
  DWORD hastoterminate;
  DWORD hasIF;
  UINT64 guestCR0;
  UINT64 guestCR3;
  char  isboot;
  char  command;
  char  vmxsetup;
  char  invalidcs;

  int   int1happened; //set if it has just redirected a interrupt, cleared by vmcall query command
  int   int3happened; //'  '  '
  int   int14happened; //'  '  '

  /* the TS elements are used for transition from protected mode to real and back, since that changes the TS temporarily */
  WORD  TSsegment;
  UINT64 TSbase;
  DWORD TSlimit;
  DWORD TSaccessRights;



  unsigned long long sysenter_CS; //what the guest sees
  unsigned long long sysenter_EIP;
  unsigned long long sysenter_ESP;

  int   hidden_sysenter_modification;
  unsigned long long actual_sysenter_CS; //what is actually is
  unsigned long long actual_sysenter_EIP;
  unsigned long long actual_sysenter_ESP;
  unsigned long long efer;


  void *vmcb_host;
  pvmcb vmcb; //AMD's virtual machine control_block. Give the physical address of this to VMRUN
  UINT64 vmcb_PA;

  UINT64 guest_VM_HSAVE_PA; //the current VM_HSAVE_PA according to the guest



  void* vmxon_region;
  void* vmcs_region;

  UINT64 virtualTLB_PA;
  void  *virtualTLB;
  void  *virtualTLB_FreeSpot;
  DWORD virtualTLB_Max; //max size of the virtual TLB, when hit, flush...
  UINT64 *virtualTLB_Lookup; //used to lookup the original physical address of a entry
  int   virtualTLB_whiped;

  unsigned char *virtualTLB_guest_PDPTR_lookup;  //memory to keep the original guest's pagedirptr addresses in. (so changes can be detected)
  unsigned char *virtualTLB_guest_PD_lookup; //memory to keep the original guests's pagedir(s) addresses in. (so changes can be detected)

  UINT64 AvailableVirtualAddress;  //used for mapping physical memory, last 4 bits define the cpunr

  UINT64 Previous_Interuptability_State; //used for the block/unblock interrupts vmcall
  int    Previous_CLI;

  struct {
    UINT64 IDTBase;
    WORD IDTLimit;
    UINT64 GDTBase;
    WORD GDTLimit;
  } RealMode;

  struct {
    int cr3_change_callback; //=1 when a callback has been registered
    int called_callback;

    int calling_convention;
    WORD callback_cs;
    WORD callback_ss;
    UINT64 callback_rip;
    UINT64 callback_rsp;

    UINT64 rip;

    //saved state before the callback as made
    UINT64 rax;
    UINT64 rbx;
    UINT64 rcx;
    UINT64 rdx;
    UINT64 rsi;
    UINT64 rdi;
    UINT64 rbp;
    UINT64 rsp;
    UINT64 r8;
    UINT64 r9;
    UINT64 r10;
    UINT64 r11;
    UINT64 r12;
    UINT64 r13;
    UINT64 r14;
    UINT64 r15;

    UINT64 rflags;
    UINT64 interruptability_state;

    ULONG cs_selector;
    ULONG cs_limit;
    ULONG cs_base;
    ULONG cs_accessrights;

    ULONG ss_selector;
    ULONG ss_limit;
    ULONG ss_base;
    ULONG ss_accessrights;

    ULONG ds_selector;
    ULONG ds_limit;
    ULONG ds_base;
    ULONG ds_accessrights;

    ULONG es_selector;
    ULONG es_limit;
    ULONG es_base;
    ULONG es_accessrights;

    ULONG fs_selector;
    ULONG fs_limit;
    ULONG fs_base;
    ULONG fs_accessrights;

    ULONG gs_selector;
    ULONG gs_limit;
    ULONG gs_base;
    ULONG gs_accessrights;

    UINT64 newcr3;
    int changedcr3;
  } cr3_callback;

  struct
  {
    int Active; //set to 1 when active
    QWORD CR3; //Holds the CR3 value to watch taskswitch to and from
    QWORD DEBUGCTL; //Holds the DebugCTL value to set when inside the target process
    QWORD DS_AREA; //Holds the DS_AREA to set when
    QWORD OriginalDebugCTL; //When inside the target process this holds the debugctl that was set before entering. Return this on readMSR (and set with writeMSR when inside the process)
    QWORD OriginalDS_AREA; //When inside the target process this holds the DS_AREA that was set before entering. Return this with readMSR ('''')

#ifdef ULTIMAPDEBUG
    QWORD CR3_switchcount;
    QWORD CR3_switchcount2;
    QWORD LastOldCR3;
    QWORD LastNewCR3;
#endif
  } Ultimap;

  struct
  {
      int Active;
      QWORD LastIgnoredPageFault;
  } IgnorePageFaults;


  //Host-only fields:
  //field for exception handling
  struct
  {
      QWORD RIP;  //if set go to this address on return from any interrupt
      QWORD RSP;  //if set go to this address on return from any interrupt
  } OnInterrupt;



  unsigned char LastInterrupt;
  unsigned char LastInterruptHasErrorcode;
  WORD LastInterruptErrorcode;

} tcpuinfo, *pcpuinfo; //allocated when the number of cpu's is known
tcpuinfo cpuinfo[32];




typedef struct
{
  union
  {
    ULONG	Selectorvalue;
	  struct {
      ULONG	RPL      : 2;
      ULONG TI       : 1;
      ULONG	Selector : 29;
		};
	};
} Selector_Field, *PSelector_Field;


typedef struct _regCR0
{
  union{
    unsigned long long CR0;
    struct {
      unsigned PE         :1; //0
      unsigned MP         :1; //1
      unsigned EM         :1; //2
      unsigned TS         :1; //3
      unsigned ET         :1; //4
      unsigned NE         :1; //5
      unsigned reserved1  :10; //6-15
      unsigned WP         :1; //16
      unsigned reserved2  :1; //17
      unsigned AM         :1; //18
      unsigned reserved   :10; //19-28
      unsigned NW         :1; //29
      unsigned CD         :1; //30
      unsigned PG         :1; //31
    };
  };
} __attribute__((__packed__)) regCR0,*PregCR0;

typedef struct _regCR4
{
  union{
    unsigned long long CR4;
    struct {
      unsigned VME        :1;
      unsigned PVI        :1;
      unsigned TSD        :1;
      unsigned DE         :1;
      unsigned PSE        :1;
      unsigned PAE        :1;
      unsigned MCE        :1;
      unsigned PGE        :1;
      unsigned PCE        :1;
      unsigned OSFXSR     :1;
      unsigned OSXMMEXCPT :1;
      unsigned reserved   :2;
      unsigned VMXE       :1;
      UINT64   reserved2  :50;
    };
  };
} __attribute__((__packed__)) regCR4,*PregCR4;

//PAE setting bits(when used without regCR4)
#define CR4_VME         (1<<0)
#define CR4_PVI         (1<<1)
#define CR4_TSD         (1<<2)
#define CR4_DE          (1<<3)
#define CR4_PSE         (1<<4)
#define CR4_PAE         (1<<5)
#define CR4_MCE         (1<<6)
#define CR4_PGE         (1<<7)
#define CR4_PCE         (1<<8)
#define CR4_OSFXSR      (1<<9)
#define CR4_OSXMMEXCPT  (1<<10)
#define CR4_VMXE        (1<<13)
#define CR4_SMXE        (1<<14)
#define CR4_FSGSBASE    (1<<16)
#define CR4_PCIDE       (1<<17)
#define CR4_OSXSAVE     (1<<18)



typedef struct _regDR6
{
  union{
    unsigned long long DR6;
    struct {
      unsigned B0        :1;
      unsigned B1        :1;
      unsigned B2        :1;
      unsigned B3        :1;
      unsigned Reserved  :9;
      unsigned BD        :1;
      unsigned BS        :1;
      unsigned BT        :1;
    };
  };
} __attribute__((__packed__)) regDR6,*PregDR6;

typedef struct _regDR7
{
  union{
    unsigned long long DR7;
    struct {
      unsigned L0        :1; //0
      unsigned G0        :1; //1
      unsigned L1        :1; //2
      unsigned G1        :1; //3
      unsigned L2        :1; //4
      unsigned G2        :1; //5
      unsigned L3        :1; //6
      unsigned G3        :1; //7
      unsigned LE        :1; //8
      unsigned GE        :1; //9
      unsigned reserved  :3; //001  //10-11-12
      unsigned GD        :1; //13...
      unsigned reserved2 :2; //00
      unsigned RW0       :2;
      unsigned LEN0      :2;
      unsigned RW1       :2;
      unsigned LEN1      :2;
      unsigned RW2       :2;
      unsigned LEN2      :2;
      unsigned RW3       :2;
      unsigned LEN3      :2;
      unsigned reserved3 :32;
    };
  };
} __attribute__((__packed__)) regDR7,*PregDR7;


typedef struct _pferrorcode /* errorcode returned for pagefaults */
{
  union{
    unsigned long long errorcode;
    struct {
      unsigned P          :1;  /* 0=non present page, 1=page level protection violation */
      unsigned W          :1;  /* 0=read exception, 1=write exception */
      unsigned US         :1;  /* 0=processor was in supervisor mode, 1=processor was in usermode */
      unsigned RSVD       :1;  /* 0=Not caused by reserved bits set, 1=Caused because reserved bits are set */
      unsigned ID         :1;  /* 0=Not caused by an instruction fetch, 1=Caused by an instruction fetch */
      unsigned reserved   :27;
    };
  };
} __attribute__((__packed__)) PFerrorcode,*PPFerrorcode;


UINT64 IA32_VMX_CR0_FIXED0,IA32_VMX_CR0_FIXED1;
UINT64 IA32_VMX_CR4_FIXED0,IA32_VMX_CR4_FIXED1;
TIA32_VMX_BASIC IA32_VMX_BASIC;
UINT64 IA32_VMX_PINBASED_CTLS;
UINT64 IA32_VMX_PROCBASED_CTLS;
UINT64 IA32_VMX_SECONDARY_PROCBASED_CTLS;
UINT64 IA32_VMX_EXIT_CTLS;
UINT64 IA32_VMX_ENTRY_CTLS;
TIA32_VMX_MISC IA32_VMX_MISC;

extern void SaveExtraHostState(UINT64 VMCB_PA);

void CheckGuest(void);
void displayVMmemory(pcpuinfo currentcpuinfo);
void displayPhysicalMemory();
void setupTSS8086(void);
void setupVMX(pcpuinfo currentcpuinfo);
void launchVMX(pcpuinfo currentcpuinfo);
int vmexit(tcpuinfo *cpu, UINT64 *registers);
int vmexit_amd(pcpuinfo currentcpuinfo, UINT64 *registers);

void sendvmstate(pcpuinfo currentcpuinfo, VMRegisters *registers);
char *getVMInstructionErrorString(void);

void ShowCurrentInstruction(pcpuinfo currentcpuinfo);
void ShowCurrentInstructions(pcpuinfo currentcpuinfo);
void displayPreviousStates(void);

int isDebugFault(QWORD dr6, QWORD dr7);


int ISREALMODE(pcpuinfo currentcpuinfo);
int IS64BITPAGING(pcpuinfo currentcpuinfo);
int IS64BITCODE(pcpuinfo currentcpuinfo);

#endif /*VMMHELPER_H_*/