java.lua 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478
  1. --todo: split up into multiple units and use the java table for the methods as well
  2. JAVACMD_STARTCODECALLBACKS=0
  3. JAVACMD_STOPCODECALLBACKS=1
  4. JAVACMD_GETLOADEDCLASSES=2
  5. JAVACMD_DEREFERENCELOCALOBJECT=3
  6. JAVACMD_GETCLASSMETHODS=4
  7. JAVACMD_GETCLASSFIELDS=5
  8. JAVACMD_GETIMPLEMENTEDINTERFACES=6
  9. JAVAVMD_FINDREFERENCESTOOBJECT=7
  10. JAVACMD_FINDJOBJECT=8
  11. JAVACMD_GETCLASSSIGNATURE=9 --=getClassName
  12. JAVACMD_GETSUPERCLASS=10
  13. JAVACMD_GETOBJECTCLASS=11
  14. JAVACMD_GETCLASSDATA=12
  15. JAVACMD_REDEFINECLASS=13
  16. JAVACMD_FINDCLASS=14
  17. JAVACMD_GETCAPABILITIES=15
  18. JAVACMD_GETMETHODNAME=16 --gets the methodname and the signature
  19. JAVACMD_INVOKEMETHOD=17
  20. JAVACMD_FINDCLASSOBJECTS=18 --find objects that belong to the given class
  21. JAVACMD_ADDTOBOOTSTRAPCLASSLOADERPATH=19
  22. JAVACMD_ADDTOSYSTEMCLASSLOADERPATH=20
  23. JAVACMD_PUSHLOCALFRAME=21
  24. JAVACMD_POPLOCALFRAME=22
  25. JAVACMD_GETFIELDDECLARINGCLASS=23
  26. JAVACMD_GETFIELDSIGNATURE=24
  27. JAVACMD_GETFIELD=25
  28. JAVACMD_SETFIELD=26
  29. JAVACMD_STARTSCAN=27
  30. JAVACMD_REFINESCANRESULTS=28
  31. JAVACMD_GETSCANRESULTS=29
  32. JAVACMD_FINDWHATWRITES=30
  33. JAVACMD_STOPFINDWHATWRITES=31
  34. JAVACMD_GETMETHODDECLARINGCLASS=32
  35. JAVACODECMD_METHODLOAD=0
  36. JAVACODECMD_METHODUNLOAD=1
  37. JAVACODECMD_DYNAMICCODEGENERATED=2
  38. JAVACODECMD_TERMINATED=255
  39. JAVA_TIMEOUT=5000 --5 seconds
  40. function getFieldFromType(type, field, infloopprotection)
  41. if type==nil then return nil end
  42. if infloopprotection==nil then
  43. infloopprotection=0
  44. else
  45. infloopprotection=infloopprotection+1
  46. if infloopprotection>20 then
  47. return nil
  48. end
  49. end
  50. type=type:gsub("<.->(.-)","<%1>") --replace the <xxx> part with <>
  51. local Struct=JavaStructs[type]
  52. if (Struct==nil) or (Struct[field]==nil) then
  53. return getFieldFromType(JavaTypes[type].Alternate, field, infloopprotection) --check the super type if that one has fields
  54. else
  55. return Struct[field]
  56. end
  57. end
  58. function getKlassFromObject(object)
  59. return readQword(object+getFieldFromType("oopDesc","_metadata._klass").Offset)+JavaTypes["oopDesc"].Size
  60. end
  61. function CollectJavaSymbolsNonInjected(thread)
  62. if thread~=nil then
  63. thread.name="CollectJavaSymbolsNonInjected"
  64. end
  65. JavaStructs={}
  66. JavaTypes={}
  67. local s,s2
  68. s=readPointer("jvm.gHotSpotVMStructs")
  69. if (s==nil) or (s==0) then
  70. return --invalid JVM
  71. end
  72. VMStructEntryTypeNameOffset=readInteger("jvm.gHotSpotVMStructEntryTypeNameOffset")
  73. VMStructEntryFieldNameOffset=readInteger("jvm.gHotSpotVMStructEntryFieldNameOffset")
  74. VMStructEntryTypestringOffset=readInteger("jvm.gHotSpotVMStructEntryTypestringOffset")
  75. VMStructEntryIsStaticOffset=readInteger("jvm.gHotSpotVMStructEntryIsStaticOffset")
  76. VMStructEntryOffsetOffset=readInteger("jvm.gHotSpotVMStructEntryOffsetOffset")
  77. VMStructEntryAddressOffset=readInteger("jvm.gHotSpotVMStructEntryAddressOffset")
  78. VMStructEntryArrayStride=readInteger("jvm.gHotSpotVMStructEntryArrayStride")
  79. --[[
  80. const char* typeName; // The type name containing the given field (example: "Klass")
  81. const char* fieldName; // The field name within the type (example: "_name")
  82. const char* Typestring; // Quoted name of the type of this field (example: "Symbol*";
  83. // parsed in Java to ensure type correctness
  84. int32_t isStatic; // Indicates whether following field is an offset or an address
  85. uint64_t offset; // Offset of field within structure; only used for nonstatic fields
  86. void* address; // Address of field; only used for static fields
  87. // ("offset" can not be reused because of apparent SparcWorks compiler bug
  88. // in generation of initializer data)
  89. --]]
  90. while readString(readQword(s+VMStructEntryTypeNameOffset))~=nil do
  91. local a,b,c,d;
  92. a=readString(readPointer(s+VMStructEntryTypeNameOffset),255)
  93. b=readString(readPointer(s+VMStructEntryFieldNameOffset),255)
  94. c=readString(readPointer(s+VMStructEntryTypestringOffset),255)
  95. d=readPointer(s+VMStructEntryIsStaticOffset)
  96. if a and b and c then
  97. if JavaStructs[a]==nil then
  98. JavaStructs[a]={}
  99. end
  100. JavaStructs[a][b]={}
  101. JavaStructs[a][b].Typestring=c
  102. if d==0 then
  103. JavaStructs[a][b].Offset=readPointer(s+VMStructEntryOffsetOffset)
  104. else
  105. JavaStructs[a][b].Address=readPointer(s+VMStructEntryAddressOffset)
  106. end
  107. --if d~=0 then
  108. -- print(a.." - "..b.." - "..c.." : "..string.format("%x ( %x )",readPointer(s+VMStructEntryAddressOffset), readPointer(readPointer(s+VMStructEntryAddressOffset)) ))
  109. --else
  110. -- print(a.." - "..b.." - "..c.." : "..string.format("%x",readPointer(s+VMStructEntryOffsetOffset)))
  111. --end
  112. end
  113. s=s+VMStructEntryArrayStride
  114. end
  115. --print("--------------------------------------------------------------------------------")
  116. s2=readPointer("jvm.gHotSpotVMTypes")
  117. VMTypeEntryTypeNameOffset=readInteger("jvm.gHotSpotVMTypeEntryTypeNameOffset")
  118. VMTypeEntrySuperclassNameOffset=readInteger("jvm.gHotSpotVMTypeEntrySuperclassNameOffset")
  119. VMTypeEntryIsOopTypeOffset=readInteger("jvm.gHotSpotVMTypeEntryIsOopTypeOffset")
  120. VMTypeEntryIsIntegerTypeOffset=readInteger("jvm.gHotSpotVMTypeEntryIsIntegerTypeOffset")
  121. VMTypeEntryIsUnsignedOffset=readInteger("jvm.gHotSpotVMTypeEntryIsUnsignedOffset")
  122. VMTypeEntrySizeOffset=readInteger("jvm.gHotSpotVMTypeEntrySizeOffset")
  123. VMTypeEntryArrayStride=readInteger("jvm.gHotSpotVMTypeEntryArrayStride")
  124. while readString(readPointer(s2+VMTypeEntryTypeNameOffset))~=nil do
  125. local a,b,isInteger, isOop, size;
  126. a=readString(readPointer(s2+VMTypeEntryTypeNameOffset),255)
  127. b=readString(readPointer(s2+VMTypeEntrySuperclassNameOffset),255)
  128. isOop=readInteger(s2+VMTypeEntryIsOopTypeOffset)
  129. isInteger=readInteger(s2+VMTypeEntryIsIntegerTypeOffset)
  130. size=readInteger(s2+VMTypeEntrySizeOffset)
  131. if a then
  132. local _a,_b
  133. _a=a:gsub("<.->(.-)","<%1>")
  134. JavaTypes[_a]={}
  135. JavaTypes[_a].Size=size
  136. if b then
  137. _b=b:gsub("<.->(.-)","<%1>")
  138. JavaTypes[_a].Alternate=_b
  139. end
  140. end
  141. local r=''
  142. if a then
  143. r=r..a
  144. end
  145. if b then
  146. r=r.." - "..b
  147. end
  148. --print(r.." (size="..size..")")
  149. s2=s2+VMTypeEntryArrayStride
  150. end
  151. -- print("-------------------------------------------------")
  152. --[[
  153. s=readPointer("jvm.gHotSpotVMIntConstants")
  154. VMIntConstantEntryNameOffset=readInteger("jvm.gHotSpotVMIntConstantEntryNameOffset")
  155. VMIntConstantEntryValueOffset=readInteger("jvm.gHotSpotVMIntConstantEntryValueOffset")
  156. VMIntConstantEntryArrayStride=readInteger("jvm.gHotSpotVMIntConstantEntryArrayStride")
  157. while readString(readPointer(s+VMIntConstantEntryNameOffset))~=nil do
  158. local name,value
  159. name=readString(readPointer(s+VMIntConstantEntryNameOffset))
  160. value=readInteger(s+VMIntConstantEntryValueOffset)
  161. --print(name.."="..string.format("%x",value))
  162. s=s+VMIntConstantEntryArrayStride
  163. end
  164. --print("-------------------------------------------------")
  165. s=readPointer("jvm.gHotSpotVMLongConstants")
  166. VMLongConstantEntryNameOffset=readInteger("jvm.gHotSpotVMLongConstantEntryNameOffset")
  167. VMLongConstantEntryValueOffset=readInteger("jvm.gHotSpotVMLongConstantEntryValueOffset")
  168. VMLongConstantEntryArrayStride=readInteger("jvm.gHotSpotVMLongConstantEntryArrayStride")
  169. while readString(readPointer(s+VMLongConstantEntryNameOffset))~=nil do
  170. local name,value
  171. name=readString(readPointer(s+VMLongConstantEntryNameOffset))
  172. value=readQword(s+VMLongConstantEntryValueOffset)
  173. --print(name.."="..string.format("%x",value))
  174. s=s+VMLongConstantEntryArrayStride
  175. end
  176. --Fetch the interpreter functions
  177. local InterpreterFunctionList=getFieldFromType('AbstractInterpreter', '_code').Address
  178. local BufferOffset=getFieldFromType('StubQueue', '_stub_buffer').Offset
  179. local QueueEndOffset=getFieldFromType('StubQueue', '_queue_end').Offset
  180. local InterpreterCodeletSizeOffset=getFieldFromType('InterpreterCodelet', '_size').Offset
  181. local InterpreterCodeletDescriptionOffset=getFieldFromType('InterpreterCodelet', '_description').Offset
  182. local InterpreterCodeletHeaderSize=JavaTypes['InterpreterCodelet'].Size
  183. local InterpreterCodeletHeaderSizeAligned
  184. InterpreterCodeletHeaderSizeAligned=InterpreterCodeletHeaderSize
  185. if targetIs64Bit() then
  186. --increase InterpreterCodeletHeaderSizeAligned so it's dividable by 32
  187. if (InterpreterCodeletHeaderSizeAligned % 32)~=0 then
  188. InterpreterCodeletHeaderSizeAligned=(InterpreterCodeletHeaderSizeAligned+32) - (InterpreterCodeletHeaderSizeAligned % 32)
  189. end
  190. else
  191. --increase InterpreterCodeletHeaderSizeAligned so it's dividable by 16
  192. if (InterpreterCodeletHeaderSizeAligned % 16)~=0 then
  193. InterpreterCodeletHeaderSizeAligned=(InterpreterCodeletHeaderSizeAligned+16) - (InterpreterCodeletHeaderSizeAligned % 16)
  194. end
  195. end
  196. StubQueueAddress=readPointer(InterpreterFunctionList)
  197. BufferStart=readPointer(StubQueueAddress+BufferOffset)
  198. BufferEnd=BufferStart+readInteger(StubQueueAddress+QueueEndOffset)
  199. CurrentPos=BufferStart
  200. while (CurrentPos<BufferEnd) do
  201. local CodeletSize=readInteger(CurrentPos+InterpreterCodeletSizeOffset)
  202. local Description=readString(readInteger(CurrentPos+InterpreterCodeletDescriptionOffset))
  203. local Codestart=CurrentPos+InterpreterCodeletHeaderSizeAligned
  204. --print(string.format("%x = %s", Codestart, Description))
  205. JavaSymbols.addSymbol("","jInterpreter_"..Description,Codestart, CodeletSize-InterpreterCodeletHeaderSizeAligned)
  206. CurrentPos=CurrentPos+CodeletSize
  207. end
  208. --]]
  209. JavaHotSpotFieldsLoaded=true
  210. end
  211. function javaInjectAgent()
  212. if (JavaSymbols==nil) then
  213. JavaSymbols=createSymbolList()
  214. else
  215. JavaSymbols.clear()
  216. end
  217. if (java~=nil) and (java.attachedProcess==getOpenedProcessID()) then
  218. return 1
  219. end
  220. createNativeThread(CollectJavaSymbolsNonInjected)
  221. if (javapipe ~= nil) then
  222. javapipe.destroy() --this will cause the pipe listener to destroy the java event server, which will stop the javaeventthread (so no need to wait for that)
  223. javapipe=nil
  224. end
  225. local alreadyinjected=false
  226. if javaInjectedProcesses==nil then
  227. javaInjectedProcesses={}
  228. local oldstate=errorOnLookupFailure(false)
  229. local address=getAddress('CEJVMTI.dll')
  230. if (address~=nil) and (address~=0) then
  231. javaInjectedProcesses[getOpenedProcessID()]=true
  232. alreadyinjected=true
  233. --opened a process with the JVMTI agent already running
  234. end
  235. errorOnLookupFailure(oldstate)
  236. else
  237. --check if already injected
  238. alreadyinjected=javaInjectedProcesses[getOpenedProcessID()]==true
  239. end
  240. local dllpath
  241. if targetIs64Bit() then
  242. dllpath=getCheatEngineDir()..[[autorun\dlls\64\CEJVMTI]]
  243. else
  244. dllpath=getCheatEngineDir()..[[autorun\dlls\32\CEJVMTI]]
  245. end
  246. if (alreadyinjected==false) then
  247. local script=''
  248. if targetIs64Bit() then
  249. script=[[
  250. globalalloc(bla,1024)
  251. globalalloc(cmd,16)
  252. globalalloc(arg0,256)
  253. globalalloc(arg1,256)
  254. globalalloc(arg2,256)
  255. globalalloc(result,4)
  256. globalalloc(pipename,256)
  257. cmd:
  258. db 'load',0
  259. arg0:
  260. db ']]..dllpath..[[',0
  261. arg1:
  262. db 0
  263. arg2:
  264. db 0
  265. pipename:
  266. db '\\.\pipe\cejavapipe',0
  267. bla:
  268. sub rsp,8
  269. sub rsp,30
  270. mov rcx,cmd
  271. mov rdx,arg0
  272. mov r8,arg1
  273. mov r9,arg2
  274. mov [rsp],cmd
  275. mov [rsp+8],arg0
  276. mov [rsp+10],arg1
  277. mov [rsp+18],arg2
  278. mov [rsp+20],pipename
  279. call jvm.JVM_EnqueueOperation
  280. mov [result],eax
  281. add rsp,38
  282. ret
  283. createthread(bla)
  284. ]]
  285. else
  286. script=[[
  287. globalalloc(bla,1024)
  288. globalalloc(cmd,16)
  289. globalalloc(arg0,256)
  290. globalalloc(arg1,256)
  291. globalalloc(arg2,256)
  292. globalalloc(result,4)
  293. globalalloc(pipename,256)
  294. cmd:
  295. db 'load',0
  296. arg0:
  297. db ']]..dllpath..[[',0
  298. arg1:
  299. db 0
  300. arg2:
  301. db 0
  302. pipename:
  303. db '\\.\pipe\cejavapipe',0
  304. bla:
  305. push pipename
  306. push arg2
  307. push arg1
  308. push arg0
  309. push cmd
  310. call jvm.JVM_EnqueueOperation
  311. mov [result],eax
  312. ret
  313. createthread(bla)
  314. ]]
  315. end
  316. if autoAssemble(script)==false then
  317. error('Auto assembler failed:'..script)
  318. end
  319. javaInjectedProcesses[getOpenedProcessID()]=true
  320. end
  321. --wait till attached
  322. local timeout=getTickCount()+JAVA_TIMEOUT
  323. while (javapipe==nil) and (getTickCount()<timeout) do
  324. javapipe=connectToPipe('cejavadc_pid'..getOpenedProcessID())
  325. end
  326. if (javapipe==nil) then
  327. return 0 --failure
  328. end
  329. java_StartListeneningForEvents()
  330. JavaSymbols.register() --make these symbols available to all of cheat engine
  331. java.capabilities=java_getCapabilities()
  332. java.attachedProcess=getOpenedProcessID();
  333. return 1;
  334. end
  335. function JavaEventListener(thread)
  336. if thread~=nil then
  337. thread.name="JavaEventListener"
  338. end
  339. --this code runs in another thread
  340. local EVENTCMD_METHODLOAD=0
  341. local EVENTCMD_METHODUNLOAD=1
  342. local EVENTCMD_DYNAMICCODEGENERATED=2
  343. local EVENTCMD_FIELDMODIFICATION=3
  344. local JavaEventPipe
  345. local timeout=getTickCount()+JAVA_TIMEOUT --5 seconds
  346. while (JavaEventPipe==nil) and (getTickCount()<timeout) do
  347. JavaEventPipe=connectToPipe('cejavaevents_pid'..getOpenedProcessID())
  348. end
  349. if (JavaEventPipe==nil) then
  350. return --failure
  351. end
  352. while true do
  353. local command=JavaEventPipe.readByte()
  354. if command==EVENTCMD_METHODLOAD then --methodload
  355. local size1, size2, size3,ssize,classname, methodname, methodsig
  356. local method=JavaEventPipe.readQword()
  357. local code_size=JavaEventPipe.readDword()
  358. local code_addr=JavaEventPipe.readQword()
  359. size1=JavaEventPipe.readWord()
  360. if (size1>0) then
  361. classname=JavaEventPipe.readString(size1)
  362. else
  363. classname=''
  364. end
  365. size2=JavaEventPipe.readWord()
  366. if (size2>0) then
  367. methodname=JavaEventPipe.readString(size2)
  368. else
  369. methodname=''
  370. end
  371. size3=JavaEventPipe.readWord()
  372. if (size3>0) then
  373. methodsig=JavaEventPipe.readString(size3)
  374. else
  375. methodsig=''
  376. end
  377. local endpos=classname:match'^.*();'
  378. if endpos~=nil then
  379. classname=string.sub(classname,1,endpos-1)
  380. end
  381. local name=classname.."::"..methodname..methodsig
  382. JavaSymbols.addSymbol("",classname.."::"..methodname,code_addr,code_size)
  383. --print(string.format("s1=%d s2=%d s3=%d (cn=%s mn=%s ms=%s)", size1,size2,size3, classname, methodname, methodsig))
  384. --print(string.format("Methodload: %s - (%x) %x-%x", name, method, code_addr, code_addr+code_size))
  385. --
  386. elseif command==EVENTCMD_METHODUNLOAD then --methodunload
  387. local method=JavaEventPipe.readQword()
  388. local code_addr=JavaEventPipe.readQword()
  389. print("EVENTCMD_METHODUNLOAD")
  390. JavaSymbols.deleteSymbol(code_addr)
  391. --
  392. elseif command==EVENTCMD_DYNAMICCODEGENERATED then --DynamicCodeGenerated
  393. local ssize
  394. local address=JavaEventPipe.readQword()
  395. local length=JavaEventPipe.readDword()
  396. ssize=JavaEventPipe.readWord()
  397. local name=JavaEventPipe.readString(ssize)
  398. --print(string.format("DynamicCode: %s - %x-%x", name, address, address+length))
  399. JavaSymbols.addSymbol("",name,address,length)
  400. --
  401. elseif command==EVENTCMD_FIELDMODIFICATION then
  402. --print("EVENTCMD_FIELDMODIFICATION")
  403. local id=JavaEventPipe.readDword()
  404. local entry={}
  405. --print("id=="..id)
  406. entry.methodid=JavaEventPipe.readQword()
  407. entry.location=JavaEventPipe.readQword()
  408. local stackcount=JavaEventPipe.readByte()
  409. local i
  410. local stack={}
  411. --print("stackcount=="..stackcount)
  412. for i=1, stackcount do
  413. stack[i]={}
  414. stack[i].methodid=JavaEventPipe.readQword()
  415. stack[i].location=JavaEventPipe.readQword()
  416. end
  417. entry.stack=stack
  418. if java.findwhatwriteslist~=nil then
  419. local fcd=java.findwhatwriteslist[id]
  420. if fcd~=nil then
  421. --check if this entry is already in the list
  422. local found=false
  423. for i=1, #fcd.entries do
  424. if (fcd.entries[i].methodid==entry.methodid) and (fcd.entries[i].location==entry.location) then
  425. found=true
  426. break
  427. end
  428. end
  429. if not found then
  430. local mname=java_getMethodName(entry.methodid)
  431. local class=java_getMethodDeclaringClass(entry.methodid)
  432. local classname=java_getClassSignature(class)
  433. java_dereferenceLocalObject(class)
  434. entry.classname=classname
  435. entry.methodname=mname
  436. --execute this in the main thread (gui access)
  437. synchronize(function(classname, id, mname)
  438. local fcd=java.findwhatwriteslist[id]
  439. if fcd~=nil then --check that the found code dialog hasn't been freed while waiting for sync
  440. tventry=fcd.lv.items.add()
  441. tventry.Caption=classname
  442. tventry.SubItems.add(string.format('%x: %s', entry.methodid, mname))
  443. tventry.SubItems.add(entry.location)
  444. table.insert(fcd.entries, entry)
  445. end
  446. end, classname, id, mname)
  447. else
  448. -- print("Already in the list")
  449. end
  450. else
  451. -- print("fcd==nil")
  452. end
  453. else
  454. -- print("java.findwhatwriteslist==nil")
  455. end
  456. --print("done")
  457. elseif command==JAVACODECMD_TERMINATED then
  458. print("Java:eventserver terminated")
  459. break
  460. elseif command==nil then
  461. print("Java:Disconnected")
  462. break
  463. else
  464. print("Java:Unexpected event received") --synchronize isn't necesary for print as that function is designed to synchronize internally
  465. break --unknown command
  466. end
  467. end
  468. print("Java:Event handler terminating")
  469. JavaEventPipe.destroy();
  470. end
  471. function java_getCapabilities()
  472. result={}
  473. javapipe.lock()
  474. javapipe.writeByte(JAVACMD_GETCAPABILITIES)
  475. result.can_access_local_variables=javapipe.readByte()==1
  476. result.can_generate_all_class_hook_events=javapipe.readByte()==1
  477. result.can_generate_breakpoint_events=javapipe.readByte()==1
  478. result.can_generate_compiled_method_load_events=javapipe.readByte()==1
  479. result.can_generate_field_access_events=javapipe.readByte()==1
  480. result.can_generate_field_modification_events=javapipe.readByte()==1
  481. result.can_generate_single_step_events=javapipe.readByte()==1
  482. result.can_get_bytecodes=javapipe.readByte()==1
  483. result.can_get_constant_pool=javapipe.readByte()==1
  484. result.can_maintain_original_method_order=javapipe.readByte()==1
  485. result.can_redefine_any_class=javapipe.readByte()==1
  486. result.can_redefine_classes=javapipe.readByte()==1
  487. result.can_retransform_any_class=javapipe.readByte()==1
  488. result.can_retransform_classes=javapipe.readByte()==1
  489. result.can_tag_objects=javapipe.readByte()==1
  490. javapipe.unlock()
  491. return result;
  492. end
  493. function java_StartListeneningForEvents()
  494. javapipe.lock();
  495. javapipe.writeByte(JAVACMD_STARTCODECALLBACKS)
  496. --the javapipe will now be frozen until a javaeventpipe makes an connection
  497. createNativeThread(JavaEventListener);
  498. javapipe.unlock();
  499. end
  500. function java_getLoadedClasses()
  501. javapipe.lock()
  502. javapipe.writeByte(JAVACMD_GETLOADEDCLASSES)
  503. local classcount=javapipe.readDword()
  504. local classes={}
  505. if (classcount==nil) then
  506. return nil
  507. end
  508. if classcount>0 then
  509. local i=0
  510. local length
  511. for i=1,classcount do
  512. classes[i]={}
  513. classes[i].jclass=javapipe.readQword() --this is a pointer to a pointer to java.lang.class. To get the offset where klass is stored use getFieldFromType("java_lang_Class", "_klass_offset") (The klass contains a _fields field which points to a array which contains the offset of the fields. Might be useful)
  514. length=javapipe.readWord()
  515. classes[i].signature=javapipe.readString(length);
  516. length=javapipe.readWord()
  517. classes[i].generic=javapipe.readString(length);
  518. end
  519. end
  520. javapipe.unlock()
  521. return classes
  522. end
  523. function java_pushLocalFrame(count)
  524. javapipe.lock()
  525. javapipe.writeByte(JAVACMD_PUSHLOCALFRAME)
  526. javapipe.writeWord(count)
  527. javapipe.unlock()
  528. end
  529. function java_popLocalFrame(result) --result can be nil
  530. local result=nil
  531. javapipe.lock()
  532. javapipe.writeByte(JAVACMD_POPLOCALFRAME)
  533. javapipe.writeQword(result)
  534. result=javapipe.readQword()
  535. javapipe.unlock()
  536. return result
  537. end
  538. function java_dereferenceLocalObject(object)
  539. javapipe.lock()
  540. javapipe.writeByte(JAVACMD_DEREFERENCELOCALOBJECT)
  541. javapipe.writeQword(object)
  542. javapipe.unlock()
  543. end
  544. function java_cleanClasslist(classlist)
  545. local i
  546. for i=1, #classlist do
  547. java_dereferenceLocalObject(classlist[i].jclass)
  548. end
  549. end
  550. function java_getClassMethods(class)
  551. javapipe.lock()
  552. javapipe.writeByte(JAVACMD_GETCLASSMETHODS)
  553. javapipe.writeQword(class)
  554. local count=javapipe.readDword()
  555. local i
  556. local result={}
  557. local length
  558. for i=1,count do
  559. result[i]={}
  560. result[i].jmethodid=javapipe.readQword()
  561. length=javapipe.readWord()
  562. result[i].name=javapipe.readString(length)
  563. length=javapipe.readWord()
  564. result[i].signature=javapipe.readString(length)
  565. length=javapipe.readWord()
  566. result[i].generic=javapipe.readString(length)
  567. end
  568. javapipe.unlock()
  569. return result
  570. end
  571. function java_getClassFields(class)
  572. javapipe.lock()
  573. javapipe.writeByte(JAVACMD_GETCLASSFIELDS)
  574. javapipe.writeQword(class)
  575. local count=javapipe.readDword()
  576. local i
  577. local result={}
  578. local length
  579. for i=1,count do
  580. result[i]={}
  581. result[i].jfieldid=javapipe.readQword()
  582. length=javapipe.readWord()
  583. result[i].name=javapipe.readString(length)
  584. length=javapipe.readWord()
  585. result[i].signature=javapipe.readString(length)
  586. length=javapipe.readWord()
  587. result[i].generic=javapipe.readString(length)
  588. end
  589. javapipe.unlock()
  590. return result
  591. end
  592. function java_getAllClassFields(class)
  593. --get all the fields of the given class, including inherited ones
  594. java_pushLocalFrame(16)
  595. local result={}
  596. while (class~=nil) and (class~=0) do
  597. local r=java_getClassFields(class)
  598. local i
  599. for i=1,#r do
  600. result[#result+1]=r[i]
  601. end
  602. class=java_getSuperClass(class) --this pushes an object on the local frame
  603. end
  604. java_popLocalFrame(nil)
  605. return result
  606. end
  607. function java_getImplementedInterfaces(class)
  608. result={}
  609. javapipe.lock()
  610. javapipe.writeByte(JAVACMD_GETIMPLEMENTEDINTERFACES)
  611. javapipe.writeQword(class)
  612. local count=javapipe.readDword()
  613. for i=1,count do
  614. result[i]=javapipe.readQword()
  615. end
  616. javapipe.unlock()
  617. return result
  618. end
  619. function java_findReferencesToObject(jObject)
  620. result={}
  621. local count=0
  622. javapipe.lock()
  623. javapipe.writeByte(JAVAVMD_FINDREFERENCESTOOBJECT)
  624. javapipe.writeQword(jObject)
  625. count=javapipe.readDword()
  626. local i
  627. for i=1, count do
  628. result[i]=javapipe.readQword();
  629. end
  630. javapipe.unlock()
  631. return result
  632. end
  633. function java_redefineClassWithCustomData(class, memory)
  634. javapipe.lock()
  635. javapipe.writeByte(JAVACMD_REDEFINECLASS)
  636. javapipe.writeQword(class)
  637. javapipe.writeDword(#memory)
  638. javapipe.writeString(memory)
  639. javapipe.unlock()
  640. end
  641. function java_redefineClassWithCustomClassFile(class, filename)
  642. local f=assert(io.open(filename,"rb"))
  643. local data = f:read("*all")
  644. f:close()
  645. java_redefineClassWithCustomData(class, data)
  646. end
  647. function java_getClassData(class)
  648. --gets the .class binary data (tip: Write a .class parser/editor so you can modify attributes and method bodies)
  649. local result={}
  650. javapipe.lock()
  651. javapipe.writeByte(JAVACMD_GETCLASSDATA)
  652. javapipe.writeQword(class)
  653. result.size=javapipe.readDword()
  654. if (result.size > 0) then
  655. result.data=javapipe.readString(result.size)
  656. end
  657. javapipe.unlock()
  658. return result.data
  659. end
  660. function java_writeClassToDisk(class, filename)
  661. local data=java_getClassData(class)
  662. local f=assert(io.open(filename,"wb"))
  663. f:write(data)
  664. f:close()
  665. end
  666. function java_getMethodName(methodid)
  667. local name=nil
  668. local sig=nil
  669. local gen=nil
  670. javapipe.lock()
  671. javapipe.writeByte(JAVACMD_GETMETHODNAME)
  672. javapipe.writeQword(methodid)
  673. local length
  674. length=javapipe.readWord()
  675. name=javapipe.readString(length)
  676. length=javapipe.readWord()
  677. sig=javapipe.readString(length)
  678. length=javapipe.readWord()
  679. gen=javapipe.readString(length)
  680. javapipe.unlock()
  681. return name, sig, gen
  682. end
  683. function java_parseSignature_type(sig, i)
  684. local result=''
  685. local char=string.sub(sig,i,i)
  686. if (char=='V') or (char=='Z') or (char=='B') or (char=='C') or (char=='S') or (char=='I') or (char=='J') or (char=='F') or (char=='D') then
  687. result=char
  688. elseif char=='L' then
  689. local classtype
  690. local newi
  691. newi=string.find(sig,';', i+1)
  692. if newi==nil then
  693. return #sig --error
  694. end
  695. result=string.sub(sig, i, newi)
  696. i=newi
  697. elseif char=='[' then
  698. result,i=java_parseSignature_type(sig,i+1)
  699. result='['..result
  700. end
  701. return result,i
  702. end
  703. function java_parseSignature_method(sig, i, result)
  704. result.parameters={}
  705. while i<=#sig do
  706. local parem
  707. local char=string.sub(sig,i,i)
  708. --parse every type
  709. if char==')' then
  710. return i+1
  711. end
  712. param,i=java_parseSignature_type(sig, i)
  713. result.parameters[#result.parameters+1]=param
  714. i=i+1
  715. end
  716. end
  717. function java_parseSignature(sig)
  718. if sig==nil then
  719. error('Invalid java signature')
  720. end
  721. --parse the given signature
  722. local result={}
  723. local i=1
  724. while i<=#sig do
  725. local char=string.sub(sig,i,i)
  726. if char=='(' then
  727. i=java_parseSignature_method(sig, i+1, result)
  728. else
  729. if char~=' ' then
  730. result.returntype, i=java_parseSignature_type(sig, i)
  731. end
  732. i=i+1
  733. end
  734. end
  735. return result
  736. end
  737. Java_TypeSigToIDConversion={}
  738. Java_TypeSigToIDConversion['V']=0 --void
  739. Java_TypeSigToIDConversion['Z']=1 --boolean
  740. Java_TypeSigToIDConversion['B']=2 --byte
  741. Java_TypeSigToIDConversion['C']=3 --char
  742. Java_TypeSigToIDConversion['S']=4 --short
  743. Java_TypeSigToIDConversion['I']=5 --int
  744. Java_TypeSigToIDConversion['J']=6 --long
  745. Java_TypeSigToIDConversion['F']=7 --float
  746. Java_TypeSigToIDConversion['D']=8 --double
  747. Java_TypeSigToIDConversion['L']=9 --object
  748. Java_TypeSigToIDConversion['[']=10 --array
  749. --boolean array =11
  750. --byte array =12
  751. --...
  752. function java_invokeMethod_sendParameter(typeid, a, skiptypeid)
  753. if (skiptypeid==nil) or (skiptypeid==true) then
  754. javapipe.writeByte(typeid)
  755. end
  756. if typeid==1 then --boolean
  757. if a==true then
  758. javapipe.writeByte(1)
  759. else
  760. javapipe.writeByte(0)
  761. end
  762. elseif typeid==2 then
  763. javapipe.writeByte(a)
  764. elseif typeid==3 then --char
  765. if tonumber(a)==nil then
  766. javapipe.writeWord(string.byte(a,1))
  767. else
  768. javapipe.writeWord(a)
  769. end
  770. elseif typeid==4 then --short
  771. javapipe.writeWord(a)
  772. elseif typeid==5 then --int
  773. javapipe.writeDword(a)
  774. elseif typeid==6 then --long
  775. javapipe.writeQword(a)
  776. elseif typeid==7 then --float
  777. javapipe.writeFloat(a)
  778. elseif typeid==8 then --double
  779. javapipe.writeDouble(a)
  780. elseif typeid==9 then --object
  781. javapipe.writeQword(a)
  782. elseif typeid>10 then --array
  783. if typeid==13 then
  784. --check if a is a string
  785. if type(a)=='string' then
  786. javapipe.writeDword(#a)
  787. javapipe.writeString(a)
  788. return
  789. end
  790. --else send it char by char
  791. end
  792. javapipe.writeDword(#a) --length of the array
  793. --send the fields as the given type
  794. local i
  795. for i=1, #a do
  796. java_invokeMethod_sendParameter(typeid-10, a[i], true)
  797. end
  798. end
  799. end
  800. function java_invokeMethod(object, methodid, ...)
  801. local argumentcount=#arg
  802. local name, sig, gen=java_getMethodName(methodid)
  803. --parse sig to find out what to give as parameters and what to expect as result (I am assuming the caller KNOWS what he's doing...)
  804. --format of sig: (ABC)D () part are the parameters, D is the return type
  805. local result=nil
  806. parsedsignature=java_parseSignature(sig)
  807. --convert returntype to the id used by JAVACMD_INVOKEMETHOD
  808. local returntype=Java_TypeSigToIDConversion[string.sub(parsedsignature.returntype,1,1)]
  809. if returntype>=10 then
  810. error('Array return types are not supported');
  811. end
  812. if argumentcount~=#parsedsignature.parameters then
  813. error('Parameter count does not match')
  814. end
  815. javapipe.lock()
  816. javapipe.writeByte(JAVACMD_INVOKEMETHOD)
  817. javapipe.writeQword(object)
  818. javapipe.writeQword(methodid)
  819. javapipe.writeByte(returntype)
  820. javapipe.writeByte(argumentcount)
  821. local i
  822. for i=1, argumentcount do
  823. local typeid
  824. typeid=Java_TypeSigToIDConversion[string.sub(parsedsignature.parameters[i],1,1)]
  825. if typeid==10 then
  826. typeid=10+Java_TypeSigToIDConversion[string.sub(parsedsignature.parameters[i],2,2)]
  827. end
  828. java_invokeMethod_sendParameter(typeid, arg[i])
  829. end
  830. result=javapipe.readQword()
  831. javapipe.unlock()
  832. if returntype==1 then
  833. result=result~=0
  834. elseif returntype==7 then --float
  835. result=byteTableToFloat(dwordToByteTable(result))
  836. elseif returntype==8 then --double
  837. result=byteTableToDouble(qwordToByteTable(result))
  838. end
  839. return result
  840. end
  841. function java_findMethod(class, name, sig)
  842. local cm=java_getClassMethods(class)
  843. local i
  844. for i=1,#cm do
  845. if cm[i].name==name then
  846. if (sig==nil) or (sig==cm[i].signature) then
  847. return cm[i].jmethodid
  848. end
  849. end
  850. end
  851. return nil --still here
  852. end
  853. function java_findClass(signature)
  854. local result=nil
  855. javapipe.lock()
  856. javapipe.writeByte(JAVACMD_FINDCLASS)
  857. javapipe.writeWord(#signature)
  858. javapipe.writeString(signature)
  859. result=javapipe.readQword()
  860. javapipe.unlock()
  861. return result
  862. end
  863. function java_findAllObjectsFromClass(jClass)
  864. local result={}
  865. javapipe.lock()
  866. javapipe.writeByte(JAVACMD_FINDCLASSOBJECTS)
  867. javapipe.writeQword(jClass)
  868. local count=javapipe.readDword()
  869. for i=1,count do
  870. result[i]=javapipe.readQword()
  871. end
  872. javapipe.unlock()
  873. return result
  874. end
  875. function java_addToBootstrapClassLoaderPath(segment)
  876. javapipe.lock()
  877. javapipe.writeByte(JAVACMD_ADDTOBOOTSTRAPCLASSLOADERPATH)
  878. javapipe.writeWord(#segment)
  879. javapipe.writeString(segment)
  880. javapipe.unlock()
  881. end
  882. function java_addToSystemClassLoaderPath()
  883. javapipe.lock()
  884. javapipe.writeByte(JAVACMD_ADDTOSYSTEMCLASSLOADERPATH)
  885. javapipe.writeWord(#segment)
  886. javapipe.writeString(segment)
  887. javapipe.unlock()
  888. end
  889. function java_getFieldDeclaringClass(klass, fieldid)
  890. local result=nil
  891. javapipe.lock()
  892. javapipe.writeByte(JAVACMD_GETFIELDDECLARINGCLASS)
  893. javapipe.writeQword(klass)
  894. javapipe.writeQword(fieldid)
  895. result=javapipe.readQword()
  896. javapipe.unlock()
  897. return result
  898. end
  899. function java_getFieldSignature(klass, fieldid)
  900. local result={}
  901. javapipe.lock()
  902. javapipe.writeByte(JAVACMD_GETFIELDSIGNATURE)
  903. javapipe.writeQword(klass)
  904. javapipe.writeQword(fieldid)
  905. local length
  906. length=javapipe.readWord()
  907. result.name=javapipe.readString(length)
  908. length=javapipe.readWord()
  909. result.signature=javapipe.readString(length)
  910. length=javapipe.readWord()
  911. result.generic=javapipe.readString(length)
  912. javapipe.unlock()
  913. return result
  914. end
  915. function java_getField(jObject, fieldid, signature)
  916. if signature==nil then
  917. --I need to figure it out myself I guess...
  918. local klass=java_getObjectClass(jObject)
  919. signature=java_getFieldSignature(klass, fieldid).signature
  920. java_dereferenceLocalObject(klass)
  921. end
  922. --parse the signature
  923. local vartype=Java_TypeSigToIDConversion[string.sub(signature,1,1)]
  924. if vartype>9 then --not sure what to do about arrays. For now, force them to 'objects'
  925. vartype=9
  926. end
  927. local result=nil
  928. javapipe.lock()
  929. javapipe.writeByte(JAVACMD_GETFIELD)
  930. javapipe.writeQword(jObject)
  931. javapipe.writeQword(fieldid)
  932. javapipe.writeByte(vartype)
  933. result=javapipe.readQword()
  934. javapipe.unlock()
  935. if vartype==1 then
  936. result=result~=0
  937. elseif vartype==7 then --float
  938. result=byteTableToFloat(dwordToByteTable(result))
  939. elseif vartype==8 then --double
  940. result=byteTableToDouble(qwordToByteTable(result))
  941. end
  942. return result
  943. end
  944. function java_setField(jObject, fieldid, signature, value)
  945. if signature==nil then
  946. --I need to figure it out myself I guess...
  947. local klass=java_getObjectClass(jObject)
  948. signature=java_getFieldSignature(klass, fieldid).signature
  949. java_dereferenceLocalObject(klass)
  950. end
  951. local vartype=Java_TypeSigToIDConversion[string.sub(signature,1,1)]
  952. if vartype>9 then --not sure what to do about arrays. For now, force them to 'objects'
  953. vartype=9
  954. end
  955. if vartype==1 then --boolean
  956. if value then value=1 else value=0 end
  957. elseif vartype==7 then
  958. value=byteTableToDword(floatToByteTable(value))
  959. elseif vartype==8 then
  960. value=byteTableToQword(doubleToByteTable(value))
  961. end
  962. javapipe.lock()
  963. javapipe.writeByte(JAVACMD_SETFIELD)
  964. javapipe.writeQword(jObject)
  965. javapipe.writeQword(fieldid)
  966. javapipe.writeByte(vartype)
  967. javapipe.writeQword(value)
  968. javapipe.unlock()
  969. end
  970. function java_search_start(value, boolean)
  971. --tag all known objects and set a variable to let some functions know they can not function until the scan has finished (they can't set tags)
  972. local result=nil
  973. javapipe.lock()
  974. javapipe.writeByte(JAVACMD_STARTSCAN)
  975. if value==nil then
  976. javapipe.writeByte(1) --unknown initial value scan
  977. else
  978. javapipe.writeByte(0) --value scan
  979. javapipe.writeDouble(value)
  980. if (boolean~=nil) and (boolean==true) then
  981. javapipe.writeByte(1)
  982. else
  983. javapipe.writeByte(0)
  984. end
  985. end
  986. result=javapipe.readQword() --Wait till done, get nr of results)
  987. java_scanning=true
  988. javapipe.unlock()
  989. return result
  990. end
  991. function java_search_refine(scantype, scanvalue)
  992. --refines the result of the current scan
  993. --scantype:
  994. --0 = exact value
  995. --1 = increased value
  996. --2 = decreased value
  997. --3 = changed value
  998. --4 = unchanged value
  999. local result=nil
  1000. if scantype==nil then
  1001. error("Scantype was not set")
  1002. end
  1003. javapipe.lock()
  1004. javapipe.writeByte(JAVACMD_REFINESCANRESULTS)
  1005. javapipe.writeByte(scantype)
  1006. if scantype==0 then
  1007. javapipe.writeDouble(scanvalue)
  1008. end
  1009. result=javapipe.readQword()
  1010. javapipe.unlock()
  1011. return result
  1012. end
  1013. function java_search_getResults(maxresults)
  1014. --get the results
  1015. --note, the results are referencec to the object, so CLEAN UP when done with it (and don't get too many)
  1016. local result={}
  1017. javapipe.lock()
  1018. javapipe.writeByte(JAVACMD_GETSCANRESULTS)
  1019. if maxresults==0 then
  1020. maxresults=10
  1021. end
  1022. javapipe.writeDword(maxresults)
  1023. --local i=1
  1024. while true do
  1025. --print(i)
  1026. -- i=i+1
  1027. local object=javapipe.readQword()
  1028. if (object==0) or (object==nil) then
  1029. --print("End of the list")
  1030. break
  1031. end --end of the list
  1032. local r={}
  1033. r.object=object
  1034. r.fieldid=javapipe.readQword()
  1035. table.insert(result, r)
  1036. end
  1037. javapipe.unlock()
  1038. return result
  1039. end
  1040. function java_search_finish()
  1041. java_scanning=false
  1042. end
  1043. function java_foundCodeDialogClose(sender)
  1044. --print("closing")
  1045. local id=sender.Tag
  1046. local fcd=java.findwhatwriteslist[id]
  1047. java.findwhatwriteslist[id]=nil
  1048. java_stopFindWhatWrites(id)
  1049. return caFree
  1050. end
  1051. function java_MoreInfoDblClick(sender)
  1052. --get the class and method and start the editor
  1053. local index=sender.ItemIndex+1
  1054. if index>0 then
  1055. local methodid=getRef(sender.Tag).stack[index].methodid --the listview also has this tag (tag to entry)
  1056. local class=java_getMethodDeclaringClass(methodid)
  1057. --get the class that defines this method
  1058. local classdata=java_getClassData(class)
  1059. local parsedclass=java_parseClass(classdata)
  1060. local mname=java_getMethodName(methodid)
  1061. local parsedmethod=javaclass_findMethod(parsedclass, mname)
  1062. javaclasseditor_editMethod(parsedclass, parsedmethod, editMethod_applyClick, class)
  1063. end
  1064. end
  1065. function java_foundCodeDialog_MoreInfo_OnDestroy(sender)
  1066. --cleanup the reference to this entry
  1067. local entry=getRef(sender.Tag)
  1068. if entry~=nil then
  1069. entry.form=nil
  1070. destroyRef(sender.Tag)
  1071. end
  1072. end
  1073. function java_createEntryListView(owner)
  1074. local lv=createListView(owner)
  1075. lv.ViewStyle=vsReport
  1076. lv.ReadOnly=true
  1077. lv.RowSelect=true
  1078. local c=lv.Columns.add()
  1079. c.caption='Class'
  1080. c.width=150
  1081. c=lv.Columns.add()
  1082. c.caption='Method'
  1083. c.width=150
  1084. c=lv.Columns.add()
  1085. c.caption='Position'
  1086. c.autosize=true
  1087. return lv
  1088. end
  1089. function java_foundCodeDialogLVDblClick(sender)
  1090. local id=sender.tag
  1091. local fcd=java.findwhatwriteslist[id]
  1092. local index=sender.ItemIndex+1
  1093. if index>0 then
  1094. local entry=fcd.entries[index]
  1095. if (entry.stack~=nil) and (entry.form==nil) then
  1096. --show a form with the stack info
  1097. local ref=createRef(entry)
  1098. entry.form=createForm()
  1099. entry.form.Caption=string.format("More info %s.%s(%d)", entry.classname, entry.methodname, entry.location)
  1100. entry.form.Tag=ref
  1101. entry.form.Width=400
  1102. entry.form.Height=150
  1103. entry.form.Position=poScreenCenter
  1104. entry.form.BorderStyle=bsSizeable
  1105. local lv=java_createEntryListView(entry.form)
  1106. lv.Tag=ref
  1107. lv.Align=alClient
  1108. entry.form.OnDestroy=java_foundCodeDialog_MoreInfo_OnDestroy
  1109. --fill the listview with the data
  1110. local i
  1111. for i=1, #entry.stack do
  1112. local se=entry.stack[i]
  1113. local mname=java_getMethodName(se.methodid)
  1114. local class=java_getMethodDeclaringClass(se.methodid)
  1115. local classname=java_getClassSignature(class)
  1116. java_dereferenceLocalObject(class)
  1117. class=nil
  1118. local tventry=lv.items.add()
  1119. tventry.Caption=classname
  1120. tventry.SubItems.add(string.format('%x: %s', se.methodid, mname))
  1121. tventry.SubItems.add(se.location)
  1122. end
  1123. lv.OnDblClick=java_MoreInfoDblClick
  1124. end
  1125. if (entry.form~=nil) then
  1126. entry.form.show() --bring to front
  1127. end
  1128. end
  1129. end
  1130. function java_findWhatWrites(object, fieldid)
  1131. local id=nil
  1132. if java.capabilities.can_generate_field_modification_events then
  1133. --spawn a window to receive the data
  1134. javapipe.lock()
  1135. javapipe.writeByte(JAVACMD_FINDWHATWRITES)
  1136. javapipe.writeQword(object)
  1137. javapipe.writeQword(fieldid)
  1138. id=javapipe.readDword()
  1139. --print("id="..id)
  1140. javapipe.unlock()
  1141. local fcd={} --found code dialog
  1142. fcd.form=createForm()
  1143. fcd.form.width=400
  1144. fcd.form.height=300
  1145. fcd.form.Position=poScreenCenter
  1146. fcd.form.BorderStyle=bsSizeable
  1147. fcd.form.caption='The following methods accessed the given variable'
  1148. fcd.form.OnClose=java_foundCodeDialogClose
  1149. fcd.form.Tag=id
  1150. fcd.lv=java_createEntryListView(fcd.form)
  1151. fcd.lv.Align=alClient
  1152. fcd.lv.OnDblClick=java_foundCodeDialogLVDblClick
  1153. fcd.lv.Tag=id
  1154. fcd.lv.Name='results';
  1155. fcd.entries={}
  1156. if java.findwhatwriteslist==nil then
  1157. java.findwhatwriteslist={}
  1158. end
  1159. java.findwhatwriteslist[id]=fcd
  1160. else
  1161. error('java_find_what_writes only works when the jvmti agent is launched at start')
  1162. end
  1163. return id
  1164. end
  1165. function java_stopFindWhatWrites(id)
  1166. javapipe.lock()
  1167. javapipe.writeByte(JAVACMD_STOPFINDWHATWRITES)
  1168. javapipe.writeDword(id)
  1169. javapipe.unlock()
  1170. end
  1171. function java_getMethodDeclaringClass(methodid)
  1172. javapipe.lock()
  1173. javapipe.writeByte(JAVACMD_GETMETHODDECLARINGCLASS)
  1174. javapipe.writeQword(methodid)
  1175. local result=javapipe.readQword()
  1176. javapipe.unlock()
  1177. return result
  1178. end
  1179. function java_getObjectHandleToAddress(address)
  1180. local result=0
  1181. javapipe.lock()
  1182. javapipe.writeByte(JAVACMD_FINDJOBJECT)
  1183. javapipe.writeQword(address)
  1184. result=javapipe.readQword()
  1185. javapipe.unlock()
  1186. return result
  1187. end
  1188. function java_getObjectClass(jObject)
  1189. local result
  1190. javapipe.lock()
  1191. javapipe.writeByte(JAVACMD_GETOBJECTCLASS);
  1192. javapipe.writeQword(jObject)
  1193. result=javapipe.readQword()
  1194. javapipe.unlock()
  1195. return result
  1196. end
  1197. function java_getClassSignature(jClass)
  1198. local length
  1199. local result=''
  1200. javapipe.lock()
  1201. javapipe.writeByte(JAVACMD_GETCLASSSIGNATURE)
  1202. javapipe.writeQword(jClass)
  1203. length=javapipe.readWord()
  1204. result=javapipe.readString(length);
  1205. length=javapipe.readWord()
  1206. if (length>0) then
  1207. result=result..' Generic='..javapipe.readString(length);
  1208. end
  1209. javapipe.unlock()
  1210. return result
  1211. end
  1212. function java_getSuperClass(jClass)
  1213. local result=nil
  1214. javapipe.lock()
  1215. javapipe.writeByte(JAVACMD_GETSUPERCLASS)
  1216. javapipe.writeQword(jClass)
  1217. result=javapipe.readQword()
  1218. javapipe.unlock()
  1219. return result
  1220. end
  1221. function miJavaActivateClick(sender)
  1222. javaInjectAgent()
  1223. end
  1224. function javaForm_treeviewExpanding(sender, node)
  1225. local allow=true
  1226. --outputDebugString("Expanding "..node.Text)
  1227. --print("javaForm_treeviewExpanding "..node.level)
  1228. if node.Level==0 then --root level (class expasion)
  1229. if node.Count==0 then --not yet filled in
  1230. --expand the class this node describes
  1231. local jklass=node.Data
  1232. local methods=java_getClassMethods(jklass)
  1233. local fields=java_getClassFields(jklass)
  1234. local interfaces=java_getImplementedInterfaces(jklass)
  1235. local superclass=java_getSuperClass(jklass)
  1236. local i
  1237. if superclass~=0 then
  1238. node.add('superclass='..java_getClassSignature(superclass))
  1239. java_dereferenceLocalObject(superclass)
  1240. end
  1241. node.add('---Implemented interfaces---');
  1242. for i=1, #interfaces do
  1243. local name
  1244. if interfaces[i]>0 then
  1245. name=java_getClassSignature(interfaces[i])
  1246. else
  1247. name='???'
  1248. end
  1249. node.add(string.format("%x : %s", interfaces[i], name))
  1250. end
  1251. node.add('---Fields---');
  1252. for i=1, #fields do
  1253. node.add(string.format("%x: %s: %s (%s)", fields[i].jfieldid, fields[i].name, fields[i].signature,fields[i].generic))
  1254. end
  1255. node.add('---Methods---');
  1256. for i=1, #methods do
  1257. local n=node.add(string.format("%x: %s%s %s", methods[i].jmethodid, methods[i].name, methods[i].signature, methods[i].generic))
  1258. n.data=methods[i].jmethodid --ONLY methods have this field set at level 1. (!ONLY METHODS!)
  1259. end
  1260. --java_getClassFields(jklass);
  1261. end
  1262. end
  1263. return allow
  1264. end
  1265. function javaForm_searchClass(sender)
  1266. javaForm.findAll=false --classes only
  1267. javaForm.findDialog.Title="Search for class..."
  1268. javaForm.findDialog.execute()
  1269. end
  1270. function javaForm_searchAll(sender)
  1271. javaForm.findAll=true --everything
  1272. javaForm.findDialog.Title="Search for..."
  1273. javaForm.findDialog.execute()
  1274. end
  1275. function javaForm_doSearch(sender)
  1276. --search for javaForm.findDialog.FindText
  1277. local currentindex=1
  1278. local findall=javaForm.findAll
  1279. local searchstring=javaForm.findDialog.FindText
  1280. if javaForm.treeview.Selected ~= nil then
  1281. currentindex=javaForm.treeview.Selected.AbsoluteIndex+1 --start at the next one
  1282. end
  1283. while currentindex<javaForm.treeview.Items.Count do
  1284. local node=javaForm.treeview.Items[currentindex]
  1285. if (node.level==0) or findall then
  1286. --check if node.Text contains the searchstring
  1287. if string.find(node.Text,searchstring) ~= nil then
  1288. --found one
  1289. node.Selected=true
  1290. node.makeVisible()
  1291. return
  1292. end
  1293. end
  1294. if findall and node.HasChildren then
  1295. node.expand()
  1296. end
  1297. currentindex=currentindex+1
  1298. end
  1299. end
  1300. function varscan_showResults(count)
  1301. --print("showing results for "..count.." results");
  1302. java.varscan.currentresults=java_search_getResults(math.min(count, 100))
  1303. if count>100 then
  1304. java.varscan.Count.Caption=string.format('%d of %d', #java.varscan.currentresults, count)
  1305. else
  1306. java.varscan.Count.Caption=count
  1307. end
  1308. count=#java.varscan.currentresults
  1309. local i
  1310. for i=1,count do
  1311. local object=java.varscan.currentresults[i].object
  1312. local fieldid=java.varscan.currentresults[i].fieldid
  1313. local class=java_getObjectClass(object)
  1314. local classname=java_getClassSignature(class)
  1315. --local class2=java_getFieldDeclaringClass(class, fieldid)
  1316. local fieldname=java_getFieldSignature(class, fieldid)
  1317. java_dereferenceLocalObject(class)
  1318. --java_dereferenceLocalObject(class2)
  1319. java.varscan.Results.Items.Add('Obj('..classname..'.'..fieldname.name..')')
  1320. end
  1321. end
  1322. function varscan_cleanupResults()
  1323. local i
  1324. java.varscan.Results.clear()
  1325. for i=1,#java.varscan.currentresults do
  1326. java_dereferenceLocalObject(java.varscan.currentresults[i].object)
  1327. end
  1328. java.varscan.currentresults=nil
  1329. end
  1330. function varscan_firstScan(sender)
  1331. --print("first scan")
  1332. if (sender.Tag==0) then
  1333. --first scan
  1334. local count=java_search_start(java.varscan.ValueBox.Text)
  1335. varscan_showResults(count)
  1336. sender.Caption="New Scan"
  1337. sender.Tag=1
  1338. java.varscan.NextScan.Enabled=#java.varscan.currentresults>0
  1339. else
  1340. --new scan
  1341. varscan_cleanupResults()
  1342. java_search_finish()
  1343. java.varscan.NextScan.Enabled=false
  1344. sender.Caption="First Scan"
  1345. sender.Tag=0
  1346. end
  1347. end
  1348. function varscan_nextScan(sender)
  1349. --print("next scan")
  1350. varscan_cleanupResults()
  1351. local count=java_search_refine(0, java.varscan.ValueBox.Text)
  1352. varscan_showResults(count)
  1353. java.varscan.NextScan.Enabled=#java.varscan.currentresults>0
  1354. end
  1355. function miFindWhatAccessClick(sender)
  1356. local i=java.varscan.Results.ItemIndex
  1357. if i~=-1 then
  1358. i=i+1
  1359. local object=java.varscan.currentresults[i].object
  1360. local fieldid=java.varscan.currentresults[i].fieldid
  1361. java_findWhatWrites(object, fieldid)
  1362. end
  1363. end
  1364. function miJavaVariableScanClick(sender)
  1365. javaInjectAgent()
  1366. local varscan=java.varscan
  1367. if varscan==nil then
  1368. --build a gui
  1369. varscan={}
  1370. varscan.form=createForm()
  1371. varscan.form.Width=400
  1372. varscan.form.Height=400
  1373. varscan.form.Position=poScreenCenter
  1374. varscan.form.Caption="Java Variable Scanner"
  1375. varscan.form.BorderStyle=bsSizeable
  1376. varscan.controls=createPanel(varscan.form)
  1377. varscan.controls.Align=alRight
  1378. varscan.controls.Caption=''
  1379. varscan.controls.BevelOuter="bvNone"
  1380. varscan.ValueText=createLabel(varscan.controls)
  1381. varscan.ValueText.Caption="Value"
  1382. varscan.FirstScan=createButton(varscan.controls)
  1383. varscan.FirstScan.Caption="First Scan"
  1384. varscan.NextScan=createButton(varscan.controls)
  1385. varscan.NextScan.Caption="Next Scan"
  1386. local width=6+math.max(varscan.form.Canvas.getTextWidth(varscan.FirstScan.Caption), varscan.form.Canvas.getTextWidth(varscan.NextScan.Caption)) --guess which one will be bigger... (just in case someone translates this)
  1387. varscan.FirstScan.ClientWidth=width
  1388. varscan.NextScan.ClientWidth=width
  1389. varscan.ValueBox=createEdit(varscan.controls)
  1390. varscan.ValueBox.Top=20
  1391. varscan.ValueBox.Left=20;
  1392. varscan.ValueText.AnchorSideLeft.Control=varscan.ValueBox
  1393. varscan.ValueText.AnchorSideLeft.Side=asrLeft
  1394. varscan.ValueText.AnchorSideBottom.Control=varscan.ValueBox
  1395. varscan.ValueText.AnchorSideBottom.Side=asrTop
  1396. varscan.ValueText.Anchors="[akLeft, akBottom]"
  1397. varscan.FirstScan.AnchorSideLeft.Control=varscan.ValueBox
  1398. varscan.FirstScan.AnchorSideLeft.Side=asrLeft
  1399. varscan.FirstScan.AnchorSideTop.Control=varscan.ValueBox
  1400. varscan.FirstScan.AnchorSideTop.Side=asrBottom
  1401. varscan.FirstScan.BorderSpacing.Top=5
  1402. varscan.FirstScan.Anchors="[akTop, akLeft]"
  1403. varscan.FirstScan.OnClick=varscan_firstScan
  1404. varscan.NextScan.AnchorSideLeft.Control=varscan.FirstScan
  1405. varscan.NextScan.AnchorSideLeft.Side=asrRight
  1406. varscan.NextScan.BorderSpacing.Left=5
  1407. varscan.NextScan.OnClick=varscan_nextScan
  1408. varscan.NextScan.AnchorSideTop.Control=varscan.ValueBox
  1409. varscan.NextScan.AnchorSideTop.Side=asrBottom
  1410. varscan.NextScan.BorderSpacing.Top=5
  1411. varscan.NextScan.Anchors="[akTop, akLeft]"
  1412. varscan.NextScan.Enabled=false
  1413. varscan.ValueBox.Width=varscan.NextScan.Left+varscan.NextScan.Width-varscan.ValueBox.Left
  1414. varscan.controls.Width=varscan.ValueBox.Width+40
  1415. varscan.ResultPanel=createPanel(varscan.form)
  1416. varscan.ResultPanel.Align=alClient
  1417. varscan.ResultPanel.Caption=""
  1418. varscan.ResultPanel.BevelOuter="bvNone"
  1419. varscan.Count=createLabel(varscan.ResultPanel)
  1420. varscan.Count.Caption="Found:"
  1421. varscan.Count.Align=alTop
  1422. varscan.Results=createListBox(varscan.ResultPanel)
  1423. varscan.Results.Align=alClient
  1424. varscan.Results.Width=200
  1425. varscan.Results.PopupMenu=createPopupMenu(varscan.form)
  1426. local mi
  1427. mi=createMenuItem(varscan.Results.PopupMenu)
  1428. mi.Caption="Find what accesses this value"
  1429. mi.OnClick=miFindWhatAccessClick;
  1430. varscan.Results.PopupMenu.Items.add(mi)
  1431. end
  1432. varscan.form.show()
  1433. java.varscan=varscan
  1434. end
  1435. function editMethod_applyClick(parsedclass, class)
  1436. local newdata=java_writeClass(parsedclass)
  1437. java_redefineClassWithCustomData(class, newdata)
  1438. end
  1439. function miEditMethodClick(sender)
  1440. --javaclasseditor_editMethod(class, methodid)
  1441. local sel=javaForm.treeview.Selected
  1442. if (sel~=nil) and (sel.Level==1) and (sel.Data~=0) then
  1443. --find the class and the methodid
  1444. --class can be found in the parent
  1445. --methodid is in the data
  1446. local class=sel.Parent.Data
  1447. local methodid=sel.data
  1448. --javaclasseditor_editMethod(class, methodid)
  1449. local classdata=java_getClassData(class)
  1450. local parsedclass=java_parseClass(classdata)
  1451. local mname=java_getMethodName(methodid)
  1452. local parsedmethod=javaclass_findMethod(parsedclass, mname)
  1453. javaclasseditor_editMethod(parsedclass, parsedmethod, editMethod_applyClick, class)
  1454. end
  1455. end
  1456. function javaDissectPopupOnPopup(sender)
  1457. --check if the current line contains a method, and if so, show miEditMethod else hide it
  1458. local sel=javaForm.treeview.Selected
  1459. javaForm.miEditMethod.Visible=(sel~=nil) and (sel.Level==1) and (sel.Data~=0)
  1460. end
  1461. function miJavaDissectClick(sender)
  1462. javaInjectAgent()
  1463. --I could also implement the same method as mono, but as an example I'll be creating the form with code only
  1464. if (javaForm==nil) then
  1465. javaForm={}
  1466. javaForm.form=createForm()
  1467. javaForm.form.Borderstyle=bsSizeable
  1468. javaForm.form.Width=640
  1469. javaForm.form.Height=480
  1470. javaForm.treeview=createTreeview(javaForm.form)
  1471. javaForm.treeview.align=alClient
  1472. javaForm.treeview.OnExpanding=javaForm_treeviewExpanding
  1473. javaForm.treeview.RightClickSelect=true
  1474. javaForm.menu=createMainMenu(javaForm.form)
  1475. local searchmenu=createMenuItem(javaForm.menu)
  1476. searchmenu.caption="Search"
  1477. javaForm.menu.items.add(searchmenu)
  1478. local searchClass=createMenuItem(javaForm.menu)
  1479. searchClass.caption="Find Class"
  1480. searchClass.Shortcut="Ctrl+F"
  1481. searchClass.OnClick=javaForm_searchClass
  1482. searchmenu.add(searchClass)
  1483. local searchAll=createMenuItem(javaForm.menu)
  1484. searchAll.caption="Find..."
  1485. searchAll.Shortcut="Ctrl+Alt+F"
  1486. searchAll.OnClick=javaForm_searchAll
  1487. searchmenu.add(searchAll)
  1488. javaForm.findDialog=createFindDialog(javaForm.form)
  1489. javaForm.findDialog.Options="[frHideEntireScope, frHideWholeWord, frDown, frDisableUpDown, frMatchCase, frDisableMatchCase]"
  1490. javaForm.findDialog.OnFind=javaForm_doSearch
  1491. javaForm.form.position=poScreenCenter
  1492. javaForm.popupMenu=createPopupMenu(javaForm.treeview)
  1493. javaForm.miEditMethod=createMenuItem(javaForm.popupMenu)
  1494. javaForm.miEditMethod.Caption="Edit method"
  1495. javaForm.miEditMethod.OnClick=miEditMethodClick
  1496. javaForm.popupMenu.Items.Add(javaForm.miEditMethod)
  1497. javaForm.popupMenu.OnPopup=javaDissectPopupOnPopup
  1498. javaForm.treeview.PopupMenu=javaForm.popupMenu
  1499. javaForm.form.OnClose=nil --get rid of autodestruct
  1500. end
  1501. if (java_classlist~=nil) then
  1502. java_cleanClasslist(java_classlist) --prevent a memory leak
  1503. end
  1504. java_classlist=java_getLoadedClasses()
  1505. if (java_classlist~=nil) then
  1506. local i
  1507. for i=1,#java_classlist do
  1508. local node=javaForm.treeview.Items.Add(string.format("%d(%x) : %s (%s)", i, java_classlist[i].jclass, java_classlist[i].signature, java_classlist[i].generic ))
  1509. node.Data=java_classlist[i].jclass
  1510. node.HasChildren=true
  1511. end
  1512. end
  1513. javaForm.form.show()
  1514. end
  1515. function miJavaSetEnvironmentClick(sender)
  1516. if targetIs64Bit() then
  1517. autoAssemble([[
  1518. alloc(newenv, 32768)
  1519. alloc(sev, 2048)
  1520. alloc(path, 512)
  1521. alloc(pathstr,5)
  1522. alloc(JTOstr, 18)
  1523. alloc(JTO, 19)
  1524. label(end)
  1525. label(hasnosemicolon)
  1526. label(copyoption)
  1527. path:
  1528. {$lua}
  1529. return "db ';"..getCheatEngineDir().."autorun\\dlls\\32;"..getCheatEngineDir().."autorun\\dlls\\64',0"
  1530. {$asm}
  1531. pathstr:
  1532. db 'PATH',0
  1533. JTOstr:
  1534. db 'JAVA_TOOL_OPTIONS',0
  1535. JTO:
  1536. db ' -agentlib:cejvmti',0
  1537. sev:
  1538. //sub rsp,8 //align the stack
  1539. //sub rsp,20 //allocate scratchspace for function calls
  1540. sub rsp,28 //using magic to compine those two
  1541. //set the path
  1542. mov rcx,pathstr
  1543. mov rdx,newenv
  1544. mov r8,8000
  1545. call GetEnvironmentVariableA
  1546. mov rdx,path
  1547. cmp byte [newenv+rax],';'
  1548. jne hasnosemicolon
  1549. add rdx,1 //it already has a semicolon so skip it
  1550. hasnosemicolon:
  1551. mov rcx,newenv
  1552. //rdx=path(+1)
  1553. call ntdll.strcat
  1554. mov rcx,pathstr
  1555. mov rdx,newenv
  1556. call SetEnvironmentVariableA
  1557. //set the java tool options
  1558. mov byte [newenv],0
  1559. mov rcx,JTOstr
  1560. mov rdx,newenv
  1561. mov r8,8000
  1562. call GetEnvironmentVariableA
  1563. mov rdx, JTO
  1564. cmp rax,0 //not yet defined
  1565. jne copyoption
  1566. //it hasn't been defined yet
  1567. add rdx,1 //no space
  1568. copyoption:
  1569. mov rcx,newenv
  1570. //rdx=rdx
  1571. call ntdll.strcat
  1572. mov rcx,JTOstr
  1573. mov rdx,newenv
  1574. call SetEnvironmentVariableA
  1575. end:
  1576. add rsp,28
  1577. ret
  1578. createthread(sev)
  1579. ]])
  1580. else
  1581. autoAssemble([[
  1582. alloc(newenv, 32768)
  1583. alloc(sev, 2048)
  1584. alloc(path, 512)
  1585. alloc(pathstr,5)
  1586. alloc(JTOstr, 18)
  1587. alloc(JTO, 19)
  1588. label(end)
  1589. label(hasnosemicolon)
  1590. label(copyoption)
  1591. path:
  1592. {$lua}
  1593. return "db ';"..getCheatEngineDir().."autorun\\dlls\\32;"..getCheatEngineDir().."autorun\\dlls\\64',0"
  1594. {$asm}
  1595. pathstr:
  1596. db 'PATH',0
  1597. JTOstr:
  1598. db 'JAVA_TOOL_OPTIONS',0
  1599. JTO:
  1600. db ' -agentlib:cejvmti',0
  1601. sev:
  1602. //set the path
  1603. push 8000
  1604. push newenv
  1605. push pathstr
  1606. call GetEnvironmentVariableA
  1607. mov esi,path
  1608. cmp byte [newenv+eax],';'
  1609. jne hasnosemicolon
  1610. add esi,1 //it already has a semicolon so skip it
  1611. hasnosemicolon:
  1612. push esi
  1613. push newenv
  1614. call ntdll.strcat
  1615. add esp,8
  1616. push newenv
  1617. push pathstr
  1618. call SetEnvironmentVariableA
  1619. //set the java tool options
  1620. mov byte [newenv],0
  1621. push 8000
  1622. push newenv
  1623. push JTOstr
  1624. call GetEnvironmentVariableA
  1625. mov esi, JTO
  1626. cmp eax,0 //not yet defined
  1627. jne copyoption
  1628. //it hasn't been defined yet
  1629. add esi,1 //no space
  1630. copyoption:
  1631. push esi
  1632. push newenv
  1633. call ntdll.strcat
  1634. add esp,8
  1635. push newenv
  1636. push JTOstr
  1637. call SetEnvironmentVariableA
  1638. end:
  1639. ret
  1640. createthread(sev)
  1641. ]]
  1642. )
  1643. end
  1644. end
  1645. function java_OpenProcessAfterwards()
  1646. local usesjava=false
  1647. local m=enumModules()
  1648. local i
  1649. java_classlist=nil
  1650. for i=1, #m do
  1651. if m[i].Name=='jvm.dll' then
  1652. usesjava=true
  1653. break
  1654. end
  1655. end
  1656. if usesjava or java.settings.cbAlwaysShowMenu.Checked then
  1657. if (miJavaTopMenuItem==nil) then
  1658. local mfm=getMainForm().Menu
  1659. local mi
  1660. miJavaTopMenuItem=createMenuItem(mfm)
  1661. miJavaTopMenuItem.Caption="Java"
  1662. mfm.Items.insert(mfm.Items.Count-1, miJavaTopMenuItem) --add it before help
  1663. mi=createMenuItem(miJavaTopMenuItem)
  1664. mi.Caption="Activate java features"
  1665. mi.OnClick=miJavaActivateClick
  1666. mi.Enabled=usesjava
  1667. mi.Name="miActivate"
  1668. mi.Visible=false
  1669. miJavaTopMenuItem.Add(mi)
  1670. mi=createMenuItem(miJavaTopMenuItem)
  1671. mi.Caption="Dissect java classes"
  1672. mi.Shortcut="Ctrl+Alt+J"
  1673. mi.OnClick=miJavaDissectClick
  1674. mi.Enabled=usesjava
  1675. mi.Name="miDissectJavaClasses"
  1676. miJavaTopMenuItem.Add(mi)
  1677. mi=createMenuItem(miJavaTopMenuItem)
  1678. mi.Caption="Java variable scan"
  1679. mi.Shortcut="Ctrl+Alt+S"
  1680. mi.OnClick=miJavaVariableScanClick
  1681. mi.Enabled=usesjava
  1682. mi.Name="miJavaVariableScan"
  1683. miJavaTopMenuItem.Add(mi)
  1684. mi=createMenuItem(miJavaTopMenuItem)
  1685. mi.Caption="-"
  1686. miJavaTopMenuItem.Add(mi)
  1687. mi=createMenuItem(miJavaTopMenuItem)
  1688. mi.Caption="Debug child processes"
  1689. mi.OnClick=miJavaSetEnvironmentClick
  1690. mi.Enabled=getOpenedProcessID()~=0
  1691. mi.Name="miDebugChildren"
  1692. miJavaTopMenuItem.Add(mi)
  1693. else
  1694. miJavaTopMenuItem.miActivate.enabled=usesjava
  1695. miJavaTopMenuItem.miDissectJavaClasses.enabled=usesjava
  1696. miJavaTopMenuItem.miJavaVariableScan.enabled=usesjava
  1697. miJavaTopMenuItem.miDebugChildren=getOpenedProcessID()~=0
  1698. end
  1699. end
  1700. end
  1701. function java_OpenProcess(processid)
  1702. if java.oldOnOpenProcess~=nil then
  1703. java.oldOnOpenProcess(processid)
  1704. end
  1705. synchronize(java_OpenProcessAfterwards) --call this function when the whole OpenProcess routine is done (next sync check)
  1706. end
  1707. function javaAA_USEJAVA(parameters, syntaxcheckonly)
  1708. --called whenever an auto assembler script encounters the USEJAVA() line
  1709. --the value you return will be placed instead of the given line
  1710. --In this case, returning a empty string is fine
  1711. --Special behaviour: Returning nil, with a secondary parameter being a string, will raise an exception on the auto assembler with that string
  1712. if (syntaxcheckonly==false) and (javaInjectAgent()==0) then
  1713. return nil,"The java handler failed to initialize"
  1714. end
  1715. return "" --return an empty string (removes it from the internal aa assemble list)
  1716. end
  1717. function java_settingsClose(sender)
  1718. local result=caHide
  1719. if java.settingsOnClose~=nil then
  1720. result=java.settingsOnClose(sender)
  1721. end
  1722. if (result==caHide) and (sender.ModalResult==mrOK) then
  1723. --Apply changes
  1724. --if there is an error return caNone (and show a message preferably)
  1725. if java.settings.cbAlwaysShowMenu.Checked then
  1726. java.settings.registry.Value["Always Show Menu"]=1
  1727. else
  1728. java.settings.registry.Value["Always Show Menu"]=0
  1729. end
  1730. --[[
  1731. if java.settings.cbGlobalHook.Checked then
  1732. if (java.settings.registry.Value["Global Hook"]=='') or (java.settings.registry.Value["Global Hook"]==0) then
  1733. --it got selected
  1734. end
  1735. java.settings.registry.Value["Global Hook"]=1
  1736. else
  1737. if java.settings.registry.Value["Global Hook"]==1 then
  1738. --it got deselected
  1739. end
  1740. java.settings.registry.Value["Global Hook"]=0
  1741. end
  1742. --]]
  1743. end
  1744. return result
  1745. end
  1746. function java_settingsShow(sender)
  1747. if java.settingsOnShow~=nil then
  1748. result=java.settingsOnShow(sender)
  1749. end
  1750. --update the controls based on the registry
  1751. java.settings.cbAlwaysShowMenu.Checked=java.settings.registry.Value["Always Show Menu"]=='1'
  1752. --java.settings.cbGlobalHook.Checked=java.settings.registry.Value["Global Hook"]=='1'
  1753. end
  1754. function java_initialize()
  1755. --register a function to be called when a process is opened
  1756. if (java==nil) then
  1757. java={}
  1758. java.oldOnOpenProcess=onOpenProcess
  1759. onOpenProcess=java_OpenProcess
  1760. registerAutoAssemblerCommand("USEJAVA", javaAA_USEJAVA)
  1761. local sf=getSettingsForm()
  1762. java.settingsTab=sf.SettingsPageControl.addTab()
  1763. local insertNode=sf.SettingsTreeView.Items[3] --insert it near the unrandomizer since it'd be used as often as that setting
  1764. local node=sf.SettingsTreeView.Items.insert(insertNode, "Java")
  1765. node.data=userDataToInteger(java.settingsTab)
  1766. java.settingsOnClose=sf.onClose
  1767. sf.onClose=java_settingsClose
  1768. java.settingsOnShow=sf.onShow
  1769. sf.onShow=java_settingsShow
  1770. java.settings={}
  1771. local cbAlwaysShowMenu=createCheckBox(java.settingsTab)
  1772. cbAlwaysShowMenu.Caption="Show java menu item even if the target process hasn't loaded jvm.dll (Used for the local setEnvironment option)"
  1773. cbAlwaysShowMenu.AnchorSideLeft.Control=java.settingsTab
  1774. cbAlwaysShowMenu.AnchorSideLeft.Side="asrLeft"
  1775. cbAlwaysShowMenu.AnchorSideTop.Control=java.settingsTab
  1776. cbAlwaysShowMenu.AnchorSideTop.Side="asrTop"
  1777. cbAlwaysShowMenu.Anchors="[akTop, akLeft]"
  1778. java.settings.cbAlwaysShowMenu=cbAlwaysShowMenu
  1779. --[[
  1780. --warning: If you uninstall CE while this is checked you won't be able to load any java programs
  1781. local cbGlobalHook=createCheckBox(java.settingsTab)
  1782. cbGlobalHook.Caption="Systemwide java agent injection. (Loads the java agent even when CE isn't running. Reboot recommended)"
  1783. cbGlobalHook.AnchorSideLeft.Control=java.settingsTab
  1784. cbGlobalHook.AnchorSideLeft.Side="asrLeft"
  1785. cbGlobalHook.AnchorSideTop.Control=cbAlwaysShowMenu
  1786. cbGlobalHook.AnchorSideTop.Side="asrBottom"
  1787. cbGlobalHook.Anchors="[akTop, akLeft]"
  1788. java.settings.cbGlobalHook=cbGlobalHook
  1789. --]]
  1790. java.settings.registry=getSettings("Java")
  1791. --initialize the settings based on the registry
  1792. java.settings.cbAlwaysShowMenu.Checked=java.settings.registry.Value["Always Show Menu"]=='1'
  1793. --java.settings.cbGlobalHook.Checked=java.settings.registry.Value["Global Hook"]=='1'
  1794. end
  1795. end
  1796. java_initialize()