Feel free to use it or write your own...
This will enable mono before script is execute & disable mono when script finish executing...
Code: Select all
function onMemRecPreExecute(memoryrecord, newstate)
if memoryrecord.Type == vtAutoAssembler then LaunchMonoDataCollector()end
end
function onMemRecPostExecute(memoryrecord, newState, succeeded )
if memoryrecord.Type == vtAutoAssembler then
miMonoActivateClick(sender)
end
end
Public Static variable parsing
print the variable class name so you know which is which...
Code: Select all
function mono_printAllStaticfrom(Address,size)
Address=getAddressSafe(Address)
if not size then size=0x100 end
local i=0
local j=1
while(i=#list then break end
end
if opc:find('],') then
opc=opc:sub(opc:find("%[")+1,opc:find("]")-1)
if tonumber(opc,16) then
local currentaddress, classaddress, classname=mono_object_findRealStartOfObject(readPointer(opc))
for j=1,#list do
if classname==list[j] then unregisterSymbol(list[j]) registerSymbol(list[j],opc,true) k=k+1 break end
end
if k>=#list then break end
end
end
i=i+getInstructionSize(Address+i)
end
end
Class searching
return a list of classes that contain that name
Code: Select all
function mono_find_classes(namespace,classname)
local ass=mono_enumAssemblies()
local classes,k={},1
if string.find(classname,':') then parent=classname:sub(1,string.find(classname,':')-1) classname=classname:sub(string.find(classname,':')+1,classname:len()) end
if ass==nil then return nil end
for i=1, #ass do
if monopipe==nil then print('mono not active...')return 0 end
local c=mono_image_enumClasses(mono_getImageFromAssembly(ass[i]))
if c then
local j
for j=1, #c do
if c[j].namespace==namespace and string.find(c[j].classname,classname) then classes[k]=c[j] k=k+1 end
end
end
end
return classes
end
good for finding struct that has the same name as class or "class in class", by providing field name or field type name
Code: Select all
function mono_findClassWithField(namespace,classname,fieldname,fieldtypename)
local class=mono_find_classes(namespace,classname)
for i=1,#class do
local fields =mono_class_enumFields(class[i].class,true)
for j=1,#fields do
if fieldname and fieldname==fields[j].name then return class[i].class end
if fieldtypename and fieldtypename==fields[j].typename then return class[i].class end
end
end
end
function/method searching
return a list of methods that have the same name inside that class...also work for method that reside inside "class in class"
Code: Select all
function mono_findMethods(namespace,classname,methodname)
if not namespace then namespace='' end
local class=mono_find_classes(namespace,classname)
local result,m,methods={},1
for i=1,#class do
methods = mono_class_enumMethods(class[i].class,false)
for l,v in ipairs(methods) do if v.name==methodname then result[m]=v.method m=m+1 end end
end
return result
end
return a method that has the highest score according to filter set... work for finding overloaded method...
you can put printall as true to print all the method's signature found, so you know the format...
Code: Select all
function mono_findMethodBySignature(classname,methodname,paramtype,paramname,rettype,printall)
local methods=mono_findMethods(classname,methodname)
local score,result,ptype,pname,rtype,j={}
if #methods==0 then return nil end
for i=1,#methods do
score[i]=0
ptype,pname,rtype=mono_method_getSignature(methods[i])
if printall then
print('\n'..i..'.'..ptype..'\n{')
for k=1,#pname do
print(' '..pname[k])
end
print('}\n'..rtype)
end
if paramtype and paramtype==ptype then score[i]=score[i]+1 end
if paramname and type(paramname)==type({}) then
if #paramname==#pname then score[i]=score[i]+1 end
for j=1,#paramname do
if paramname[j]==pname[j] then score[i]=score[i]+1 end
end
end
if rettype and rettype==rtype then score[i]=score[i]+1 end
if not result and score[i]>0 then result=i
elseif result and score[i]>score[result] then result=i end
end
if result then result=methods[result] end
return result
end
return the method's compile address as hexadecimal string
Code: Select all
function mono_compile_methodS(method)
local address=mono_compile_method(method)
if not address then return address end
return string.format('%X',address)
end
Dissect Structure
Creating dissect structure for use in script & table so when offset change when the game update, you dont have to update your table...
will dump all members for that class/struct
Code: Select all
function monocreatestruct(namespace,classname)
local struct=isStructExist(classname)
if struct then struct:Destroy() end
local fields =mono_class_enumFields(mono_findClass(namespace,classname),true)
local struct=createStructure(classname)
struct.beginUpdate()
for n=1,#fields do
local e=struct.addElement()
e.Offset=fields[n].offset
e.Name=fields[n].name
e.Vartype=monoTypeToVarType(fields[n].monotype)
end
struct.endUpdate()
struct.addToGlobalStructureList()
end
function monocreatestructC(class)
local classname=mono_class_getName(class)
local struct=isStructExist(classname)
if struct then struct:Destroy() end
local fields =mono_class_enumFields(class,true)
local struct=createStructure(classname)
struct.beginUpdate()
for n=1,#fields do
local e=struct.addElement()
e.Offset=fields[n].offset
e.Name=fields[n].name
e.Vartype=monoTypeToVarType(fields[n].monotype)
end
struct.endUpdate()
struct.addToGlobalStructureList()
end
Code injection/ function/method manipulating...
Since, mono use jit compilation, this function is written to be just like jit compilation,lol, which not like the static way,
this function calculate the bytes need to replace for jump & its nop & save the instruction & bytes prior replacing...
So, automatic stuff...
Dont know how reliable it is...
Code: Select all
function getInsForJump(address,registername,destination,allocsize,SharedMemoryName)
address = getAddressSafe(address)
if not address then error('getInsForJump address nil') return end
if not allocsize then allocsize=4096 end
destination=getAddressSafe(destination)
if not destination then
if not SharedMemoryName then destination = allocateMemory(allocsize,address)
else destination = allocateSharedMemory(SharedMemoryName,allocsize) end
end
local size = (address+5-destination>0x7FFFFFFF) and 14 or 5
if registername then
unregisterSymbol(registername)
registerSymbol(registername,destination,true)
end
local opcodes = {}
local i = 0
while(i<size) do
local ext, opc=splitDisassembledString(disassemble(address+i))
opcodes[#opcodes+1] = opc
i=i+getInstructionSize(address+i)
end
local copy = table.concat(opcodes,'\r\n')
local readAsTable = true
local byt = readBytes(address,i,readAsTable)
for j=1,#byt do byt[j] = ('%02X'):format(byt[j]) end
local bytes = table.concat(byt, ' ')
return i,copy,bytes,size,destination
end
function enablescript(name,registername,addressname,script,disable)
local address=getAddress(addressname)
if disable then script=(script):format(address,registername,readBytes(registername,1))
else
local i,copy,bytes,size =getInsForJump(address,name)
script=(script):format(registername, registername, name, copy, registername, i, bytes, address)..string.rep('nop\n',i-size)..'returnhere:'
end
local success,erro=autoAssembleCheck(script)
if not success then print('\n'..erro..'\n')
local scriptstr=createStringlist()scriptstr.Text=script
for j=0,scriptstr.Count-1 do print(string.format('%u\t%s',j+1,scriptstr[j])) end
if not disable then deAlloc(name)unregisterSymbol(name)end
error(name..' autoAssemble failed')
end
autoAssemble(script)
if disable then deAlloc(name)unregisterSymbol(name)unregisterSymbol(registername)end
end
template:
Code: Select all
[ENABLE]
enablescript('symbol_name_for_allocate_address','symbol_name_for_saved_original_bytes','hook_address',[[
label(newmem)
label(returnhere)
label(%s)
registersymbol(%s)
%s:
newmem:
//your code here
%s //<--original code
//or code here
jmp returnhere
%s:
db %X %s
%X:
jmp newmem
]])
[DISABLE]
enablescript('symbol_name_for_allocate_address','symbol_name_for_saved_original_bytes','hook_address',[[
%X:
readmem(%s+1,%u)
]],true)
Just a function to run AA script inside Lua script with error printing,lol....
Code: Select all
function AAscript(script)
local success,erro=autoAssembleCheck(script)
if not success then
print('\n'..erro..'\n')
local scriptstr=createStringlist()scriptstr.Text=script
for j=0,scriptstr.Count-1 do print(string.format('%u\t%s',j+1,scriptstr[j])) end
error('autoAssemble failed')
end
autoAssemble(script)
end
I use this instead of aobscan, because although the instruction opcode is the same, the bytes will probably change every time jit compilation occur...
Code: Select all
function findOpcodes(address,opcode,size)
if not size then size=0x50 end
address=getAddressSafe(address)
if not address then return nil end
local addr={}
local i=0
local j=1
while(i<size) do
local ext, opc, byt, add=splitDisassembledString(disassemble(address+i))
if string.find(opc,opcode) then
addr[j]=address+i
j=j+1
end
i=i+getInstructionSize(address+i)
end
return addr
end
index Disassemble, I use this when ever I want to make a call hook, because making a call hook from pre-function will most likely crash the game...
Code: Select all
function indexdism(Address)
Address=getAddressSafe(Address)
if not Address then return nil end
size=0x100
local addr={}
local i=0
local j=1
while(i<size) do
addr[j]={}
addr[j].ext, addr[j].opc, addr[j].byt, addr[j].add=splitDisassembledString(disassemble(Address+i))
j=j+1
i=i+getInstructionSize(Address+i)
end
return addr
end