|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Sun Jun 26, 2016 2:43 pm Post subject: LUA logfile script HELP! [1st time on LUA] |
|
|
I'm trying to write down a logfile script for debugging purposes.
I need it because I'm dealing with an event base managed game (one function for reading almost everything).
So, not only I have to identify the memory by its relative label/event but also by the sequence of chained events leading to it.
I have two problems (after hours kicking my head to the wall - smashing my PC wasn't a wise move):
1) in the logfile I managed to obtain all numbers are decimal and I wasn't able to store them in hex;
2) I need that after filling 10000 records in logfile, the script pause the process and end itself for an eventual restart.
Like stating in the subject, it's my first time on LUA
Code: | ck_addr = getAddress("exec.exe+[offset]") -- like "Tutorial-x86_64.exe+12F8"
logfile = [[D:\tmplog.txt]]
function debugger_onBreakpoint()
if (EIP==ck_addr) then
tmp_EAX = EAX
addr_EAX = tmp_EAX + 0x1C -- I don't understand why EAX + 0x1C returns a wrong value,
and the same goes for EAX + 28
if (readString(addr_EAX)~=nil) then -- I don't understand why (readString(EAX)~=nil)
doesn't work
str_EAX = readString(addr_EAX)
addr_ECX = ECX + 0x04
val_ECX = readInteger(addr_ECX)
f = io.open(logfile,"a+")
f:write(addr_ECX .. ", " .. val_ECX .. ", " .. EAX .. ", " .. str_EAX .. "\n")
f:close()
else
debug_continueFromBreakpoint(co_run)
end
debug_continueFromBreakpoint(co_run)
return 1
else
return 0
end
end
debug_setBreakpoint(ck_addr) |
What do I have to add/change to solve my problems?
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Sun Jun 26, 2016 4:03 pm Post subject: |
|
|
Use string.format("%X",number) to get the string representation of a number in hex.
I'm not sure what you mean by "end itself for an eventual restart."
For all relevant intents and purposes, addr_EAX is the exact same as EAX+0x1C when you call readString. It was something else in your code that was wrong.
I don't know what you're trying to do with "readString(EAX)~=nil" if it doesn't work for you. Pretty much all you're doing is checking if EAX points to a valid memory location.
Code: | logFileCount = 0;
debug_setBreakpoint("exec.exe+[offset]", 1, bptExecute, function()
local eaxStr = readString(EAX+0x1C,1000)
if eaxStr then
f = io.open("D:\\tmplog.txt","a+")
f:write(string.format("%X, %d, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, eaxStr))
f:close()
logFileCount = logFileCount + 1
end
debug_continueFromBreakpoint(co_run)
if logFileCount > 10000 then pause() end
return 1
end) |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Sun Jun 26, 2016 8:20 pm Post subject: |
|
|
Thanks for your answer.
Quote: | I don't know what you're trying to do with "readString(EAX)~=nil" [...]Pretty much all you're doing is checking if EAX points to a valid memory location. |
Yes, in a few cases EAX is not an address, but just a value.
Quote: | I'm not sure what you mean by "end itself for an eventual restart." |
Like I wrote, the process is an event base managed game, and I'm trying to logging into a function reading almost everything. That's means it's prone to crash - I already tested someone else table, that worked flawlessly for a few hours and suddenly the game crashed.
Trying to use "Break and trace instructions" is no use, because VEH debugger crashes and the same goes using for a handful of seconds (less then 30) "Find out what addresses this code accesses".
So I need to remove the bp, but I think it's enough to insert debug_removeBreakpoint(address) in your script.
Code: | [ ... ]
if logFileCount > 10000 then
pause()
debug_removeBreakpoint("exec.exe+[offset]") <--- here, I think
end
return 1
end |
Please, tell me if I'm wrong.
One last question:
Where can I use the code you posted? In a LUA engine window only? Or inside a AA script too?
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Sun Jun 26, 2016 8:46 pm Post subject: |
|
|
That would be correct. If the process still crashes, you may want to remove pause().
You can enter it in the Lua script window, the Lua engine window, or an AA script. You can directly copy and paste it into the Lua script or Lua engine windows, but you have to format an AA script with the {$lua} tag:
Code: | {$lua}
if syntaxcheck then return end
[ENABLE]
-- Lua code to run when script is enabled
[DISABLE]
-- Lua code to run when script is disabled |
CE's auto assembler will execute the code when you change it or assign it to the cheat table in order to do a syntax check of it. If you're certain the script is correct, you can avoid this by checking the variable syntaxcheck (CE sets this to true if it's doing a syntaxcheck).
When inside a {$lua} block, the [ENABLE] and [DISABLE] tags will still be recognized by CE's parser even though the syntax highlighter doesn't do anything to them.
You can use {$asm} to switch back to assembly if you want.
The [ENABLE] and [DISABLE] sections do not share a common scope; however, anything before the [ENABLE] tag will be executed both when the script is enabled and disabled:
Code: | {$lua}
print("script toggled") -- prints on both enable and disable
[ENABLE]
local a = 5
print(tostring(a)) -- prints 5
[DISABLE]
print(tostring(a)) -- prints nil |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Mon Jun 27, 2016 6:24 am Post subject: |
|
|
In order to recap.
Inside Lua script window, or Lua engine window:
Code: | logFileCount = 0;
debug_setBreakpoint("exec.exe+[offset]", 1, bptExecute, function()
if (readString(EAX+0x1C,1000)) then
f = io.open("D:\\tmplog.txt","a+")
f:write(string.format("%X, %X, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, readString(EAX+0x1C,1000))
f:close()
logFileCount = logFileCount + 1
end
debug_continueFromBreakpoint(co_run)
if logFileCount > 10000 then
pause()
debug_removeBreakpoint("exec.exe+[offset]")
end
return 1
end |
Inside an AA script
Code: | {$lua}
if syntaxcheck then return end
{$asm}
[ENABLE]
AOBScanModule(aobname,exec.exe,[array pattern])
alloc(newmem,$1000)
label1
[...]
labeln
registersymbol(aobname)
newmem:
[originalcode]
label1: \
[asm code] |
[...] > placement irrelevant
labeln: |
[asm code] /
{$lua}
logFileCount = 0;
if (readString(EAX+0x1C,1000)) then
f = io.open("D:\\tmplog.txt","a+")
f:write(string.format("%X, %X, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, readString(EAX+0x1C,1000))
f:close()
logFileCount = logFileCount + 1
end
if logFileCount > 10000 then
pause()
end
return 1
end
{$asm}
aobname:
jmp newmem
(nops)
return:
[DISABLE]
aobname:
[originalcode]
dealloc(newmem)
unregistersymbol(aobname)
|
Are they both correct?
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Mon Jun 27, 2016 9:01 am Post subject: |
|
|
Why do you have that random Lua block inside the AA script? That's only going to get executed once when the script is first enabled. If you're going to execute the Lua code inside the Lua script/engine window, then you don't need any of this Lua code inside your AA script.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Mon Jun 27, 2016 12:36 pm Post subject: |
|
|
I wasn't saying I wanted to use both at the same time.
I was just trying to put down two different alternatives.
The solution using a Lua script inside an AA script could be useful in order to avoid involving the debugger and bps (fps drop down hardly, and crashes happen easily).
But I understand that it can require a pretty much different approach.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Mon Jun 27, 2016 12:47 pm Post subject: |
|
|
Ah, my apologies.
Regardless, you'll still need to use the debugger inside the AA script. It's not like the game is running that section of Lua; it's CE that's running it once when the script first activates.
Code: | {$lua}
if syntaxcheck then return end
[ENABLE]
logFileCount = 0
debug_setBreakpoint("exec.exe+[offset]", 1, bptExecute, function()
local eaxStr = readString(EAX+0x1C,1000)
if eaxStr then
f = io.open("D:\\tmplog.txt","a+")
f:write(string.format("%X, %d, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, eaxStr))
f:close()
logFileCount = logFileCount + 1
end
debug_continueFromBreakpoint(co_run)
if logFileCount > 10000 then
pause()
debug_removeBreakpoint("exec.exe+[offset]")
end
return 1
end)
[DISABLE]
debug_removeBreakpoint("exec.exe+[offset]")
logFileCount = nil |
You can call CE to run a Lua function from the game by using "Template -> Call CE Lua function" from an AA script. Note that anything you can do in Lua you can also do in asm. It may take longer to write it, but it's possible to do.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Mon Jun 27, 2016 2:07 pm Post subject: |
|
|
When I said it requires a different approach, I mean:
- making an AA script hooking and injecting on the address where otherwise I have to put a bp
- retrieve the registers and checking if they contain addresses in the AA script then
a) retrieve data needed and put them into global allocated memory (AA)
- pass memory to Lua in order to open and write the logfile
OR
b) pass just the registers to Lua
- retrieve data and open and write the logfile
- in both cases, after reaching a manageable number of lines, put on pause the process to review and clear the logfile.
P.S.: Testing right now the script again and it's very hard to understand whats going on, because game runs so dramatically slow.
I assume that's due to the debugger full time job
|
|
Back to top |
|
|
Zanzer I post too much Reputation: 126
Joined: 09 Jun 2013 Posts: 3278
|
Posted: Mon Jun 27, 2016 8:05 pm Post subject: |
|
|
Just open the file once when you enable the script. Close after your counter or the disable. Code: | {$lua}
if syntaxcheck then return end
[ENABLE]
f = io.open("D:\\tmplog.txt","a+")
logFileCount = 0
debug_setBreakpoint("exec.exe+[offset]", 1, bptExecute, function()
local eaxStr = readString(EAX+0x1C,1000)
if eaxStr then
f:write(string.format("%X, %d, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, eaxStr))
logFileCount = logFileCount + 1
end
debug_continueFromBreakpoint(co_run)
if logFileCount > 10000 then
pause()
debug_removeBreakpoint("exec.exe+[offset]")
f:close()
f = nil
end
return 1
end)
[DISABLE]
debug_removeBreakpoint("exec.exe+[offset]")
logFileCount = nil
if f then
f:close()
f = nil
end |
|
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Tue Jun 28, 2016 4:35 am Post subject: |
|
|
Like I said, testing the script made this way it's very hard to understand whats going on, because the game nearly freezes.
One of the reason is that leaving opened the memory view you can see registers and stacktrace constantly changing.
So, I had to change the script this way:
Code: |
ck_addr = getAddress("exec.exe+[offset]")
logFileCount = 0;
function debugger_onBreakpoint()
if (EIP==ck_addr) then
local eaxStr = readString(EAX+0x1C,1000)
if eaxStr then
f:write(string.format("%X, %X, %X, %s\n", ECX+4, readInteger(ECX+4), EAX, eaxStr)))
f:close()
logFileCount = logFileCount + 1
end
debug_continueFromBreakpoint(co_run)
if logFileCount > 10000 then
pause()
debug_removeBreakpoint("exec.exe+[offset]")
f = nil
end
debug_continueFromBreakpoint(co_run)
return 1
end
end
debug_setBreakpoint(ck_addr, 1, bptExecute)
|
At least this way I can see what the game is doing, even if really slowly.
I think that a better way should be keeping a Lua script that takes care of populating, managing and save the logfile, while in an AA script hooking the target code and retrieving needed data.
What I don't know is how passing register values to Lua, without using the debugger.
Another note: as soon as I unpause it, or I have to run the Lua script again or the game crashes.
|
|
Back to top |
|
|
ParkourPenguin I post too much Reputation: 140
Joined: 06 Jul 2014 Posts: 4299
|
Posted: Tue Jun 28, 2016 10:32 am Post subject: |
|
|
GrandPa wrote: | What I don't know is how passing register values to Lua, without using the debugger. | As I said before:
ParkourPenguin wrote: | You can call CE to run a Lua function from the game by using "Template -> Call CE Lua function" from an AA script. |
Alternatively, you can put it inside some memory location used as a buffer and have Lua flush that buffer every once in a while.
Code: | [ENABLE]
AOBScanModule(aobname,exec.exe,[array pattern])
alloc(newmem,$1000)
alloc(results,$14000) // allocate more memory if needed
label(exit)
registersymbol(aobname)
registersymbol(results)
newmem:
push edx
mov edx,[results]
cmp edx,#10000
jae short @f
lea edx,[edx*8+results+4]
mov [edx],eax
mov [edx+4],ecx
inc [results]
jmp short exit
@@:
mov [results],FFFFFFFF //signal to Lua for max reached
exit:
pop edx
//[originalcode]
jmp return
aobname:
jmp newmem
//(nops)
return:
[DISABLE]
aobname:
//[originalcode]
dealloc(newmem)
dealloc(results)
unregistersymbol(aobname)
unregistersymbol(results) |
In Lua, make a timer that checks if the max has been reached (i.e. readInteger("results") == 0xFFFFFFFF). If it has, go through that memory region, check which addresses are still valid, and record those you want. When finished, move 0 back into "results" to signal the code injection to overwrite everything it has written with new results.
Note that if memory is moved around, it could miss a valid pointer to a string in the time it takes for the buffer to fill up.
PS: I don't see f = io.open(...) anywhere in that last script you posted. Also the optimization Zanzer suggested is a good idea and I would strongly suggest you take it.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Tue Jun 28, 2016 1:43 pm Post subject: |
|
|
My apologies. I missed the part:
<< using "Template -> Call CE Lua function" from an AA script >>
For the part: f = io.open(...), I probably lost it inside the clipboard.
Thanks. I'll try to adapt the Lua script to meet the conditions you explained.
I'll let you know as soon as done.
|
|
Back to top |
|
|
Gottwald Newbie cheater Reputation: 0
Joined: 16 Dec 2012 Posts: 12
|
Posted: Tue Jul 05, 2016 8:09 pm Post subject: |
|
|
Little off-topic post if I may:
@GrandPa
Could you maybe take a look and make an update in your spare time?
forum.cheatengine.org/viewtopic.php?t=580977
Thanks!
|
|
Back to top |
|
|
GrandPa Advanced Cheater Reputation: 3
Joined: 09 Jul 2010 Posts: 87 Location: Italy
|
Posted: Wed Jul 06, 2016 7:34 pm Post subject: |
|
|
@ParkourPenguin:
I changed a bit your AA script in order to avoid those changes in memory over time that could give wrong results.
After checking other posts on Lua matter, I also changed the Lua script a bit in order to insert a timer for checking if the "results" area was filled.
All of the scripts worked.
I would have made some other tests and something more permanent, but, really, that game made me disgusted (strange behaviors like not triggering a level end, then crashing, or cheats always working that throw errors for a while and after a couple of restarts working again) so I quit for now, waiting for some game worth the efforts (or programs, why not).
@Gottwald:
Please, read my post dated Aug 30, 2015. I can work out nothing without feeling personal involvements. Sorry.
|
|
Back to top |
|
|
|
|
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
|
|