Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Is there a way to add many addresses to cheat table by lua?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
mindoff
Advanced Cheater
Reputation: 0

Joined: 12 Jun 2016
Posts: 96

PostPosted: Sat Jul 27, 2019 10:05 pm    Post subject: Is there a way to add many addresses to cheat table by lua? Reply with quote

Right now i'm working on a kenshi ralations modify.

The problem is I can get the relation asm code and debug to get the address of each one,and if I modify that code,it will modify all the relation to some value like 50.

But I don't want all the relation to 50,I just want some one specify to be 50.

I can modify it myself,but I still want to list all the relation from that code.

the code is something like below

movss xmm6,[rax+04]


[rax+04] is float value and rax + 04 is the address

the number of relations are not fixed I think.

I may be 5 or 20 or anything.

So I need to record these address and add these address into cheat table dynamicly.

My idea is this,the address is a loop if you set a break point.

Let's say first break point rax will be

11223340,

next may be

11223350,

and so on.

this seems infinite.But it will always be
11223340 address if you keep running debug.

and this whole loop should be all the relation address I need.

In some high level language like C#,I may code like


Code:

bool bOnce = false;
bool bFinishList = false;

int firstAddress = 0;

List<int> addressList = new List<int>();

void update()
{
   if(!bFinishList)
   {
      if(!bOnce)
      {
         firstAddress = getRaxAddr();
      }

      if(firstAddress != 0 && getRaxAddr() != firstAddress)
      {
         addressList.Add(getRaxAddr());
      }

      if(getRaxAddr() == firstAddress)
      {
         bFinishList = true;
      }
   }
   
}


Then addressList should have all the relation address I need.

So is there any way to do silimar thing with Lua and list these address to cheat table dynamicly?
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Sun Jul 28, 2019 3:08 am    Post subject: This post has 1 review(s) Reply with quote

The Lua function: getAddressList() will return the main address list object from the CE window. From there you would use the AddressList and MemoryRecord objects:

Code:


MemoryRecord Class:
The memoryrecord objects are the entries you see in the addresslist

properties
  ID: Integer - Unique ID
  Index: Integer - The index ID for this record. 0 is top. (ReadOnly)
  Description: string- The description of the memory record
  Address: string - Get/set the interpretable address string. Useful for simple address settings.
  AddressString: string - Get the address string shown in CE (ReadOnly)
  OffsetCount: integer - The number of offsets. Set to 0 for a normal address
  Offset[] : integer - Array to access each offset
  OffsetText[] : string - Array to access each offset using the interpretable text style

  CurrentAddress: integer - The address the memoryrecord points to
  VarType: ValueType (string) - The variable type of this record. See vtByte to vtCustom
  Type: ValueType (number) - The variable type of this record. See vtByte to vtCustom
    If the type is vtString then the following properties are available:
     String.Size: Number of characters in the string
     String.Unicode: boolean
     String.Codepage: boolean

    If the type is vtBinary then the following properties are available
      Binary.Startbit: First bit to start reading from
      Binary.Size : Number of bits

    If the type is vtByteArray then the following properties are available
      Aob.Size : Number of bytes

  CustomTypeName: String - If the type is vtCustom this will contain the name of the CustomType
  Script: String - If the type is vtAutoAssembler this will contain the auto assembler script
  Value: string - The value in stringform.
  Selected: boolean - Set to true if selected (ReadOnly)
  Active: boolean - Set to true to activate/freeze, false to deactivate/unfreeze
  Color: integer
  ShowAsHex: boolean - Self explanatory
  ShowAsSigned: boolean - Self explanatory
  AllowIncrease: boolean - Allow value increasing, unfreeze will reset it to false
  AllowDecrease: boolean - Allow value decreasing, unfreeze will reset it to false
  Collapsed: boolean - Set to true to collapse this record or false to expand it. Use expand/collapse methods for recursive operations.
  IsGroupHeader: boolean - Set to true if the record was created as a Group Header with no address or value info. (ReadOnly)
  IsReadable: boolean - Set to false if record contains an unreadable address. NOTE: This property will not be set until the value property is accessed at least once. (ReadOnly)

  Options: String set - a string enclosed by square brackets filled with the options seperated by a comma. Valid options are: moHideChildren, moActivateChildrenAsWell, moDeactivateChildrenAsWell, moRecursiveSetValue, moAllowManualCollapseAndExpand, moManualExpandCollapse
 
  DropDownLinked: boolean - if dropdown list refers to list of another memory record eg. (memrec name)
  DropDownLinkedMemrec: string - Description of linked memrec or emptystring if not linked
  DropDownList : StringList - list of "value:description" lines, lists are still separate objects when linked, read-write
  DropDownReadOnly: boolean - true if 'Disallow manual user input' is set
  DropDownDescriptionOnly: boolean - self explanatory
  DisplayAsDropDownListItem: boolean - self explanatory
  DropDownCount: integer - equivalent to .DropDownList.Count
  DropDownValue[index] : Array to access values in DropDownList (ReadOnly)
  DropDownDescription[index] : Array to access Descriptions in DropDownList (ReadOnly)



  Count: Number of children
  Child[index] : Array to access the child records
  [index] = Child[index]
  Parent: MemoryRecord - self explanatory

  HotkeyCount: integer - Number of hotkeys attached to this memory record
  Hotkey[] : Array to index the hotkeys

  Async: Boolean - Set to true if activating this entry will be asynchronious. (only for AA/Lua scripts)
  AsyncProcessing: Boolean - True when async is true and it's being processed
  AsyncProcessingTime: qword - The time that it has been processing in milliseconds


  OnActivate: function(memoryrecord,before,currentstate):boolean - The function to call when the memoryrecord will change (or changed) Active to true. If before is true, not returning true will cause the activation to stop.
  OnDeactivate: function(memoryrecord,before,currentstate):boolean - The function to call when the memoryrecord will change (or changed) Active to false. If before is true, not returning true will cause the deactivation to stop.
  OnDestroy: function() - Called when the memoryrecord is destroyed.
  OnGetDisplayValue: function(memoryrecord,valuestring):boolean,string - This function gets called when rendering the value of a memory record. Return true and a new string to override the value shown
  DontSave: boolean - Don't save this memoryrecord and it's children

