| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577 |
- MONOCMD_INITMONO=0
- MONOCMD_OBJECT_GETCLASS=1
- MONOCMD_ENUMDOMAINS=2
- MONOCMD_SETCURRENTDOMAIN=3
- MONOCMD_ENUMASSEMBLIES=4
- MONOCMD_GETIMAGEFROMASSEMBLY=5
- MONOCMD_GETIMAGENAME=6
- MONOCMD_ENUMCLASSESINIMAGE=7
- MONOCMD_ENUMFIELDSINCLASS=8
- MONOCMD_ENUMMETHODSINCLASS=9
- MONOCMD_COMPILEMETHOD=10
- MONOCMD_GETMETHODHEADER=11
- MONOCMD_GETMETHODHEADER_CODE=12
- MONOCMD_LOOKUPRVA=13
- MONOCMD_GETJITINFO=14
- MONOCMD_FINDCLASS=15
- MONOCMD_FINDMETHOD=16
- MONOCMD_GETMETHODNAME=17
- MONOCMD_GETMETHODCLASS=18
- MONOCMD_GETCLASSNAME=19
- MONOCMD_GETCLASSNAMESPACE=20
- MONOCMD_FREEMETHOD=21
- MONOCMD_TERMINATE=22
- MONOCMD_DISASSEMBLE=23
- MONOCMD_GETMETHODSIGNATURE=24
- MONOCMD_GETPARENTCLASS=25
- MONOCMD_GETSTATICFIELDADDRESSFROMCLASS=26
- MONOCMD_GETTYPECLASS=27
- MONOCMD_GETARRAYELEMENTCLASS=28
- MONOCMD_FINDMETHODBYDESC=29
- MONOCMD_INVOKEMETHOD=30
- MONOCMD_LOADASSEMBLY=31
- MONOCMD_GETFULLTYPENAME=32
- MONO_TYPE_END = 0x00 -- End of List
- MONO_TYPE_VOID = 0x01
- MONO_TYPE_BOOLEAN = 0x02
- MONO_TYPE_CHAR = 0x03
- MONO_TYPE_I1 = 0x04
- MONO_TYPE_U1 = 0x05
- MONO_TYPE_I2 = 0x06
- MONO_TYPE_U2 = 0x07
- MONO_TYPE_I4 = 0x08
- MONO_TYPE_U4 = 0x09
- MONO_TYPE_I8 = 0x0a
- MONO_TYPE_U8 = 0x0b
- MONO_TYPE_R4 = 0x0c
- MONO_TYPE_R8 = 0x0d
- MONO_TYPE_STRING = 0x0e
- MONO_TYPE_PTR = 0x0f -- arg: <type> token
- MONO_TYPE_BYREF = 0x10 -- arg: <type> token
- MONO_TYPE_VALUETYPE = 0x11 -- arg: <type> token
- MONO_TYPE_CLASS = 0x12 -- arg: <type> token
- MONO_TYPE_VAR = 0x13 -- number
- MONO_TYPE_ARRAY = 0x14 -- type, rank, boundsCount, bound1, loCount, lo1
- MONO_TYPE_GENERICINST= 0x15 -- <type> <type-arg-count> <type-1> \x{2026} <type-n> */
- MONO_TYPE_TYPEDBYREF = 0x16
- MONO_TYPE_I = 0x18
- MONO_TYPE_U = 0x19
- MONO_TYPE_FNPTR = 0x1b -- arg: full method signature */
- MONO_TYPE_OBJECT = 0x1c
- MONO_TYPE_SZARRAY = 0x1d -- 0-based one-dim-array */
- MONO_TYPE_MVAR = 0x1e -- number */
- MONO_TYPE_CMOD_REQD = 0x1f -- arg: typedef or typeref token */
- MONO_TYPE_CMOD_OPT = 0x20 -- optional arg: typedef or typref token */
- MONO_TYPE_INTERNAL = 0x21 -- CLR internal type */
- MONO_TYPE_MODIFIER = 0x40 -- Or with the following types */
- MONO_TYPE_SENTINEL = 0x41 -- Sentinel for varargs method signature */
- MONO_TYPE_PINNED = 0x45 -- Local var that points to pinned object */
- MONO_TYPE_ENUM = 0x55 -- an enumeration */
- monoTypeToVartypeLookup={}
- monoTypeToVartypeLookup[MONO_TYPE_BOOLEAN]=vtByte
- monoTypeToVartypeLookup[MONO_TYPE_CHAR]=vtString
- monoTypeToVartypeLookup[MONO_TYPE_I1]=vtByte
- monoTypeToVartypeLookup[MONO_TYPE_U1]=vtByte
- monoTypeToVartypeLookup[MONO_TYPE_I2]=vtWord
- monoTypeToVartypeLookup[MONO_TYPE_U2]=vtWord
- monoTypeToVartypeLookup[MONO_TYPE_I4]=vtDword
- monoTypeToVartypeLookup[MONO_TYPE_U4]=vtDword
- monoTypeToVartypeLookup[MONO_TYPE_I8]=vtQword
- monoTypeToVartypeLookup[MONO_TYPE_U8]=vtQword
- monoTypeToVartypeLookup[MONO_TYPE_R4]=vtSingle
- monoTypeToVartypeLookup[MONO_TYPE_R8]=vtDouble
- monoTypeToVartypeLookup[MONO_TYPE_STRING]=vtPointer --pointer to a string object
- monoTypeToVartypeLookup[MONO_TYPE_PTR]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_BYREF]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_CLASS]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_FNPTR]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_GENERICINST]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_ARRAY]=vtPointer
- monoTypeToVartypeLookup[MONO_TYPE_SZARRAY]=vtPointer
- FIELD_ATTRIBUTE_FIELD_ACCESS_MASK=0x0007
- FIELD_ATTRIBUTE_COMPILER_CONTROLLED=0x0000
- FIELD_ATTRIBUTE_PRIVATE=0x0001
- FIELD_ATTRIBUTE_FAM_AND_ASSEM=0x0002
- FIELD_ATTRIBUTE_ASSEMBLY=0x0003
- FIELD_ATTRIBUTE_FAMILY=0x0004
- FIELD_ATTRIBUTE_FAM_OR_ASSEM=0x0005
- FIELD_ATTRIBUTE_PUBLIC=0x0006
- FIELD_ATTRIBUTE_STATIC=0x0010
- FIELD_ATTRIBUTE_INIT_ONLY=0x0020
- FIELD_ATTRIBUTE_LITERAL=0x0040
- FIELD_ATTRIBUTE_NOT_SERIALIZED=0x0080
- FIELD_ATTRIBUTE_SPECIAL_NAME=0x0200
- FIELD_ATTRIBUTE_PINVOKE_IMPL=0x2000
- FIELD_ATTRIBUTE_RESERVED_MASK=0x9500
- FIELD_ATTRIBUTE_RT_SPECIAL_NAME=0x0400
- FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL=0x1000
- FIELD_ATTRIBUTE_HAS_DEFAULT=0x8000
- FIELD_ATTRIBUTE_HAS_FIELD_RVA=0x0100
- MONO_TYPE_NAME_FORMAT_IL=0
- MONO_TYPE_NAME_FORMAT_REFLECTION=1
- MONO_TYPE_NAME_FORMAT_FULL_NAME=2
- MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED=3
- function monoTypeToVarType(monoType)
- --MonoTypeEnum
- local result=monoTypeToVartypeLookup[monoType]
- if result==nil then
- result=vtDword --just give it something
- end
- return result
- end
- function LaunchMonoDataCollector()
- if debug_canBreak() then return 0 end
- if (monopipe~=nil) then
- if (mono_AttachedProcess==getOpenedProcessID()) then
- return monoBase --already attached to this process
- end
- monopipe.destroy()
- monopipe=nil
- end
- if (monoeventpipe~=nil) then
- monoeventpipe.destroy()
- monoeventpipe=nil
- end
- local dllname="MonoDataCollector"
- if targetIs64Bit() then
- dllname=dllname.."64.dll"
- else
- dllname=dllname.."32.dll"
- end
- if injectDLL(getCheatEngineDir()..[[\autorun\dlls\]]..dllname)==false then
- print("Failure injecting the MonoDatacollector dll")
- return 0
- end
- --wait till attached
- local timeout=getTickCount()+5000;
- while (monopipe==nil) and (getTickCount()<timeout) do
- monopipe=connectToPipe('cemonodc_pid'..getOpenedProcessID())
- end
- if (monopipe==nil) then
- return 0 --failure
- end
- --in case you implement the profiling tools use a secondary pipe to receive profiler events
- -- while (monoeventpipe==nil) do
- -- monoeventpipe=connectToPipe('cemonodc_pid'..getOpenedProcessID()..'_events')
- -- end
- mono_AttachedProcess=getOpenedProcessID()
- monopipe.writeByte(CMD_INITMONO)
- monopipe.ProcessID=getOpenedProcessID()
- monoBase=monopipe.readQword()
- if (monoBase~=0) then
- if mono_AddressLookupID==nil then
- mono_AddressLookupID=registerAddressLookupCallback(mono_addressLookupCallback)
- end
- if mono_SymbolLookupID==nil then
- mono_SymbolLookupID=registerSymbolLookupCallback(mono_symbolLookupCallback, slNotSymbol)
- end
- if mono_StructureNameLookupID==nil then
- mono_StructureNameLookupID=registerStructureNameLookup(mono_structureNameLookupCallback)
- end
- if mono_StructureDissectOverrideID==nil then
- mono_StructureDissectOverrideID=registerStructureDissectOverride(mono_structureDissectOverrideCallback)
- end
- end
- if (monoSettings==nil) then
- monoSettings=getSettings("MonoExtension")
- end
- return monoBase
- end
- function mono_structureDissectOverrideCallback(structure, baseaddress)
- -- print("oc")
- local realaddress, classaddress=mono_object_findRealStartOfObject(baseaddress)
- if (realaddress==baseaddress) then
- local smap = {}
- local s = monoform_exportStructInternal(structure, classaddress, true, false, smap, false)
- return s~=nil
- else
- return nil
- end
- end
- function mono_structureNameLookupCallback(address)
- local currentaddress, classaddress, classname
- local always=monoSettings.Value["AlwaysUseForDissect"]
- local r
- if (always==nil) or (always=="") then
- r=messageDialog("Do you wish to let the mono extention figure out the name and start address? If it's not a proper object this may crash the target.", mtConfirmation, mbYes, mbNo, mbYesToAll, mbNoToAll)
- else
- if (always=="1") then
- r=mrYes
- else
- r=mrNo
- end
- end
-
-
- if (r==mrYes) or (r==mbYesToAll) then
- currentaddress, classaddress, classname=mono_object_findRealStartOfObject(address)
- if (currentaddress~=nil) then
- -- print("currentaddress~=nil : "..currentaddress)
- return classname,currentaddress
- else
- -- print("currentaddress==nil")
- return nil
- end
- end
- --still alive, so the user made a good choice
- if (r==mrYesToAll) then
- monoSettings.Value["AlwaysUseForDissect"]="1"
- elseif (r==mrNoToAll) then
- monoSettings.Value["AlwaysUseForDissect"]="0"
- end
- end
- function mono_symbolLookupCallback(symbol)
- if debug_canBreak() then return nil end
- local parts={}
- local x
- for x in string.gmatch(symbol, "[^:]+") do
- table.insert(parts, x)
- end
- local methodname=''
- local classname=''
- local namespace=''
- if (#parts>0) then
- methodname=parts[#parts]
- if (#parts>1) then
- classname=parts[#parts-1]
- if (#parts>2) then
- namespace=parts[#parts-2]
- end
- end
- end
- if (methodname~='') and (classname~='') then
- local method=mono_findMethod(namespace, classname, methodname)
- if (method==0) then
- return nil
- end
- local methodaddress=mono_compile_method(method)
- if (methodaddress~=0) then
- return methodaddress
- end
- end
- --still here,
- return nil
- end
- function mono_addressLookupCallback(address)
- if (inMainThread()==false) or (debug_canBreak()) then --the debugger thread might call this
- return nil
- end
- local ji=mono_getJitInfo(address)
- local result=''
- if ji~=nil then
- --[[
- ji.jitinfo;
- ji.method
- ji.code_start
- ji.code_size
- --]]
- if (ji.method~=0) then
- local class=mono_method_getClass(ji.method)
- if class==nil then return nil end
- local classname=mono_class_getName(class)
- local namespace=mono_class_getNamespace(class)
- if (classname==nil) or (namespace==nil) then return nil end
- if namespace~='' then
- namespace=namespace..':'
- end
- result=namespace..classname..":"..mono_method_getName(ji.method)
- if address~=ji.code_start then
- result=result..string.format("+%x",address-ji.code_start)
- end
- end
- end
- return result
- end
- function mono_object_getClass(address)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_OBJECT_GETCLASS)
- monopipe.writeQword(address)
- local classaddress=monopipe.readQword()
- if (classaddress~=nil) and (classaddress~=0) then
- local stringlength=monopipe.readWord()
- local classname
- if stringlength>0 then
- classname=monopipe.readString(stringlength)
- end
- monopipe.unlock()
- return classaddress, classname
- else
- monopipe.unlock()
- return nil
- end
- end
- function mono_enumDomains()
- if debug_canBreak() then return nil end
- if monopipe==nil then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_ENUMDOMAINS)
- local count=monopipe.readDword()
- local result={}
- local i
- if (count~=nil) then
- for i=1, count do
- result[i]=monopipe.readQword()
- end
- end
- monopipe.unlock()
- return result
- end
- function mono_setCurrentDomain(domain)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_SETCURRENTDOMAIN)
- monopipe.writeQword(domain)
- local result=monopipe.readDword()
- monopipe.unlock()
- return result;
- end
- function mono_enumAssemblies()
- local result=nil
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_ENUMASSEMBLIES)
- local count=monopipe.readDword()
- if count~=nil then
- result={}
- local i
- for i=1, count do
- result[i]=monopipe.readQword()
- end
- end
- monopipe.unlock()
- return result
- end
- function mono_getImageFromAssembly(assembly)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETIMAGEFROMASSEMBLY)
- monopipe.writeQword(assembly)
- monopipe.unlock()
- return monopipe.readQword()
- end
- function mono_image_get_name(image)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETIMAGENAME)
- monopipe.writeQword(image)
- local namelength=monopipe.readWord()
- local name=monopipe.readString(namelength)
- monopipe.unlock()
- return name
- end
- function mono_image_enumClasses(image)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_ENUMCLASSESINIMAGE)
- monopipe.writeQword(image)
- local classcount=monopipe.readDword()
- local classes={}
- local i;
- for i=1, classcount do
- classes[i]={}
- classes[i].class=monopipe.readQword()
- local classnamelength=monopipe.readWord()
- if classnamelength>0 then
- classes[i].classname=monopipe.readString(classnamelength)
- else
- classes[i].classname=''
- end
- local namespacelength=monopipe.readWord()
- if namespacelength>0 then
- classes[i].namespace=monopipe.readString(namespacelength)
- else
- classes[i].namespace=''
- end
-
- end
- monopipe.unlock()
- return classes;
- end
- function mono_class_getName(clasS)
- if debug_canBreak() then return nil end
- local result=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETCLASSNAME)
- monopipe.writeQword(clasS)
- local namelength=monopipe.readWord();
- result=monopipe.readString(namelength);
- monopipe.unlock()
- return result;
- end
- function mono_class_getNamespace(clasS)
- if debug_canBreak() then return nil end
- local result=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETCLASSNAMESPACE)
- monopipe.writeQword(clasS)
- local namelength=monopipe.readWord();
- result=monopipe.readString(namelength);
- monopipe.unlock()
- return result;
- end
- function mono_class_getFullName(typeptr, isclass, nameformat)
- if debug_canBreak() then return nil end
- if isclass==nil then isclass=1 end
- if nameformat==nil then nameformat=MONO_TYPE_NAME_FORMAT_REFLECTION end
- local result=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETFULLTYPENAME)
- monopipe.writeQword(typeptr)
- monopipe.writeByte(isclass)
- monopipe.writeDword(nameformat)
- local namelength=monopipe.readWord();
- result=monopipe.readString(namelength);
- monopipe.unlock()
- return result;
- end
- function mono_class_getParent(class)
- if debug_canBreak() then return nil end
- local result=0
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETPARENTCLASS)
- monopipe.writeQword(class)
- result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_type_getClass(monotype)
- if debug_canBreak() then return nil end
- local result=0
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETTYPECLASS)
- monopipe.writeQword(monotype)
- result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_class_getArrayElementClass(klass)
- if debug_canBreak() then return nil end
- local result=0
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETARRAYELEMENTCLASS)
- monopipe.writeQword(klass)
- result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_class_getStaticFieldAddress(domain, class)
- if debug_canBreak() then return nil end
- local result=0
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETSTATICFIELDADDRESSFROMCLASS)
- monopipe.writeQword(domain)
- monopipe.writeQword(class)
- result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_class_enumFields(class)
- if debug_canBreak() then return nil end
- local classfield;
- local index=1;
- local fields={}
- monopipe.lock()
- monopipe.writeByte(MONOCMD_ENUMFIELDSINCLASS)
- monopipe.writeQword(class)
- repeat
- classfield=monopipe.readQword()
- if (classfield~=nil) and (classfield~=0) then
- local namelength;
- fields[index]={}
- fields[index].field=classfield
- fields[index].type=monopipe.readQword()
- fields[index].monotype=monopipe.readDword()
- fields[index].parent=monopipe.readQword()
- fields[index].offset=monopipe.readDword()
- fields[index].flags=monopipe.readDword()
-
- fields[index].isStatic=(bAnd(fields[index].flags, bOr(FIELD_ATTRIBUTE_STATIC, FIELD_ATTRIBUTE_HAS_FIELD_RVA))) ~= 0 --check mono for other fields you'd like to test
- fields[index].isConst=(bAnd(fields[index].flags, FIELD_ATTRIBUTE_LITERAL)) ~= 0
- namelength=monopipe.readWord();
- fields[index].name=monopipe.readString(namelength);
- namelength=monopipe.readWord();
- fields[index].typename=monopipe.readString(namelength);
- index=index+1
- end
- until (classfield==nil) or (classfield==0)
- monopipe.unlock()
- return fields
- end
- function mono_class_enumMethods(class)
- if debug_canBreak() then return nil end
- local method
- local index=1
- local methods={}
- monopipe.lock()
- monopipe.writeByte(MONOCMD_ENUMMETHODSINCLASS)
- monopipe.writeQword(class)
- repeat
- method=monopipe.readQword()
- if (method~=nil) and (method~=0) then
- local namelength;
- methods[index]={}
- methods[index].method=method
- namelength=monopipe.readWord();
- methods[index].name=monopipe.readString(namelength);
- index=index+1
- end
- until (method==nil) or (method==0)
- monopipe.unlock()
- return methods
- end
- function mono_getJitInfo(address)
- if debug_canBreak() then return nil end
- local d=mono_enumDomains()
- if (d~=nil) then
- monopipe.lock()
- for i=1, #d do
- monopipe.writeByte(MONOCMD_GETJITINFO)
- monopipe.writeQword(d[i])
- monopipe.writeQword(address)
- local jitinfo=monopipe.readQword()
- if (jitinfo~=nil) and (jitinfo~=0) then
- local result={}
- result.jitinfo=jitinfo;
- result.method=monopipe.readQword();
- result.code_start=monopipe.readQword();
- result.code_size=monopipe.readDword();
- monopipe.unlock() --found something
- return result
- end
- end
- monopipe.unlock()
- end
- return nil
- end
- function mono_object_findRealStartOfObject(address, maxsize)
- if debug_canBreak() then return nil end
- if maxsize==nil then
- maxsize=4096
- end
- if address==nil then
- error("address==nil")
- end
- local currentaddress=bAnd(address, 0xfffffffffffffffc)
- while (currentaddress>address-maxsize) do
- local classaddress,classname=mono_object_getClass(currentaddress)
- if (classaddress~=nil) and (classname~=nil) then
- classname=classname:match "^%s*(.-)%s*$" --trim
- if (classname~='') then
- local r=string.find(classname, "[^%a%d_.]", 1) --scan for characters that are not decimal or characters, or have a _ or . in the name
- if (r==nil) or (r>=5) then
- return currentaddress, classaddress, classname --good enough
- end
- end
- end
- currentaddress=currentaddress-4
- end
- --still here
- return nil
- end
- --function mono_findReferencesToObject(class) --scan the memory for objects with a vtable to a specific class
- --end
- function mono_image_findClass(image, namespace, classname)
- if debug_canBreak() then return nil end
- --find a class in a specific image
- monopipe.lock()
- monopipe.writeByte(MONOCMD_FINDCLASS)
- monopipe.writeQword(image)
- monopipe.writeWord(#classname)
- monopipe.writeString(classname)
- if (namespace~=nil) then
- monopipe.writeWord(#namespace)
- monopipe.writeString(namespace)
- else
- monopipe.writeWord(0)
- end
- result=monopipe.readQword()
- monopipe.unlock()
- return result
- end
- function mono_findClass(namespace, classname)
- if debug_canBreak() then return nil end
- --searches all images for a specific class
- local ass=mono_enumAssemblies()
- local result=0
- for i=1, #ass do
- result=mono_image_findClass(mono_getImageFromAssembly(ass[i]), namespace, classname)
- if (result~=0) then
- return result;
- end
- end
- --still here:
- return 0
- end
- function mono_class_findMethod(class, methodname)
- if debug_canBreak() then return nil end
- if methodname==nil then return 0 end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_FINDMETHOD)
- monopipe.writeQword(class)
- monopipe.writeWord(#methodname)
- monopipe.writeString(methodname)
- local result=monopipe.readQword()
- monopipe.unlock()
- return result
- end
- function mono_findMethod(namespace, classname, methodname)
- if debug_canBreak() then return nil end
- local class=mono_findClass(namespace, classname)
- local result=0
- if class~=0 then
- result=mono_class_findMethod(class, methodname)
- end
- return result
- end
- function mono_class_findMethodByDesc(image, methoddesc)
- if debug_canBreak() then return nil end
- if image==nil then return 0 end
- if methoddesc==nil then return 0 end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_FINDMETHODBYDESC)
- monopipe.writeQword(image)
- monopipe.writeWord(#methoddesc)
- monopipe.writeString(methoddesc)
- local result=monopipe.readQword()
- monopipe.unlock()
- return result
- end
- function mono_findMethodByDesc(assemblyname, methoddesc)
- if debug_canBreak() then return nil end
- local assemblies = mono_enumAssemblies()
- for i=1, #assemblies do
- local image = mono_getImageFromAssembly(assemblies[i])
- local imagename = mono_image_get_name(image)
- if imagename == 'UnityEngine' then
- return mono_class_findMethodByDesc(image, methoddesc)
- end
- end
- return nil
- end
- --idea for the future:
- --function mono_invokeMethod()
- -- print("Not yet implemented")
- --end
- function mono_method_getName(method)
- if debug_canBreak() then return nil end
- local result=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETMETHODNAME)
- monopipe.writeQword(method)
- local namelength=monopipe.readWord();
- result=monopipe.readString(namelength);
- monopipe.unlock()
- return result;
- end
- function mono_method_getHeader(method)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETMETHODHEADER)
- monopipe.writeQword(method)
- local result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_method_getSignature(method)
- --Gets the method 'signature', the corresponding parameter names, and the returntype
- if debug_canBreak() then return nil end
- local result=''
- local parameternames={}
- local returntype=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETMETHODSIGNATURE)
- monopipe.writeQword(method)
- local paramcount=monopipe.readByte()
- local i
-
- for i=1, paramcount do
- local namelength=monopipe.readByte()
- if namelength>0 then
- parameternames[i]=monopipe.readString(namelength)
- else
- parameternames[i]='param'..i
- end
- end
- local resultlength=monopipe.readWord();
- result=monopipe.readString(resultlength);
- local returntypelength=monopipe.readByte()
- returntype=monopipe.readString(returntypelength)
-
- monopipe.unlock()
- return result, parameternames, returntype;
- end
- function mono_method_disassemble(method)
- if debug_canBreak() then return nil end
- local result=''
- monopipe.lock()
- monopipe.writeByte(MONOCMD_DISASSEMBLE)
- monopipe.writeQword(method)
- local resultlength=monopipe.readWord();
- result=monopipe.readString(resultlength);
- monopipe.unlock()
- return result;
- end
- function mono_method_getClass(method)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETMETHODCLASS)
- monopipe.writeQword(method)
- local result=monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- function mono_compile_method(method) --Jit a method if it wasn't jitted yet
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_COMPILEMETHOD)
- monopipe.writeQword(method)
- local result=monopipe.readQword()
- monopipe.unlock()
- return result
- end
- --note: does not work while the profiler is active (Current implementation doesn't use the profiler, so we're good to go)
- function mono_free_method(method) --unjit the method. Only works on dynamic methods. (most are not)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_FREEMETHOD)
- monopipe.writeQword(method)
- monopipe.unlock()
- end
- function mono_methodheader_getILCode(methodheader)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_GETMETHODHEADER_CODE)
- monopipe.writeQword(methodheader)
- local address=monopipe.readQword()
- local size=monopipe.readDword()
- monopipe.unlock()
- return address, size;
- end
- function mono_getILCodeFromMethod(method)
- local hdr=mono_method_getHeader(method)
- return mono_methodheader_getILCode(hdr)
- end
- function mono_image_rva_map(image, offset)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_LOOKUPRVA)
- monopipe.writeQword(image)
- monopipe.writeDword(offset)
- local address=monopipe.readQword()
- monopipe.unlock()
- return address;
- end
- function mono_readObject()
- local vtype = monopipe.readByte()
- if vtype == MONO_TYPE_VOID then
- return nil
- elseif vtype == MONO_TYPE_STRING then
- local resultlength=monopipe.readWord();
- return monopipe.readString(resultlength);
- end
-
- local vartype = monoTypeToVartypeLookup[vtype]
- if vartype == vtByte then
- return monopipe.readByte()
- elseif vartype == vtWord then
- return monopipe.readWord()
- elseif vartype == vtDword then
- return monopipe.readDword()
- elseif vartype == vtQword then
- return monopipe.readQword()
- elseif vartype == vtSingle then
- return monopipe.readFloat()
- elseif vartype == vtDouble then
- return monopipe.readDouble()
- elseif vartype == vtPointer then
- return monopipe.readQword()
- end
- return nil
- end
- function mono_writeObject(vartype, value)
- if vartype == vtString then
- -- monopipe.writeByte(MONO_TYPE_STRING)
- monopipe.writeWord(#value);
- monopipe.writeString(value);
- elseif vartype == vtByte then
- -- monopipe.writeByte(MONO_TYPE_I1)
- monopipe.writeByte(value)
- elseif vartype == vtWord then
- -- monopipe.writeByte(MONO_TYPE_I2)
- monopipe.writeWord(value)
- elseif vartype == vtDword then
- -- monopipe.writeByte(MONO_TYPE_I4)
- monopipe.writeDword(value)
- elseif vartype == vtPointer then
- -- monopipe.writeByte(MONO_TYPE_PTR)
- monopipe.writeQword(value)
- elseif vartype == vtQword then
- -- monopipe.writeByte(MONO_TYPE_I8)
- monopipe.writeQword(value)
- elseif vartype == vtSingle then
- -- monopipe.writeByte(MONO_TYPE_R4)
- monopipe.writeFloat(value)
- elseif vartype == vtDouble then
- -- monopipe.writeByte(MONO_TYPE_R8)
- monopipe.writeDouble(value)
- else
- -- monopipe.writeByte(MONO_TYPE_VOID)
- end
- return nil
-
- end
- function mono_writeVarType(vartype)
- if vartype == vtString then
- monopipe.writeByte(MONO_TYPE_STRING)
- elseif vartype == vtByte then
- monopipe.writeByte(MONO_TYPE_I1)
- elseif vartype == vtWord then
- monopipe.writeByte(MONO_TYPE_I2)
- elseif vartype == vtDword then
- monopipe.writeByte(MONO_TYPE_I4)
- elseif vartype == vtPointer then
- monopipe.writeByte(MONO_TYPE_PTR)
- elseif vartype == vtQword then
- monopipe.writeByte(MONO_TYPE_I8)
- elseif vartype == vtSingle then
- monopipe.writeByte(MONO_TYPE_R4)
- elseif vartype == vtDouble then
- monopipe.writeByte(MONO_TYPE_R8)
- else
- monopipe.writeByte(MONO_TYPE_VOID)
- end
- end
- function mono_invoke_method(domain, method, object, args)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_INVOKEMETHOD)
- monopipe.writeQword(domain)
- monopipe.writeQword(method)
- monopipe.writeQword(object)
- monopipe.writeWord(#args)
- for i=1, #args do
- mono_writeVarType(args[i].type)
- end
- for i=1, #args do
- mono_writeObject(args[i].type, args[i].value)
- end
-
- local result=mono_readObject()
- monopipe.unlock()
- return result;
-
- end
- function mono_loadAssemblyFromFile(fname)
- if debug_canBreak() then return nil end
- monopipe.lock()
- monopipe.writeByte(MONOCMD_LOADASSEMBLY)
- monopipe.writeWord(#fname)
- monopipe.writeString(fname)
- local result = monopipe.readQword()
- monopipe.unlock()
- return result;
- end
- --[[
- --------code belonging to the mono dissector form---------
- --]]
- function monoform_killform(sender)
- return caFree
- end
- function monoform_miShowILDisassemblyClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
- local f=createForm()
- f.BorderStyle=bsSizeable
- f.centerScreen()
- f.Caption=node.Text
- f.OnClose=function(sender) return caFree end
- local m=createMemo(f)
- m.Align=alClient
- m.ScrollBars=ssBoth
- m.Lines.Text=mono_method_disassemble(node.Data)
- end
- end
- end
- function monoform_miRejitClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
- local r=mono_compile_method(node.Data)
- getMemoryViewForm().DisassemblerView.SelectedAddress=r
- getMemoryViewForm().show()
- -- print(string.format("Method at %x", r))
- end
- end
- end
- function monoform_miGetILCodeClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods') then
- local r,s=mono_getILCodeFromMethod(node.Data)
- if r~=nil then
- print(string.format("ILCode from %x to %x", r,r+s))
- end
- end
- end
- end
- function monoform_miDissectStaticStructureClick(sender)
- -- combine adding static to dissect and to table
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
- monoform_miAddStaticFieldAddressClick(sender)
- local smap = monoform_getStructMap()
- local s = monoform_exportStruct(node.Data, nil, true, true, smap, true, false)
- end
- end
- end
- function monoform_miAddStructureClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
- local smap = monoform_getStructMap()
- local s = monoform_exportStruct(node.Data, nil, false, false, smap, true, false)
- s = monoform_exportStruct(node.Data, nil, false, true, smap, true, false)
- end
- end
- end
- function monoform_miAddStructureRecursiveClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- if (node~=nil) and (node.Data~=nil) and (node.Level==2) then
- local smap = monoform_getStructMap()
- local s = monoform_exportStruct(node.Data, nil, true, false, smap, true, false)
- s = monoform_exportStruct(node.Data, nil, true, true, smap, true, false)
- end
- end
- end
- -- Add the script for locating static data pointer for a class and adding records
- function monoform_AddStaticClass(domain, image, class)
- if domain==nil or image==nil or class==nil then
- return
- end
-
- local addrs = getAddressList()
- local classname=mono_class_getName(class)
- local namespace=mono_class_getNamespace(class)
- local assemblyname=mono_image_get_name(image)
- local prefix, rootmr, mr
- prefix = ''
- rootmr=addresslist_createMemoryRecord(addrs)
- rootmr.Description = "Resolve "..classname
- rootmr.Type = vtAutoAssembler
- local symclassname = classname:gsub("([^A-Za-z0-9%.,_$`<>%[%]])", "")
- local script = {}
- script[#script+1] = '[ENABLE]'
- script[#script+1] = monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symclassname, true)
- script[#script+1] = '[DISABLE]'
- script[#script+1] = monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symclassname, false)
- rootmr.Script = table.concat(script,"\n")
- memoryrecord_setColor(rootmr, 0xFF0000)
- --local data = mono_class_getStaticFieldAddress(domain, class)
- --rootmr.Address = string.format("%08X",data)
- --rootmr.Type = vtPointer
- mr=addresslist_createMemoryRecord(addrs)
- mr.Description=classname..'.Static'
- mr.Address='['..symclassname..".Static]"
- mr.Type=vtPointer
- mr.appendToEntry(rootmr)
- mr=addresslist_createMemoryRecord(addrs)
- mr.Description=classname..'.Class'
- mr.Address='['..symclassname..".Class]"
- mr.Type=vtPointer
- mr.appendToEntry(rootmr)
- local i
- local fields=mono_class_enumFields(class)
- for i=1, #fields do
- if fields[i].isStatic and not fields[i].isConst and (field==nil or fields[i].field==field) then
- local fieldName = fields[i].name:gsub("([^A-Za-z0-9%.,_$`<>%[%]])", "")
- local offset = fields[i].offset
- if fieldName==nil or fieldName:len()==0 then
- fieldName = string.format("Offset %x", offset)
- end
- mr=addresslist_createMemoryRecord(addrs)
- mr.Description=prefix..fieldName
- if fields[i].monotype==MONO_TYPE_STRING then
- -- mr.Address=string.format("[[%s.Static]+%X]+C",symclassname,offset)
- mr.Address=symclassname..'.Static'
- mr.OffsetCount=2
- mr.Offset[0]=0xC
- mr.Offset[1]=offset
- mr.Type=vtString
- memoryrecord_string_setUnicode(mr, true)
- memoryrecord_string_setSize(mr, 80)
- else
- mr.Address=symclassname..'.Static'
- mr.OffsetCount=1
- mr.Offset[0]=offset
- mr.Type=monoTypeToVarType(fields[i].monotype)
- end
- if rootmr~=nil then
- mr.appendToEntry(rootmr)
- else
- break
- end
- end
- end
- end
- function monoform_AddStaticClassField(domain, image, class, fieldclass, field)
- if domain==nil or image==nil or class==nil or fieldclass==nil or field==nil then
- return
- end
- local i
- local fields=mono_class_enumFields(fieldclass)
- for i=1, #fields do
- if fields[i].field==field then
- local fieldname = fields[i].name
- local offset = fields[i].offset
- if fieldname==nil or fieldname:len()==0 then
- fieldname = string.format("Offset %x", offset)
- end
-
- local addrs = getAddressList()
- local classname=mono_class_getName(class)
- local namespace=mono_class_getNamespace(class)
- local assemblyname=mono_image_get_name(image)
- local rootmr, mr
- rootmr=addresslist_createMemoryRecord(addrs)
- rootmr.Description = "Resolve "..classname.."."..fieldname
- rootmr.Type = vtAutoAssembler
- local symclassname = classname:gsub("[^A-Za-z0-9._]", "")
- local symfieldname = fieldname:gsub("[^A-Za-z0-9._]", "")
- local script = {}
- script[#script+1] = '[ENABLE]'
- script[#script+1] = monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symclassname, true)
- script[#script+1] = '[DISABLE]'
- script[#script+1] = monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symclassname, false)
- rootmr.Script = table.concat(script,"\n")
- memoryrecord_setColor(rootmr, 0xFF0000)
-
- mr=addresslist_createMemoryRecord(addrs)
- mr.Description=classname..'.'..fieldname
- mr.appendToEntry(rootmr)
- if fields[i].monotype==MONO_TYPE_STRING then
- mr.Address=symclassname..'.'..symfieldname
- mr.OffsetCount=1
- mr.Offset[0]=0xC
- mr.Type=vtString
- memoryrecord_string_setUnicode(mr, true)
- memoryrecord_string_setSize(mr, 80)
- else
- mr.Address="["..symclassname..'.'..symfieldname.."]"
- mr.Type=monoTypeToVarType(fields[i].monotype)
- end
- break
- end
- end
- end
- function monoform_miAddStaticFieldAddressClick(sender)
- if (monoForm.TV.Selected~=nil) then
- local node=monoForm.TV.Selected
- local domain, image, class, field
- if (node~=nil) and (node.Data~=nil) then
- if (node.Level>=4) and (node.Parent.Text=='static fields') then
- local inode = node.Parent.Parent.Parent
- local cnode = node.Parent.Parent
- local fieldclass = cnode.Data
- while inode.Text == 'base class' do
- cnode = inode.Parent
- inode = cnode.Parent
- end
- domain = inode.Parent.Data
- image = inode.Data
- class = cnode.Data
- field = node.Data
- monoform_AddStaticClassField(domain, image, class, fieldclass, field)
- elseif (node~=nil) and (node.Data~=nil) and (node.Level==2) then
- domain = node.Parent.Parent.Data
- image = node.Parent.Data
- class = node.Data
- monoform_AddStaticClass(domain, image, class)
- elseif (node~=nil) and (node.Data~=nil) and (node.Level==3) then
- domain = node.Parent.Parent.Parent.Data
- image = node.Parent.Parent.Data
- class = node.Parent.Data
- monoform_AddStaticClass(domain, image, class)
- end
- end
- end
- end
- function monoform_context_onpopup(sender)
- local node=monoForm.TV.Selected
- local methodsEnabled = (node~=nil) and (node.Level==4) and (node.Parent.Text=='methods')
- monoForm.miRejit.Enabled = methodsEnabled
- monoForm.miGetILCode.Enabled = methodsEnabled
- monoForm.miShowILDisassembly.Enabled = methodsEnabled
- local structuresEnabled = (node~=nil) and (node.Data~=nil) and (node.Level==2)
- monoForm.miExportStructure.Enabled = structuresEnabled
- local fieldsEnabled = (node~=nil) and (node.Data~=nil)
- and ( (node.Level==2)
- or ((node.Level>=3) and (node.Text=='static fields'))
- or ((node.Level>=4) and (node.Parent.Text=='static fields')))
- monoForm.miFieldsMenu.Enabled = fieldsEnabled
- monoForm.miAddStaticFieldAddress.Enabled = fieldsEnabled
- end
- function monoform_EnumImages(node)
- --print("monoform_EnumImages")
- local i
- local domain=node.Data
- --mono_setCurrentDomain(domain)
- local assemblies=mono_enumAssemblies()
- for i=1, #assemblies do
- local image=mono_getImageFromAssembly(assemblies[i])
- local imagename=mono_image_get_name(image)
- local n=node.add(string.format("%x : %s", image, imagename))
- n.HasChildren=true;
- n.Data=image
- end
- end
- function monoform_AddClass(node, klass, namespace, classname, fqname)
- local desc=string.format("%x : %s", klass, fqname)
- local n=node.add(desc)
- n.Data=klass
-
- local nf=n.add("static fields")
- nf.Data=klass
- nf.HasChildren=true
-
- local nf=n.add("fields")
- nf.Data=klass
- nf.HasChildren=true
- local nm=n.add("methods")
- nm.Data=klass
- nm.HasChildren=true
-
- local p = mono_class_getParent(klass)
- if p~=nil then
- local np=n.add("base class")
- np.Data=p
- np.HasChildren=true
- end
- end
- function monoform_EnumClasses(node)
- --print("monoform_EnumClasses")
- local image=node.Data
- local classes=mono_image_enumClasses(image)
- local i
- if classes~=nil then
- for i=1, #classes do
- classes[i].fqname = mono_class_getFullName(classes[i].class)
- end
-
- local monoform_class_compare = function (a,b)
- if a.namespace < b.namespace then
- return true
- elseif b.namespace < a.namespace then
- return false
- end
- if a.fqname < b.fqname then
- return true
- elseif b.fqname < a.fqname then
- return false
- end
- return a.class < b.class
- end
-
- table.sort(classes, monoform_class_compare)
- for i=1, #classes do
- monoform_AddClass(node, classes[i].class, classes[i].namespace, classes[i].classname, classes[i].fqname)
- end
- end
- end;
- function monoform_EnumFields(node, static)
- -- print("monoform_EnumFields")
- local i
- local class=node.Data;
- local fields=mono_class_enumFields(class)
- for i=1, #fields do
- if fields[i].isStatic == static and not fields[i].isConst then
- local n=node.add(string.format("%x : %s (type: %s)", fields[i].offset, fields[i].name, fields[i].typename))
- n.Data=fields[i].field
- end
- end
- end
- function monoform_EnumMethods(node)
- --print("monoform_EnumMethods")
- local i
- local class=node.Data;
- local methods=mono_class_enumMethods(class)
- for i=1, #methods do
- local n=node.add(string.format("%x : %s", methods[i].method, methods[i].name))
- n.Data=methods[i].method
- end
- end
- function mono_TVExpanding(sender, node)
- --print("mono_TVExpanding")
- --print("node.Count="..node.Count)
- --print("node.Level="..node.Level)
- local allow=true
- if (node.Count==0) then
- if (node.Level==0) then --images
- monoform_EnumImages(node)
- elseif (node.Level==1) then --classes
- monoform_EnumClasses(node)
- elseif (node.Level>=3) and (node.Text=='static fields') then --static fields
- monoform_EnumFields(node, true)
- elseif (node.Level>=3) and (node.Text=='fields') then --fields
- monoform_EnumFields(node, false)
- elseif (node.Level>=3) and (node.Text=='methods') then --methods
- monoform_EnumMethods(node)
- elseif (node.Level>=3) and (node.Text=='base class') then
- if (monoForm.autoExpanding==nil) or (monoForm.autoExpanding==false) then
- local klass = node.Data
- if (klass ~= 0) then
- local classname=mono_class_getName(klass)
- local namespace=mono_class_getNamespace(klass)
- local fqname=mono_class_getFullName(klass)
- monoform_AddClass(node, klass, namespace, classname, fqname)
- end
- else
- allow=false --don't auto expand the base classes
- end
- end
- end
- return allow
- end
- function mono_TVCollapsing(sender, node)
- local allow=true
- return allow
- end
- function monoform_FindDialogFind(sender)
- local texttofind=string.lower(monoForm.FindDialog.FindText)
- local tv=monoForm.TV
- local startindex=0
- if tv.Selected~=nil then
- startindex=tv.Selected.AbsoluteIndex+1
- end
- local i
- if string.find(monoForm.FindDialog.Options, 'frEntireScope') then
- --deep scan
- tv.beginUpdate()
- i=startindex
- while i<tv.Items.Count do
- local node=monoForm.TV.items[i]
- local text=string.lower(node.Text)
- if string.find(text, texttofind)~=nil then
- --found it
- tv.Selected=node
- break
- end
- if node.HasChildren then
- node.Expand(false)
- end
- i=i+1
- end
- tv.endUpdate()
- else
- --just the already scanned stuff
- for i=startindex, tv.Items.Count-1 do
- local node=monoForm.TV.items[i]
- local text=string.lower(node.Text)
- if string.find(text, texttofind)~=nil then
- --found it
- tv.Selected=node
- return
- end
- end
- end
- end
- function monoform_miFindClick(sender)
- monoForm.FindDialog.execute()
- end
- function monoform_miExpandAllClick(sender)
- if messageDialog("Are you sure you wish to expand the whole tree? This can take a while and Cheat Engine may look like it has crashed (It has not)", mtConfirmation, mbYes, mbNo)==mrYes then
- monoForm.TV.beginUpdate()
- monoForm.autoExpanding=true --special feature where a base object can contain extra lua variables
- monoForm.TV.fullExpand()
- monoForm.autoExpanding=false
- monoForm.TV.endUpdate()
- end
- end
- function monoform_miSaveClick(sender)
- if monoForm.SaveDialog.execute() then
- monoForm.TV.saveToFile(monoForm.SaveDialog.Filename)
- end
- end
- function mono_dissect()
- --shows a form with a treeview that holds all the data nicely formatted.
- --only fetches the data when requested
- if (monopipe==nil) then
- LaunchMonoDataCollector()
- end
- if (monoForm==nil) then
- monoForm=createFormFromFile(getCheatEngineDir()..[[\autorun\forms\MonoDataCollector.frm]])
- end
- monoForm.show()
- monoForm.TV.Items.clear()
- local domains=mono_enumDomains()
- local i
- if (domains~=nil) then
- for i=1, #domains do
- n=monoForm.TV.Items.add(string.format("%x", domains[i]))
- n.Data=domains[i]
- monoForm.TV.Items[i-1].HasChildren=true
- end
- end
- end
- function miMonoActivateClick(sender)
- if LaunchMonoDataCollector()==0 then
- showMessage("Failure to launch")
- end
- end
- function miMonoDissectClick(sender)
- mono_dissect()
- end
- function mono_OpenProcessMT(t)
- if t~=nil then
- t.destroy()
- end
- --enumModules is faster than getAddress at OpenProcess time (No waiting for all symbols to be loaded first)
- local usesmono=false
- local m=enumModules()
- local i
- for i=1, #m do
- if (m[i].Name=='mono.dll') or (string.sub(m[i].Name,1,5)=='mono-') then
- usesmono=true
- break
- end
- end
- if usesmono then
- --create a menu item if needed
- if (miMonoTopMenuItem==nil) then
- local mfm=getMainForm().Menu
-
- if (mfm) then
- local mi
- miMonoTopMenuItem=createMenuItem(mfm)
- miMonoTopMenuItem.Caption="Mono"
- mfm.Items.insert(mfm.Items.Count-1, miMonoTopMenuItem) --add it before help
- mi=createMenuItem(miMonoTopMenuItem)
- mi.Caption="Activate mono features"
- mi.OnClick=miMonoActivateClick
- miMonoTopMenuItem.Add(mi)
- mi=createMenuItem(miMonoTopMenuItem)
- mi.Caption="Dissect mono"
- mi.Shortcut="Ctrl+Alt+M"
- mi.OnClick=miMonoDissectClick
- miMonoTopMenuItem.Add(mi)
- end
- end
- else
- --destroy the menu item if needed
- if miMonoTopMenuItem~=nil then
- miMonoTopMenuItem.destroy() --also destroys the subitems as they are owned by this menuitem
- miMonoTopMenuItem=nil
- end
- if monopipe~=nil then
- monopipe.destroy()
- monopipe=nil
- if mono_AddressLookupID~=nil then
- unregisterAddressLookupCallback(mono_AddressLookupID)
- mono_AddressLookupID=nil
- end
- if mono_SymbolLookupID~=nil then
- unregisterSymbolLookupCallback(mono_SymbolLookupID)
- mono_SymbolLookupID=nil
- end
- end
- end
- if (monopipe~=nil) and (monopipe.ProcessID~=getOpenedProcessID()) then
- --different process
- monopipe.destroy()
- monopipe=nil
- if mono_AddressLookupID~=nil then
- unregisterAddressLookupCallback(mono_AddressLookupID)
- mono_AddressLookupID=nil
- end
- if mono_SymbolLookupID~=nil then
- unregisterSymbolLookupCallback(mono_SymbolLookupID)
- mono_SymbolLookupID=nil
- end
- if mono_StructureNameLookupID~=nil then
- unregisterStructureNameLookup(mono_StructureNameLookupID)
- mono_StructureNameLookupID=nil
- end
- if mono_StructureDissectOverrideID~=nil then
- unregisterStructureDissectOverride(mono_StructureDissectOverrideID)
- mono_StructureDissectOverrideID=nil
- end
- end
- end
- function mono_OpenProcess(processid)
- --call the original onOpenProcess if there was one
- if mono_oldOnOpenProcess~=nil then
- mono_oldOnOpenProcess(processid)
- end
- synchronize("mono_OpenProcessMT")
- --t=createTimer()
- --t.Interval=1000
- --t.OnTimer="mono_OpenProcessEpilogue"
- --t.Enabled=true
- end
- function monoAA_USEMONO(parameters, syntaxcheckonly)
- --called whenever an auto assembler script encounters the USEMONO() line
- --the value you return will be placed instead of the given line
- --In this case, returning a empty string is fine
- --Special behaviour: Returning nil, with a secondary parameter being a string, will raise an exception on the auto assembler with that string
- --another example:
- --return parameters..":\nnop\nnop\nnop\n"
- --you'd then call it using usemono(00400500) for example
- if (syntaxcheckonly==false) and (LaunchMonoDataCollector()==0) then
- return nil,"The mono handler failed to initialize"
- end
- return "" --return an empty string (removes it from the internal aa assemble list)
- end
- function monoAA_FINDMONOMETHOD(parameters, syntaxcheckonly)
- --called whenever an auto assembler script encounters the MONOMETHOD() line
- --parameters: name, fullmethodnamestring
- --turns into a define that sets up name as an address to this method
- local name, fullmethodnamestring, namespace, classname, methodname, methodaddress
- local c,d,e
- --parse the parameters
- c=string.find(parameters,",")
- if c~=nil then
- name=string.sub(parameters, 1,c-1)
- fullmethodnamestring=string.sub(parameters, c+1, #parameters)
- c=string.find(fullmethodnamestring,":")
- if (c~=nil) then
- namespace=string.sub(fullmethodnamestring, 1,c-1)
- else
- namespace='';
- end
- d=string.find(fullmethodnamestring,":",c)
- if (d~=nil) then
- e=string.find(fullmethodnamestring,":",d+1)
- if e~=nil then
- classname=string.sub(fullmethodnamestring, c+1, e-1)
- methodname=string.sub(fullmethodnamestring, e+1, #fullmethodnamestring)
- else
- return nil,"Invalid parameters (Methodname could not be determined)"
- end
- else
- return nil,"Invalid parameters (Classname could not be determined)"
- end
- else
- return nil,"Invalid parameters (name could not be determined)"
- end
- classname=classname:match "^%s*(.-)%s*$" --trim
- methodname=methodname:match "^%s*(.-)%s*$" --trim
- if syntaxcheckonly then
- return "define("..name..",00000000)"
- end
- if (monopipe==nil) or (monopipe.Connected==false) then
- LaunchMonoDataCollector()
- end
- if (monopipe==nil) or (monopipe.Connected==false) then
- return nil,"The mono handler failed to initialize"
- end
- local method=mono_findMethod(namespace, classname, methodname)
- if (method==0) then
- return nil,fullmethodnamestring.." could not be found"
- end
- methodaddress=mono_compile_method(method)
- if (methodaddress==0) then
- return nil,fullmethodnamestring.." could not be jitted"
- end
- local result="define("..name..","..string.format("%x", methodaddress)..")"
- -- showMessage(result)
- return result
- end
- function monoform_getStructMap()
- -- TODO: bug check for getStructureCount which does not return value correctly in older CE
- local structmap={}
- local n=getStructureCount()
- if n==nil then
- showMessage("Sorry this feature does not work yet. getStructureCount needs patching first.")
- return nil
- end
- local fillChildStruct = function (struct, structmap)
- local i, e, s
- if struct==nil then return end
- for i=0, struct.Count-1 do
- e = struct.Element
- if e.Vartype == vtPointer then
- s = e.ChildStruct
- if s~=nil then fillChildStruct(s, structmap) end
- end
- end
- end
- for i=0, n-1 do
- local s = getStructure(i)
- structmap[s.Name]=s
- fillChildStruct(s, structmap)
- end
- return structmap
- end
- function mono_purgeDuplicateGlobalStructures()
- local smap = monoform_getStructMap()
- local n=getStructureCount()
- local slist = {}
- for i=0, n-1 do
- local s1 = getStructure(i)
- local s2 = smap[s1.Name]
- if s1 ~= s2 then
- slist[s1.Name] = s1
- end
- end
- local name
- local s
- for name, s in pairs(slist) do
- print("Removing "..name)
- structure_removeFromGlobalStructureList(s)
- end
- end
- function mono_reloadGlobalStructures(imagename)
- local smap = monoform_getStructMap()
- local classmap = {}
- local staticmap = {}
- local arraymap = {}
- local imageclasses = {}
-
- local i, j
- local fqclass, caddr
- local assemblies=mono_enumAssemblies()
- for i=1, #assemblies do
- local image=mono_getImageFromAssembly(assemblies[i])
- local iname=mono_image_get_name(image)
- if imagename==nil or imagename==iname then
- local classes=mono_image_enumClasses(image)
-
- -- purge classes
- for j=1, #classes do
- local fqclass = monoform_getfqclassname(classes[j].class, false)
- local s = smap[fqclass]
- if s ~= nil then
- structure_removeFromGlobalStructureList(s)
- classmap[fqclass] = classes[j].class
- end
- s = smap[fqclass..'[]']
- if s ~= nil then
- structure_removeFromGlobalStructureList(s)
- arraymap[fqclass..'[]'] = classes[j].class
- end
- -- check for static section
- fqclass = fqclass..'.Static'
- s = smap[fqclass]
- if s ~= nil then
- structure_removeFromGlobalStructureList(s)
- staticmap[fqclass] = classes[j].class
- end
- end
-
- -- if order function given, sort by it by passing the table and keys a, b, otherwise just sort the keys
- local spairs = function(t, order)
- local keys = {}
- for k in pairs(t) do keys[#keys+1] = k end
- if order then
- table.sort(keys, function(a,b) return order(t, a, b) end)
- else
- table.sort(keys)
- end
- local i = 0
- return function() -- return the iterator function
- i = i + 1
- if keys[i] then
- return keys[i], t[keys[i]]
- end
- end
- end
- local merge=function(...)
- local i,k,v
- local result={}
- i=1
- while true do
- local args = select(i,...)
- if args==nil then break end
- for k,v in pairs(args) do result[k]=v end
- i=i+1
- end
- return result
- end
- for fqclass, caddr in spairs(merge(classmap, arraymap, staticmap)) do
- s = createStructure(fqclass)
- structure_addToGlobalStructureList(s)
- smap[fqclass] = s
- end
- end
- end
- for fqclass, caddr in pairs(classmap) do
- print("Reloading Structure "..fqclass)
- monoform_exportStruct(caddr, fqclass, true, false, smap, false, true)
- end
- for fqclass, caddr in pairs(arraymap) do
- print("Reloading Structure "..fqclass)
- monoform_exportArrayStruct(nil, caddr, fqclass, true, false, smap, false, true)
- end
- for fqclass, caddr in pairs(staticmap) do
- print("Reloading Structure "..fqclass)
- monoform_exportStruct(caddr, fqclass, true, true, smap, false, true)
- end
- end
- function monoform_escapename(value)
- if value~=nil then
- return value:gsub("([^A-Za-z0-9%+%.,_$`<>%[%]])", "")
- end
- return nil
- end
- function monoform_getfqclassname(caddr, static)
- if (caddr==nil or caddr==0) then return nil end
- --local classname=mono_class_getName(caddr)
- --local namespace=mono_class_getNamespace(caddr)
- local classname=mono_class_getFullName(caddr)
- local namespace=nil
- local fqclass = monoform_escapename(classname)
- if fqclass==nil or string.len(fqclass) == 0 then
- return nil
- end
- if namespace~=nil and string.len(namespace) ~= 0 then
- fqclass = namespace.."."..fqclass
- end
- if static then
- fqclass = fqclass..".Static"
- end
- return fqclass
- end
- function monoform_exportStruct(caddr, typename, recursive, static, structmap, makeglobal, reload)
- local fqclass = monoform_getfqclassname(caddr, static)
- if typename==nil then
- typename = fqclass
- end
- if typename == nil then
- return nil
- end
- -- check if existing. exit early if already present
- local s = structmap[typename]
- if s == nil then
- -- print("Creating Structure "..typename)
- s = createStructure(typename)
- structmap[typename] = s
- if makeglobal then
- structure_addToGlobalStructureList(s)
- end
- else
- if not reload==true then
- return s
- end
- -- TODO: cannot clear fields here but would like to
- end
- makeglobal = false
- return monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal)
- end
- mono_StringStruct=nil
-
- function monoform_exportStructInternal(s, caddr, recursive, static, structmap, makeglobal)
- --print("a")
- if caddr==0 or caddr==nil then return nil end
- -- print("b")
-
- local className = mono_class_getFullName(caddr)
- --print('Populating '..className)
-
- -- handle Array as separate case
- if string.sub(className,-2)=='[]' then
- local elemtype = mono_class_getArrayElementClass(caddr)
- return monoform_exportArrayStructInternal(s, caddr, elemtype, recursive, structmap, makeglobal, true)
- end
-
- local hasStatic = false
- structure_beginUpdate(s)
-
- local fields=mono_class_enumFields(caddr)
- local str -- string struct
- local childstructs = {}
- local i
- for i=1, #fields do
- hasStatic = hasStatic or fields[i].isStatic
- if fields[i].isStatic==static and not fields[i].isConst then
- local e=s.addElement()
- local ft = fields[i].monotype
- local fieldname = monoform_escapename(fields[i].name)
- if fieldname~=nil then
- e.Name=fieldname
- end
- e.Offset=fields[i].offset
- e.Vartype=monoTypeToVarType(ft)
-
- --print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
- if ft==MONO_TYPE_STRING then
- --print(string.format(" Field: %d: %d: %d: %s", e.Offset, e.Vartype, ft, fieldname))
- if mono_StringStruct==nil then
- -- print("Creating string object")
- mono_StringStruct = createStructure("String")
-
- mono_StringStruct.beginUpdate()
- local ce=mono_StringStruct.addElement()
- ce.Name="Length"
- if targetIs64Bit() then
- ce.Offset=0x10
- else
- ce.Offset=0x8
- end
- ce.Vartype=vtDword
- ce=mono_StringStruct.addElement()
- ce.Name="Value"
- if targetIs64Bit() then
- ce.Offset=0x14
- else
- ce.Offset=0xC
- end
- ce.Vartype=vtUnicodeString
- ce.Bytesize=128
- mono_StringStruct.endUpdate()
- mono_StringStruct.addToGlobalStructureList()
- end
- e.setChildStruct(mono_StringStruct)
- --[[
- elseif ft == MONO_TYPE_PTR or ft == MONO_TYPE_CLASS or ft == MONO_TYPE_BYREF
- or ft == MONO_TYPE_GENERICINST then
- --print("bla")
- local typename = monoform_escapename(fields[i].typename)
- if typename ~= nil then
- local typeval = mono_type_getClass(fields[i].field)
- --print(string.format("PTR: %X: %s", typeval, typename))
- cs = monoform_exportStruct(typeval, typename, recursive, false, structmap, makeglobal)
- if cs~=nil then e.setChildStruct(cs) end
- end
- elseif ft == MONO_TYPE_SZARRAY then
- --print("bla2")
- local typename = monoform_escapename(fields[i].typename)
- local arraytype = mono_type_getClass(fields[i].field)
- local elemtype = mono_class_getArrayElementClass(arraytype)
- --print(typename)
- --local acs = monoform_exportArrayStruct(arraytype, elemtype, typename, recursive, static, structmap, makeglobal, false)
- --if acs~=nil then e.setChildStruct(acs) end --]]
- end
-
- end
- end
- structure_endUpdate(s)
- return s
- end
- function monoform_exportArrayStruct(arraytype, elemtype, typename, recursive, static, structmap, makeglobal, reload)
- local acs=nil
- if typename~=nil then
- acs = structmap[typename]
- if acs==nil and arraytype~=nil then
- acs = monoform_exportStruct(arraytype, typename, recursive, false, structmap, makeglobal)
- reload = true
- end
- end
- return monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
- end
- function monoform_exportArrayStructInternal(acs, arraytype, elemtype, recursive, structmap, makeglobal, reload)
- if acs~=nil then
- cs = monoform_exportStruct(elemtype, nil, recursive, false, structmap, makeglobal)
- if cs~=nil and reload then
- structure_beginUpdate(acs)
- local ce=acs.addElement()
- ce.Name='Count'
- ce.Offset=0xC
- ce.Vartype=vtDword
- ce.setChildStruct(cs)
-
- local j
- local psize
- if targetIs64Bit() then
- psize=8
- else
- psize=4
- end
-
- for j=0, 9 do -- Arbitrarily add 10 elements
- ce=acs.addElement()
- ce.Name=string.format("Item[%d]",j)
- ce.Offset=j*psize+0x10
- ce.Vartype=vtPointer
- ce.setChildStruct(cs)
- end
- structure_endUpdate(acs)
- end
- end
- return acs
- end
- function monoAA_GETMONOSTRUCT(parameters, syntaxcheckonly)
- --called whenever an auto assembler script encounters the GETMONOSTRUCT() line
- --parameters: classname or classname,namespace:classname (or classname,classname)
- --turns into a struct define
- local c,name,classname,namespace
- c=string.find(parameters,",")
- if c==nil then
- --just find this class
- name=parameters
- classname=parameters
- namespace=''
- --print("Format 1")
- --print("name="..name)
- --print("classname="..classname)
- --print("namespace="..namespace)
- else
- --this is a name,namespace:classname notation
- print("Format 2")
- name=string.sub(parameters, 1, c-1)
- parameters=string.sub(parameters, c+1, #parameters)
- c=string.find(parameters,":")
- if (c~=nil) then
- namespace=string.sub(parameters, 1,c-1)
- classname=string.sub(parameters, c+1, #parameters)
- else
- namespace='';
- classname=parameters
- end
- --print("name="..name)
- --print("classname="..classname)
- --print("namespace="..namespace)
- end
- name=name:match "^%s*(.-)%s*$"
- classname=classname:match "^%s*(.-)%s*$"
- namespace=namespace:match "^%s*(.-)%s*$"
- local class=mono_findClass(namespace, classname)
- if (class==0) then
- return nil,"The class "..namespace..":"..classname.." could not be found"
- end
- local fields=mono_class_enumFields(class)
- if (fields==nil) or (#fields==0) then
- return nil,namespace..":"..classname.." has no fields"
- end
- local offsets={}
- local i
- for i=1, #fields do
- if fields[i].offset~=0 then
- offsets[fields[i].offset]=fields[i].name
- end
- end
- local sortedindex={}
- for c in pairs(offsets) do
- table.insert(sortedindex, c)
- end
- table.sort(sortedindex)
- local result="struct "..name.."\n"
- local fieldsize
- if #sortedindex>0 then
- fieldsize=sortedindex[1]-0;
- result=result.."vtable: resb "..fieldsize
- end
- result=result.."\n"
- for i=1, #sortedindex do
- local offset=sortedindex[i]
- local name=offsets[offset]
- result=result..name..": "
- if sortedindex[i+1]~=nil then
- fieldsize=sortedindex[i+1]-offset
- else
- --print("last one")
- fieldsize=1 --last one
- end
- result=result.." resb "..fieldsize.."\n"
- end
- result=result.."ends\n"
- --showMessage(result)
- return result
- end
- function monoAA_GETMONOSTATICDATA(assemblyname, namespace, classname, symbolprefix, enable)
- --parameters: assemblyname = partial name match of assembly
- -- namespace = namespace of class (empty string if no namespace)
- -- classname = name of class
- -- symbolprefix = name of symbol prefix (sanitized classname used if nil)
- -- returns AA script for locating static data location for given structure
- local SYMCLASSNAME
- if assemblyname==nil or namespace==nil or classname==nil then
- return ''
- end
- if symbolprefix~=nil then
- SYMCLASSNAME = symbolprefix:gsub("[^A-Za-z0-9._]", "")
- else
- SYMCLASSNAME = classname:gsub("[^A-Za-z0-9._]", "")
- end
- -- Populates ###.Static and ###.Class where ### the symbol prefix
- local script_tmpl
- if enable then
- script_tmpl = [===[
- label($SYMCLASSNAME$.threadexit)
- label(classname)
- label(namespace)
- label(assemblyname)
- label(status)
- label(domain)
- label(assembly)
- label($SYMCLASSNAME$.Static)
- label($SYMCLASSNAME$.Class)
- alloc($SYMCLASSNAME$.threadstart, 2048)
- registersymbol($SYMCLASSNAME$.Static)
- registersymbol($SYMCLASSNAME$.Class)
- $SYMCLASSNAME$.threadstart:
- mov [$SYMCLASSNAME$.Class],0
- mov [$SYMCLASSNAME$.Static],0
- call mono.mono_get_root_domain
- cmp eax,0
- je $SYMCLASSNAME$.threadexit
- mov [domain],eax
- push [domain]
- call mono.mono_thread_attach
- add esp,4
- push status
- push assemblyname
- call mono.mono_assembly_load_with_partial_name
- add esp,8
- cmp eax,0
- je $SYMCLASSNAME$.threadexit
- push eax
- call mono.mono_assembly_get_image
- add esp,4
- cmp eax,0
- je $SYMCLASSNAME$.threadexit
- mov [assembly], eax
- push classname
- push namespace
- push eax
- call mono.mono_class_from_name_case
- add esp,C
- cmp eax,0
- je $SYMCLASSNAME$.threadexit
- mov [$SYMCLASSNAME$.Class],eax
- push eax
- push [domain]
- call mono.mono_class_vtable
- add esp,8
- cmp eax,0
- je $SYMCLASSNAME$.threadexit
- push eax
- call mono.mono_vtable_get_static_field_data
- add esp,4
- mov [$SYMCLASSNAME$.Static],eax
- jmp $SYMCLASSNAME$.threadexit
- ///////////////////////////////////////////////////////
- // Data section
- $SYMCLASSNAME$.Static:
- dd 0
- $SYMCLASSNAME$.Class:
- dd 0
- assemblyname:
- db '$ASSEMBLYNAME$',0
- namespace:
- db '$NAMESPACE$',0
- classname:
- db '$CLASSNAME$',0
- status:
- dd 0
- domain:
- dd 0
- assembly:
- dd 0
- $SYMCLASSNAME$.threadexit:
- ret
- createthread($SYMCLASSNAME$.threadstart)
- ]===]
- else
- script_tmpl = [===[
- unregistersymbol($SYMCLASSNAME$.Static)
- unregistersymbol($SYMCLASSNAME$.Class)
- dealloc($SYMCLASSNAME$.threadstart)
- ]===]
- end
- return script_tmpl
- :gsub('($CLASSNAME$)', classname)
- :gsub('($SYMCLASSNAME$)', SYMCLASSNAME)
- :gsub('($NAMESPACE$)', namespace)
- :gsub('($ASSEMBLYNAME$)', assemblyname)
- end
- function monoAA_GETMONOSTATICFIELDDATA(assemblyname, namespace, classname, fieldname, symbolprefix, enable)
- --parameters: assemblyname = partial name match of assembly
- -- namespace = namespace of class (empty string if no namespace)
- -- classname = name of class
- -- fieldname = name of field
- -- symbolprefix = name of symbol prefix (sanitized classname used if nil)
- -- returns AA script for locating static data location for given structure
- local SYMCLASSNAME
- if assemblyname==nil or namespace==nil or classname==nil or fieldname==nil then
- return ''
- end
- if symbolprefix~=nil then
- SYMCLASSNAME = symbolprefix:gsub("[^A-Za-z0-9._]", "")
- else
- SYMCLASSNAME = classname:gsub("[^A-Za-z0-9._]", "")
- end
- local SYMFIELDNAME = fieldname:gsub("[^A-Za-z0-9._]", "")
-
- -- Populates ###.Static and ###.Class where ### the symbol prefix
- local script_tmpl
- if enable then
- script_tmpl = [===[
- label(classname)
- label(namespace)
- label(assemblyname)
- label(fieldname)
- label(status)
- label(domain)
- label(assembly)
- label(field)
- label($SYMCLASSNAME$.$SYMFIELDNAME$)
- label($SYMCLASSNAME$.$SYMFIELDNAME$.threadexit)
- alloc($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart, 2048)
- registersymbol($SYMCLASSNAME$.$SYMFIELDNAME$)
- $SYMCLASSNAME$.$SYMFIELDNAME$.threadstart:
- mov [$SYMCLASSNAME$.$SYMFIELDNAME$],0
- call mono.mono_get_root_domain
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- mov [domain],eax
- push [domain]
- call mono.mono_thread_attach
- add esp,4
- push status
- push assemblyname
- call mono.mono_assembly_load_with_partial_name
- add esp,8
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- push eax
- call mono.mono_assembly_get_image
- add esp,4
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- mov [assembly], eax
- push classname
- push namespace
- push eax
- call mono.mono_class_from_name_case
- add esp,C
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- push fieldname
- push eax
- call mono.mono_class_get_field_from_name
- add esp,8
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- mov [field], eax
- push eax
- call mono.mono_field_get_parent
- add esp,4
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- push eax
- push [domain]
- call mono.mono_class_vtable
- add esp,8
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- push eax
- call mono.mono_vtable_get_static_field_data
- add esp,4
- cmp eax,0
- je $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- push eax // save data on stack
- push [field]
- call mono.mono_field_get_offset
- add esp,4
- pop ebx // restore data
- add eax,ebx
- mov [$SYMCLASSNAME$.$SYMFIELDNAME$],eax
- jmp $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit
- ///////////////////////////////////////////////////////
- // Data section
- $SYMCLASSNAME$.$SYMFIELDNAME$:
- dd 0
- assemblyname:
- db '$ASSEMBLYNAME$',0
- namespace:
- db '$NAMESPACE$',0
- classname:
- db '$CLASSNAME$',0
- fieldname:
- db '$FIELDNAME$',0
- status:
- dd 0
- domain:
- dd 0
- assembly:
- dd 0
- field:
- dd 0
- $SYMCLASSNAME$.$SYMFIELDNAME$.threadexit:
- ret
- createthread($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart)
- ]===]
- else
- script_tmpl = [===[
- unregistersymbol($SYMCLASSNAME$.$SYMFIELDNAME$)
- dealloc($SYMCLASSNAME$.$SYMFIELDNAME$.threadstart)
- ]===]
- end
- return script_tmpl
- :gsub('($CLASSNAME$)', classname)
- :gsub('($SYMCLASSNAME$)', SYMCLASSNAME)
- :gsub('($FIELDNAME$)', fieldname)
- :gsub('($SYMFIELDNAME$)', SYMFIELDNAME)
- :gsub('($NAMESPACE$)', namespace)
- :gsub('($ASSEMBLYNAME$)', assemblyname)
- end
- function mono_initialize()
- --register a function to be called when a process is opened
- if (mono_init1==nil) then
- mono_init1=true
- mono_oldOnOpenProcess=onOpenProcess
- onOpenProcess=mono_OpenProcess
- registerAutoAssemblerCommand("USEMONO", monoAA_USEMONO)
- registerAutoAssemblerCommand("FINDMONOMETHOD", monoAA_FINDMONOMETHOD)
- registerAutoAssemblerCommand("GETMONOSTRUCT", monoAA_GETMONOSTRUCT)
- end
- end
- mono_initialize()
|