Page 1 of 1
Null-terminated string swapper
Posted: Sat Aug 06, 2022 10:24 am
by mece
Problem:
Some games use null-terminated strings as identity for game objects. E.g. replacing the string with another you can replace item prefix with rarest one. The problem is when new string is longer than original the change crushes the game because of buffer overflow.
Possible solution:
Please create a CE plugin that will allocate memory for new string value of memory record. This should be optional. Like this:

Partial solution I used in titan quest table for inventory editing.
Re: Null-terminated string swapper
Posted: Sat Aug 06, 2022 10:25 am
by mece
Here is the solution:
Open the image in new browser tab for better view.

The main idea is to redefine the memory record editing procedure. This includes the modified UI.
[ic]getAddressList().OnValueChange = OnValueChangeEx[/ic]
Important note: this prototype is built with several assumptions:
Code: Select all
[ENABLE]
{$lua}
if syntaxcheck then return end
GetLuaEngine().MenuItem5.doClick() -- crear lua output
OpenProcess(getCheatEngineProcessID())
--------------------------------------------------------------------------------
function getPointerSize()
return 4 + 4*(targetIs64Bit() and 1 or 0)
end
--------------------------------------------------------------------------------
function DeAllocateMemoryEx(symbol)
if getAddressSafe(symbol) then
deAlloc(symbol)
unregisterSymbol(symbol)
end
end
--------------------------------------------------------------------------------
function AllocateMemoryEx(symbol,size)
local mem = allocateMemory(size)
registerSymbol(symbol,mem)
return mem
end
--------------------------------------------------------------------------------
strings = {}
function WriteStringEx(value,len,widechar)
local num = #strings+1
local memSize = (len+1)*(widechar and 2 or 1)
local terminator = widechar and {0x0, 0x0} or {0x0}
local addr = allocateMemory(memSize)
if addr == nil or addr == 0 then
print("allocateMemory() error!")
return nil
end
strings[num] = addr
writeString(addr,value,widechar)
writeBytes(addr+len,terminator)
registerSymbol("strings_" .. tostring(num), addr)
return addr
end
--------------------------------------------------------------------------------
function AllocateMemoryWriteString(value)
local len = string.len(value)
local strAddr = WriteStringEx(value,len)
local strMetaAddr = AllocateMemoryEx("StrMeta",16)
local strPtrAddr = strMetaAddr
local strLenAddr = strMetaAddr + getPointerSize()
writePointer(strPtrAddr,strAddr)
writeInteger(strLenAddr,len)
end
--------------------------------------------------------------------------------
function getSubAddress(mr, newOffsetCount)
local addr = getAddressSafe(mr.Address)
if newOffsetCount >= mr.OffsetCount then return mr.CurrentAddress end
if newOffsetCount > 0 then
for i = mr.OffsetCount-1, mr.OffsetCount-newOffsetCount, -1 do
local ptr = readPointer(addr)
local ofs = tonumber(mr.OffsetText[i],16)
if ptr == nil or ptr == 0 or ofs == nil then return 0 end
addr = ptr + ofs
end
end
return addr
end
--------------------------------------------------------------------------------
function UDFChangeValue_Close(sender)
UDFChangeValue.ModalResult = sender.ModalResult
end
--------------------------------------------------------------------------------
function UDFChangeValue_FormShow(sender)
UDFChangeValue.CEMemoStringValue.setFocus()
end
--------------------------------------------------------------------------------
function OnValueChangeEx( addresslist, mr )
if mr.Type == vtString and mr.OffsetCount > 0 then
local memo = UDFChangeValue.CEMemoStringValue
memo.Lines.Text = mr.Value
memo.selectAll()
if UDFChangeValue.showModal() == mrOK then
local newValue = memo.Lines.Text
local newLen = string.len(newValue)
local oldLen = string.len(mr.Value)
if newLen ~= oldLen then
local strPtrAddr = getSubAddress(mr, mr.OffsetCount-1)
local strLenAddr = strPtrAddr + getPointerSize()
if newLen > oldLen and UDFChangeValue.CECheckboxStringValue.Checked then
local size = (newLen+1)*(mr.String.Unicode and 2 or 1)
writePointer(strPtrAddr, WriteStringEx(newValue, newLen, mr.String.Unicode))
end
writeInteger(strLenAddr,newLen)
end
mr.Value = newValue
end
return true
end
return false -- use default editing UI
end
--------------------------------------------------------------------------------
getAddressList().OnValueChange = OnValueChangeEx
AllocateMemoryWriteString("Hello World!")
{$asm}
[DISABLE]
{$lua}
--------------------------------------------------------------------------------
local function DeleteUserdefinedSymbols()
local mv = getMemoryViewForm()
if mv.frmSymbolhandler == nil then
mv.Symbolhandler1.doClick()
mv.frmSymbolhandler.Close()
end
local items = mv.frmSymbolhandler.ListView1.Items
for i=0,items.Count-1 do
unregisterSymbol(items.Item[0].Caption)
end
end
--------------------------------------------------------------------------------
DeleteUserdefinedSymbols()
DeAllocateMemoryEx("StrMeta")