methods
  getDescription()
  setDescription()
  getAddress() : Returns the interpretable addressstring of this record. If it is a pointer, it returns a second result as a table filled with the offsets
  setAddress(string) : Sets the interpretable address string, and if offsets are provided make it a pointer

  getOffsetCount(): Returns the number of offsets for this memoryrecord
  setOffsetCount(integer): Lets you set the number of offsets

  getOffset(index) : Gets the offset at the given index
  setOffset(index, value) : Sets the offset at the given index

  getCurrentAddress(): Returns the current address as an integer (the final result of the interpretable address and pointer offsets)

  appendToEntry(memrec): Appends the current memory record to the given memory record

  getHotkey(index): Returns the hotkey from the hotkey array
  getHotkeyByID(integer): Returns the hotkey with the given id

  reinterpret()
  createHotkey({keys}, action, value OPTIONAL): Returns a hotkey object

  disableWithoutExecute(): Sets the entry to disabled without executing the disable section


global events
  function onMemRecPreExecute(memoryrecord, newstate BOOLEAN):
    If above function is defined it will be called before action* has been performed.
    Active property is about to change to newState.
 
  function onMemRecPostExecute(memoryrecord, newState BOOLEAN, succeeded BOOLEAN):
    If above function is defined it will be called after action*.
    Active property was supposed to change to newState.
    If 'succeeded' is true it means that Active state has changed and is newState.
   
    newState and succeeded are read only.
 
    *action can be: running auto assembler script (ENABLE or DISABLE section), freezing and unfreezing.
 


Addresslist Class: (Inheritance: Panel->WinControl->Control->Component->Object)
properties
  Count: Integer - The number of records in the table
  SelCount: integer- The number of records that are selected
  SelectedRecord: MemoryRecord - The main selected record
  MemoryRecord[]: MemoryRecord - Array to access the individial memory records
  [] = MemoryRecord - Default accessor

  CheckboxActiveSelectedColor: color
  CheckboxActiveColor: color
  CheckboxSelectedColor: color
  CheckboxColor: color
  SelectedBackgroundColor: color
  SelectedSecondaryBackgroundColor: color
  ExpandSignColor: color
  IncreaseArrowColor: color
  DecreaseArrowColor: color

  OnDescriptionChange: function(addresslist,memrec):boolean - called when the user initiates a description column change on a record. Return true if you handle it, false for normal behaviour
  OnAddressChange: function(addresslist,memrec):boolean - called when the user initiates an address column change on a record. Return true if you handle it, false for normal behaviour
  OnTypeChange: function(addresslist,memrec):boolean - called when the user initiates a type column change on a record. Return true if you handle it, false for normal behaviour
  OnValueChange: function(addresslist,memrec):boolean - called when the user initiates a value column change on a record. Return true if you handle it, false for normal behaviour


methods
  getCount()
  getMemoryRecord(index)
  getMemoryRecordByDescription(description): returns a MemoryRecord object
  getMemoryRecordByID(ID)
  createMemoryRecord() : creates an generic cheat table entry and add it to the list

  getSelectedRecords():  Returns a table containing all the selected records

  doDescriptionChange() : Will show the GUI window to change the description of the selected entry
  doAddressChange() : Will show the GUI window to change the address of the selected entry
  doTypeChange() : Will show the GUI window to change the type of the selected entries
  doValueChange() : Will show the GUI window to change the value of the selected entries

  getSelectedRecord() : Gets the main selected memoryrecord
  setSelectedRecord(memrec) : Sets the currently selected memoryrecord. This will unselect all other entries

  disableAllWithoutExecute(): Disables all memory records without executing their [Disable] section



