local IMAGE_SCN_CNT_CODE=0x20 local IMAGE_SCN_MEM_EXECUTE=0x20000000 if compareMemory==nil then --6.8.4 has compareMemory, but for now implement this myself (slow as fuck) compareMemory=function(a1,a2,size,method) if size==0 then error('Provide a size>0') end if method~=1 then error('this version of compareMemory does not do other methods besides 1 (target/local)') end local b1=readBytes(a1,size,true) local b2=readBytesLocal(a2,size,true) local i for i=1,size do if b1[i]~=b2[i] then return false,i-1 end end return true end end function scanModuleForPatches(modulepath, loadedModuleBase) local original=createMemoryStream() original.loadFromFile(modulepath) original.Position=0 if (byteTableToString(original.read(2))~='MZ') then original.destroy() error('Not a valid executable') end original.Position=60; local lfanew=original.readDword(); original.Position=lfanew; if (byteTableToString(original.read(2))~='PE') then original.destroy() error('Not a valid windows executable') end original.position=original.Position+2 local Machine=original.readWord() local SectionCount=original.readWord() original.Position=original.Position+12 local OptHeaderSize=original.readWord() original.position=original.Position+2 local OptHeaderStart=original.Position local Magic=original.readWord() local MajorLinkerVersion=original.readByte() local MinorLinkerVersion=original.readByte() local SizeOfCode=original.readDword() original.Position=original.Position+8 local EntryPoint=original.readDword() local BaseOfCode=original.readDword() local BaseOfData local ImageBase --scan the reloc table if Machine==0x8664 then BaseOfData=nil ImageBase=original.readQword() original.Position=original.Position+4+4+2+2+2+2+2+2+4+4+4+4+2+2+8+8+8+8 else BaseOfData=original.readDword() ImageBase=original.readDword() original.Position=original.Position+4+4+2+2+2+2+2+2+4+4+4+4+2+2+4+4+4+4 end local RelocDistance=loadedModuleBase-ImageBase; local LoaderFlags=original.readDword() local RVACount=original.readDword() if RVACount~=16 then original.destroy() error('This type of module is currently not supported') end --DataDirectory follows local DataDirPosition=original.Position local ImageSectionHeaderPosition=OptHeaderStart+OptHeaderSize --parse the sections so VirtualToFile can function local sections={} original.Position=ImageSectionHeaderPosition local i for i=1,SectionCount do sections[i]={} sections[i].name=byteTableToString(original.read(8)) sections[i].misc=original.readDword() sections[i].virtualAddress=original.readDword() sections[i].sizeOfRawData=original.readDword() sections[i].PointerToRawData=original.readDword() original.position=original.position+12; sections[i].Characteristics=original.readDword() sections[i].Executable=sections[i].Characteristics & IMAGE_SCN_CNT_CODE == IMAGE_SCN_CNT_CODE end local function VirtualToFile(VA) --scan the address in the sections list local i local offset for i=1,#sections do if (VA>=sections[i].virtualAddress) and (VA> 12 local VA=VABase+(relinfo & 0xfff); if (reltype == 3) then writeIntegerLocal(original.Memory+VirtualToFile(VA),readIntegerLocal(original.Memory+VirtualToFile(VA)+RelocDistance)) else if (reltype == 10) then writeQwordLocal(original.Memory+VirtualToFile(VA),readQwordLocal(original.Memory+VirtualToFile(VA)+RelocDistance)) else if reltype ~= 0 then relocs[VA]=true --just mark it as a "I don't know" end end end end oldpos=oldpos+Size until original.Position>=RelocationTablePosition+RelocationTableSize else end local imports={} if ImportTablePosition then original.Position=ImportTablePosition repeat i=#imports+1 imports[i]={} imports[i].ImportLookupTable=VirtualToFile(original.readDword()) imports[i].TimeDate=original.readDword() imports[i].ForwarderChain=original.readDword() imports[i].NamePosition=VirtualToFile(original.readDword()) imports[i].ImportAddressTable=VirtualToFile(original.readDword()) if imports[i].ImportLookupTable==nil then imports[i]=nil end until original.Position>=ImportTablePosition+ImportTableSize for i=1,#imports do local reader if Machine==0x8664 then reader=original.readQword else reader=original.readDword end original.Position=imports[i].ImportAddressTable while original.Position0 then scanModuleForPatches(l[i].PathToFile, l[i].Address) end end local mv=getMemoryViewForm() local mi=createMenuItem(mv.Menu) mi.Caption='Scan for patches' mi.Shortcut='Ctrl+Shift+P' mi.OnClick=startPatchScan mv.Extra1.insert(mv.DissectPEheaders1.MenuIndex+1, mi)