cheat-engine/Cheat Engine/bin/autorun/java.lua
2014-01-25 14:29:55 +00:00

418 lines
12 KiB
Lua

JAVACMD_STARTCODECALLBACKS=0
JAVACMD_STOPCODECALLBACKS=1
JAVACODECMD_METHODLOAD=0
JAVACODECMD_METHODUNLOAD=1
JAVACODECMD_DYNAMICCODEGENERATED=2
function getFieldFromType(type, field, infloopprotection)
if type==nil then return nil end
if infloopprotection==nil then
infloopprotection=0
else
infloopprotection=infloopprotection+1
if infloopprotection>20 then
return nil
end
end
type=type:gsub("<.->(.-)","<%1>") --replace the <xxx> part with <>
local Struct=JavaStructs[type]
if (Struct==nil) or (Struct[field]==nil) then
return getFieldFromType(JavaTypes[type].Alternate, field, infloopprotection) --check the super type if that one has fields
else
return Struct[field]
end
end
function getKlassFromObject(object)
return readQword(object+getFieldFromType("oopDesc","_metadata._klass").Offset)+JavaTypes["oopDesc"].Size
end
function CollectJavaSymbolsNonInjected(thread)
JavaStructs={}
JavaTypes={}
local s,s2
s=readPointer("jvm.gHotSpotVMStructs")
VMStructEntryTypeNameOffset=readInteger("jvm.gHotSpotVMStructEntryTypeNameOffset")
VMStructEntryFieldNameOffset=readInteger("jvm.gHotSpotVMStructEntryFieldNameOffset")
VMStructEntryTypestringOffset=readInteger("jvm.gHotSpotVMStructEntryTypestringOffset")
VMStructEntryIsStaticOffset=readInteger("jvm.gHotSpotVMStructEntryIsStaticOffset")
VMStructEntryOffsetOffset=readInteger("jvm.gHotSpotVMStructEntryOffsetOffset")
VMStructEntryAddressOffset=readInteger("jvm.gHotSpotVMStructEntryAddressOffset")
VMStructEntryArrayStride=readInteger("jvm.gHotSpotVMStructEntryArrayStride")
--[[
const char* typeName; // The type name containing the given field (example: "Klass")
const char* fieldName; // The field name within the type (example: "_name")
const char* Typestring; // Quoted name of the type of this field (example: "Symbol*";
// parsed in Java to ensure type correctness
int32_t isStatic; // Indicates whether following field is an offset or an address
uint64_t offset; // Offset of field within structure; only used for nonstatic fields
void* address; // Address of field; only used for static fields
// ("offset" can not be reused because of apparent SparcWorks compiler bug
// in generation of initializer data)
--]]
while readString(readQword(s+VMStructEntryTypeNameOffset))~=nil do
local a,b,c,d;
a=readString(readPointer(s+VMStructEntryTypeNameOffset),255)
b=readString(readPointer(s+VMStructEntryFieldNameOffset),255)
c=readString(readPointer(s+VMStructEntryTypestringOffset),255)
d=readPointer(s+VMStructEntryIsStaticOffset)
if a and b and c then
if JavaStructs[a]==nil then
JavaStructs[a]={}
end
JavaStructs[a][b]={}
JavaStructs[a][b].Typestring=c
if d==0 then
JavaStructs[a][b].Offset=readPointer(s+VMStructEntryOffsetOffset)
else
JavaStructs[a][b].Address=readPointer(s+VMStructEntryAddressOffset)
end
--if d~=0 then
-- print(a.." - "..b.." - "..c.." : "..string.format("%x ( %x )",readPointer(s+VMStructEntryAddressOffset), readPointer(readPointer(s+VMStructEntryAddressOffset)) ))
--else
-- print(a.." - "..b.." - "..c.." : "..string.format("%x",readPointer(s+VMStructEntryOffsetOffset)))
--end
end
s=s+VMStructEntryArrayStride
end
--print("--------------------------------------------------------------------------------")
s2=readPointer("jvm.gHotSpotVMTypes")
VMTypeEntryTypeNameOffset=readInteger("jvm.gHotSpotVMTypeEntryTypeNameOffset")
VMTypeEntrySuperclassNameOffset=readInteger("jvm.gHotSpotVMTypeEntrySuperclassNameOffset")
VMTypeEntryIsOopTypeOffset=readInteger("jvm.gHotSpotVMTypeEntryIsOopTypeOffset")
VMTypeEntryIsIntegerTypeOffset=readInteger("jvm.gHotSpotVMTypeEntryIsIntegerTypeOffset")
VMTypeEntryIsUnsignedOffset=readInteger("jvm.gHotSpotVMTypeEntryIsUnsignedOffset")
VMTypeEntrySizeOffset=readInteger("jvm.gHotSpotVMTypeEntrySizeOffset")
VMTypeEntryArrayStride=readInteger("jvm.gHotSpotVMTypeEntryArrayStride")
while readString(readPointer(s2+VMTypeEntryTypeNameOffset))~=nil do
local a,b,isInteger, isOop, size;
a=readString(readPointer(s2+VMTypeEntryTypeNameOffset),255)
b=readString(readPointer(s2+VMTypeEntrySuperclassNameOffset),255)
isOop=readInteger(s2+VMTypeEntryIsOopTypeOffset)
isInteger=readInteger(s2+VMTypeEntryIsIntegerTypeOffset)
size=readInteger(s2+VMTypeEntrySizeOffset)
if a then
local _a,_b
_a=a:gsub("<.->(.-)","<%1>")
JavaTypes[_a]={}
JavaTypes[_a].Size=size
if b then
_b=b:gsub("<.->(.-)","<%1>")
JavaTypes[_a].Alternate=_b
end
end
local r=''
if a then
r=r..a
end
if b then
r=r.." - "..b
end
--print(r.." (size="..size..")")
s2=s2+VMTypeEntryArrayStride
end
-- print("-------------------------------------------------")
s=readPointer("jvm.gHotSpotVMIntConstants")
VMIntConstantEntryNameOffset=readInteger("jvm.gHotSpotVMIntConstantEntryNameOffset")
VMIntConstantEntryValueOffset=readInteger("jvm.gHotSpotVMIntConstantEntryValueOffset")
VMIntConstantEntryArrayStride=readInteger("jvm.gHotSpotVMIntConstantEntryArrayStride")
while readString(readPointer(s+VMIntConstantEntryNameOffset))~=nil do
local name,value
name=readString(readPointer(s+VMIntConstantEntryNameOffset))
value=readInteger(s+VMIntConstantEntryValueOffset)
--print(name.."="..string.format("%x",value))
s=s+VMIntConstantEntryArrayStride
end
--print("-------------------------------------------------")
s=readPointer("jvm.gHotSpotVMLongConstants")
VMLongConstantEntryNameOffset=readInteger("jvm.gHotSpotVMLongConstantEntryNameOffset")
VMLongConstantEntryValueOffset=readInteger("jvm.gHotSpotVMLongConstantEntryValueOffset")
VMLongConstantEntryArrayStride=readInteger("jvm.gHotSpotVMLongConstantEntryArrayStride")
while readString(readPointer(s+VMLongConstantEntryNameOffset))~=nil do
local name,value
name=readString(readPointer(s+VMLongConstantEntryNameOffset))
value=readQword(s+VMLongConstantEntryValueOffset)
--print(name.."="..string.format("%x",value))
s=s+VMLongConstantEntryArrayStride
end
--Fetch the interpreter functions
local InterpreterFunctionList=getFieldFromType('AbstractInterpreter', '_code').Address
local BufferOffset=getFieldFromType('StubQueue', '_stub_buffer').Offset
local QueueEndOffset=getFieldFromType('StubQueue', '_queue_end').Offset
local InterpreterCodeletSizeOffset=getFieldFromType('InterpreterCodelet', '_size').Offset
local InterpreterCodeletDescriptionOffset=getFieldFromType('InterpreterCodelet', '_description').Offset
local InterpreterCodeletHeaderSize=JavaTypes['InterpreterCodelet'].Size
local InterpreterCodeletHeaderSizeAligned
InterpreterCodeletHeaderSizeAligned=InterpreterCodeletHeaderSize
if targetIs64Bit() then
--increase InterpreterCodeletHeaderSizeAligned so it's dividable by 32
if (InterpreterCodeletHeaderSizeAligned % 32)~=0 then
InterpreterCodeletHeaderSizeAligned=(InterpreterCodeletHeaderSizeAligned+32) - (InterpreterCodeletHeaderSizeAligned % 32)
end
else
--increase InterpreterCodeletHeaderSizeAligned so it's dividable by 16
if (InterpreterCodeletHeaderSizeAligned % 16)~=0 then
InterpreterCodeletHeaderSizeAligned=(InterpreterCodeletHeaderSizeAligned+16) - (InterpreterCodeletHeaderSizeAligned % 16)
end
end
StubQueueAddress=readPointer(InterpreterFunctionList)
BufferStart=readPointer(StubQueueAddress+BufferOffset)
BufferEnd=BufferStart+readInteger(StubQueueAddress+QueueEndOffset)
CurrentPos=BufferStart
while (CurrentPos<BufferEnd) do
local CodeletSize=readInteger(CurrentPos+InterpreterCodeletSizeOffset)
local Description=readString(readInteger(CurrentPos+InterpreterCodeletDescriptionOffset))
local Codestart=CurrentPos+InterpreterCodeletHeaderSizeAligned
--print(string.format("%x = %s", Codestart, Description))
JavaSymbols.addSymbol("","jInterpreter_"..Description,Codestart, CodeletSize-InterpreterCodeletHeaderSizeAligned)
CurrentPos=CurrentPos+CodeletSize
end
end
function javaInjectAgent()
if (JavaSymbols==nil) then
JavaSymbols=createSymbolList()
else
JavaSymbols.clear()
end
createNativeThread(CollectJavaSymbolsNonInjected)
if (JavaEventThread~=nil) then
JavaEventListener_Terminated=true
JavaEventThread.waitfor()
JavaEventThread=nil
end
if (javapipe~=nil) then
javapipe.destroy()
javapipe=nil
end
autoAssemble([[
globalalloc(bla,1024)
globalalloc(cmd,16)
globalalloc(arg0,256)
globalalloc(arg1,256)
globalalloc(arg2,256)
globalalloc(result,4)
globalalloc(pipename,256)
cmd:
db 'load',0
arg0:
db 'F:\svn\Cheat Engine\bin\autorun\dlls\CEJVMTI64',0
arg1:
db 0
arg2:
db 0
pipename:
db '\\.\pipe\cejavapipe',0
bla:
sub rsp,8
sub rsp,30
mov rcx,cmd
mov rdx,arg0
mov r8,arg1
mov r9,arg2
mov [rsp],cmd
mov [rsp+8],arg0
mov [rsp+10],arg1
mov [rsp+18],arg2
mov [rsp+20],pipename
call jvm.JVM_EnqueueOperation
mov [result],eax
add rsp,38
ret
createthread(bla)
]])
--wait till attached
local timeout=getTickCount()+5000000; --5 seconds
while (javapipe==nil) and (getTickCount()<timeout) do
javapipe=connectToPipe('cejavadc_pid'..getOpenedProcessID())
end
if (javapipe==nil) then
return 0 --failure
end
java_StartListeneningForEvents()
JavaSymbols.register()
end
function JavaEventListener(thread)
--this code runs in another thread
local EVENTCMD_METHODLOAD=0
local EVENTCMD_METHODUNLOAD=1
local EVENTCMD_DYNAMICCODEGENERATED=2
local JavaEventPipe
local timeout=getTickCount()+5000000; --5 seconds
while (JavaEventPipe==nil) and (getTickCount()<timeout) do
JavaEventPipe=connectToPipe('cejavaevents_pid'..getOpenedProcessID())
end
if (JavaEventPipe==nil) then
return --failure
end
while JavaEventListener_Terminated==false do
local command=JavaEventPipe.readByte()
if command==EVENTCMD_METHODLOAD then --methodload
local method=JavaEventPipe.readQword()
local code_size=JavaEventPipe.readDword()
local code_addr=JavaEventPipe.readQword()
local ssize=JavaEventPipe.readWord()
local classname=JavaEventPipe.readString(ssize)
ssize=JavaEventPipe.readWord()
local methodname=JavaEventPipe.readString(ssize)
ssize=JavaEventPipe.readWord()
local methodsig=JavaEventPipe.readString(ssize)
local name=classname.."."..methodname..methodsig
print(string.format("Methodload: %s - (%x) %x-%x", name, method, code_addr, code_addr+code_size))
--
elseif command==EVENTCMD_METHODUNLOAD then --methodunload
print("EVENTCMD_METHODUNLOAD")
--
elseif command==EVENTCMD_DYNAMICCODEGENERATED then --DynamicCodeGenerated
local ssize
local address=JavaEventPipe.readQword()
local length=JavaEventPipe.readDword()
ssize=JavaEventPipe.readWord()
local name=JavaEventPipe.readString(ssize)
print(string.format("DynamicCode: %s - %x-%x", name, address, address+length))
--
elseif command==nil then
print("Disconnected")
break
else
print("Unexpected event received") --synchronize isn't necesary for print as that function is designed to synchronize internally
break --unknown command
end
end
JavaEventPipe.destroy();
end
function java_StartListeneningForEvents()
javapipe.lock();
javapipe.writeByte(JAVACMD_STARTCODECALLBACKS)
--the javapipe will now be frozen until a the javaeventpipe makes an connection
JavaEventListener_Terminated=false
JavaEventThread=createNativeThread(JavaEventListener);
local result=javapipe.readByte()==1
javapipe.unlock();
return result
end