Other information regarding CE's Lua setup can be found in the celua.txt file in CE's directory.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Sun Jul 28, 2019 8:25 am    Post subject: This post has 1 review(s) Reply with quote

besides the addresslist / memory record stuff it also has some debugging stuff

Code:
-debugging

debug variables
EFLAGS
32/64-bit: EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, EIP
64-bit only: RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, RIP, R8, R9, R10, R11, R12, R13, R14, R15 : The value of the register


Debug related routines:
function debugger_onBreakpoint():
When a breaking breakpoint hits (that includes single stepping) and the lua function debugger_onBreakpoint() is defined it will be called and the global variables EAX, EBX, .... will be filled in
Return 0 if you want the userinterface to be updated and anything else if not (e.g: You continued from the breakpoint in your script)



createProcess(path, parameters OPTIONAL, debug OPTIONAL, breakonentrypoint OPTIONAL) : Creates a process. If debug is true it will be created using the windows debugger and if breakonentry is true it will cause a breakpoint to occur on entrypoint

debugProcess(interface OPT): starts the debugger for the currently opened process (won't ask the user) Optional interface: 0=default, 1=windows debug, 2=VEHDebug, 3=Kerneldebug

debug_isDebugging(): Returns true if the debugger has been started
debug_getCurrentDebuggerInterface() : Returns the current debuggerinterface used (1=windows, 2=VEH 3=Kernel, nil=no debugging active)
debug_canBreak(): Returns true if there is a possibility the target can stop on a breakpoint. 6.4+
debug_isBroken(): Returns true if the debugger is currently halted on a thread
debug_getBreakpointList(): Returns a lua table containing all the breakpoint addresses

debug_addThreadToNoBreakList(threadid): This will cause breakpoints on the provided thread to be ignored
debug_removeThreadFromNoBreakList(threadid): removed the threadid from the list


debug_setBreakpoint(address, size OPTIONAL, trigger OPTIONAL, breakpointmethod OPTIONAL, functiontocall() OPTIONAL) : sets a breakpoint of a specific size at the given address. if trigger is bptExecute then size is ignored. If trigger is ignored then it will be of type bptExecute, which obviously also ignores the size then as well.  (Other triggers are bptAccess and bptWrite)
debug_setBreakpoint(address, size OPTIONAL, trigger OPTIONAL, functiontocall() OPTIONAL)
debug_setBreakpoint(address, functiontocall() OPTIONAL)
debug_removeBreakpoint(address) : if the given address is a part of a breakpoint it will be removed
debug_continueFromBreakpoint(continueMethod) : if the debugger is currently waiting to continue you can continue with this. Valid parameters are :co_run (just continue), co_stepinto(when on top of a call, follow it), co_stepover (when on top of a call run till after the call)
debug_getXMMPointer(xmmregnr) :
  Returns the address of the specified xmm register of the thread that is currently broken
  This is a LOCAL Cheat Engine address. Use Local memory access functions to read and modify
  xmmregnr can be 0 to 15 (0 to 7 on 32-bit)


The following routines describe last branch recording. These functions only work when kernelmode debugging is used and using windows XP (vista and later work less effective or not at all because the operating system interferes.  Might also be intel specific. A dbvm upgrade in the future might make this work for windows vista and later)
debug_setLastBranchRecording(boolean): When set the Kernel debugger will try to record the last branch(es) taken before a breakpoint happens
debug_getMaxLastBranchRecord() : Returns the maximum branch record your cpu can store (-1 if none)
debug_getLastBranchRecord(index): Returns the value of the Last Branch Record at the given index (when handling a breakpoint)


function debugger_onModuleLoad(modulename, baseaddress) :
this routine is called when a module is loaded. Only works for the windows debugger
return 1 if you want to cause the debugger to break


Changing registers:
When the debugger is waiting to continue you can change the register variables. When you continue those register values will be set in the thread's context


If the target is currently stopped on a breakpoint, but not done through an onBreakpoint function. The context won't be set.
You can get and set the context back with these functions before execution continues"
debug_getContext(BOOL extraregs) - Fills the global variables for the regular registers. If extraregs is true, it will also set FP0 to FP7 and XMM0 to XMM15
debug_setContext(BOOL extraregs)
debug_updateGUI() - Will refresh the userinterface to reflect the new context if the debugger was broken



detachIfPossible() : Detaches the debugger from the target process (if it was attached)


Though I don't believe there's any trivial way to open the "find what accesses" or "find what addresses this instruction accesses" windows or the list they create. You can of course recreate the functionality yourself.

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
mindoff
Advanced Cheater
Reputation: 0

Joined: 12 Jun 2016
Posts: 96

PostPosted: Sun Jul 28, 2019 7:51 pm    Post subject: Reply with quote

Thanks,figure out how to use

getAddressList() and createMemoryRecord()

now the problem is how to mix asm and lua code together.

I test some code in Darkest Dungeon main update function,suppose lua could print number every frame and increase one by one.

But it only run once.What's the problem?

Is lua only run once in [enable]?

do I need to call lua function from asm?

if so how?

How could I record eax value from asm and add this value to memoryrecord from lua?



Code:


define(address,"Darkest.exe"+11711CF)
define(bytes,8B 34 C8 0F 84 3F 07 00 00)

{$lua}
gCount = 0

{$asm}
[ENABLE]

assert(address,bytes)
alloc(newmem,$1000)

label(code)
label(return)

newmem:

code:

{$lua}
//I want to print value every time asm code running here as asm code
print(gCount)
gCount = gCount + 1

//But it only run once and gCount is not global var,every time print will return 0...


{$asm}
  mov esi,[eax+ecx*8]
  je Darkest.exe+1171917
  jmp return

address:
  jmp newmem
  nop
  nop
  nop
  nop
return:

[DISABLE]

address:
  db bytes
  // mov esi,[eax+ecx*8]
  // je Darkest.exe+1171917

dealloc(newmem)

Back to top
View user's profile Send private message
predprey
Master Cheater
Reputation: 24

Joined: 08 Oct 2015
Posts: 486

PostPosted: Mon Jul 29, 2019 7:45 am    Post subject: Reply with quote

mindoff wrote:
Thanks,figure out how to use

getAddressList() and createMemoryRecord()

now the problem is how to mix asm and lua code together.

I test some code in Darkest Dungeon main update function,suppose lua could print number every frame and increase one by one.

But it only run once.What's the problem?

Is lua only run once in [enable]?

do I need to call lua function from asm?

if so how?

How could I record eax value from asm and add this value to memoryrecord from lua?



Code:


define(address,"Darkest.exe"+11711CF)
define(bytes,8B 34 C8 0F 84 3F 07 00 00)

{$lua}
gCount = 0

{$asm}
[ENABLE]

assert(address,bytes)
alloc(newmem,$1000)

label(code)
label(return)

newmem:

code:

{$lua}
//I want to print value every time asm code running here as asm code
print(gCount)
gCount = gCount + 1

//But it only run once and gCount is not global var,every time print will return 0...


{$asm}
  mov esi,[eax+ecx*8]
  je Darkest.exe+1171917
  jmp return

address:
  jmp newmem
  nop
  nop
  nop
  nop
return:

[DISABLE]

address:
  db bytes
  // mov esi,[eax+ecx*8]
  // je Darkest.exe+1171917

dealloc(newmem)



there is a lua server template in the AA script form. but depending on how often the hooked code runs, calling CE’s lua server from within the game through ASM might create some lag, due to interprocess communication
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Mon Jul 29, 2019 7:55 am    Post subject: Reply with quote

Quote:
now the problem is how to mix asm and lua code together. ...
Is lua only run once in [enable]?
do I need to call lua function from asm?

yes, it's really more of a metaprogramming feature where you can run lua code before the asm is even really looked at and return a string of more AA code (which could include more {$lua} blocks that return more AA code etc lol)

As predprey mentions there's a template that lets you run lua from assembly but it can cause some lag, that can be mitigated some by precompiling the lua script and using a function reference. I have a couple basic examples here: https://github.com/FreeER/CE-Examples/blob/master/Tutorial-i386.ct#L2534-L2655 which include commented links to some more info here on the forums

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
mindoff
Advanced Cheater
Reputation: 0

Joined: 12 Jun 2016
Posts: 96

PostPosted: Wed Jul 31, 2019 6:51 pm    Post subject: Reply with quote

Thanks for the tutorial,almost done.

Now what I want to know is how to set a global lua variable which can share between multi places.

On my test,Cheat Table Lua Script can't even share a variable when run some code like this

Code:

n = 0
print(n)
n = n + 1


This will always print 0


what I need is a global var which can count how many times I have run.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Wed Jul 31, 2019 7:23 pm    Post subject: Reply with quote

You are setting n to 0 then printing it, it'll always print 0 in that case.
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
mindoff
Advanced Cheater
Reputation: 0

Joined: 12 Jun 2016
Posts: 96

PostPosted: Wed Jul 31, 2019 7:28 pm    Post subject: Reply with quote

OK,all done.

Thank you all for the replies
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites