| 1 | + | local memapi={}local function deepcopy(a)local b=type(a)local c;if b=='table'then c={}for d,e in next,a,nil do c[deepcopy(d)]=deepcopy(e)end;setmetatable(c,deepcopy(getmetatable(a)))else c=a end;return c end memapi.convertToHexString=function(n,d)if d<1 or d>16 then error("Number of hexadecimal digits in the resulting string has to be in range [1; 16]") return end if _VERSION:match("5.2")~=nil then local m = load[[return function(d) return(1<<(d*4))-1 end]]()(d)local f="%0"..d.."X"return load[[return function(f,n,m)return string.format(f,n&m)end]]()(f, n, m)else local m=(1<<(d * 4))-1 local f="%0"..d.."X"return string.format(f,n&m)end end memapi.get_libbase=function(l)local a=gg.getRangesList("*"..l.."*.so")local x={}for k,v in pairs(a)do if v.state=='Xa'then table.insert(x,v)end end if #x==1 then local r={}r.base_offset = x[1].start r.end_offset = x[1]["end"] r.base_libname = x[1].name return r elseif #x>1 then return -1 else return nil end end memapi.__attach=function(self)local a=memapi.get_libbase(self.user_libname)if type(a)=="table"then self.is_hooked=true;self.base_offset=a.base_offset;self.end_offset=a.end_offset;self.libname=a.base_libname;return true elseif a==-1 then gg.alert("[memAPI] Found more then one library with this string, try to specify more precise")return false else return false end end memapi.__arch=function(self,...)local a={...}if#a==1 then if a[1]=="x32"or a[1]=="32"or a[1]=="armv7"then return not self.target_info.x64 elseif a[1]=="x64"or a[1]=='64'or a[1]=="armv8"then return self.target_info.x64 end else if self.target_info.x64 then return"x64"else return"x32"end end end memapi.__read=function(self,a,b)local c=os.clock()local d;if type(a)=="string"then d=self.base_offset+tonumber(tostring(a),16)elseif type(a)=="number"then d=self.base_offset+a end;local e={}local f=""for g=1,b do e[g]={}e[g].address=string.format("0x%X",tostring(d+g-1))e[g].flags=gg.TYPE_BYTE end;local h=gg.getValues(e)for i,j in pairs(h)do f=f..memapi.convertToHexString(j["value"],2)end;if self.debug then print(string.format("[memAPI] Read %d bytes from 0x%X in %f s",b,d,os.clock()-c))end;return f end memapi.__push=function(self,...)local a=os.clock()local b={...}if#self.write_buffer<1 then return end;if#self.op_buffer>10 then table.remove(self.op_buffer,1)end;local c={}for d,e in pairs(self.write_buffer)do if self.rollbacking then table.insert(c,gg.getValues(e))end;gg.setValues(e)end;if self.rollbacking then table.insert(self.op_buffer,c)end;if self.debug then print(string.format("[memAPI] Pushed %d operations in %f s",#self.write_buffer,os.clock()-a))end;self.write_buffer={}end memapi.__rollback=function(self)if self.rollbacking then local a=os.clock()local b=self.op_buffer[#self.op_buffer]for c,d in pairs(b)do gg.setValues(d)end;table.remove(self.op_buffer,#self.op_buffer)if self.debug then print(string.format("[memAPI] Rollbacked %d operations in %f s",#b,os.clock()-a))end else error("Rollbacking not enabled. Use ``hook.rollbacking = true``")return end end memapi.__write32=function(self,a,b)local c=os.clock()local d=memapi.__bytesToTable32(b,a)if d~=false then table.insert(self.write_buffer,d)if self.debug then print(string.format("[memAPI] __write32() %d bytes in %f s",#d,os.clock()-c))end;return true else return false end end memapi.__write64=function(self,a,b)local c=os.clock()local d=memapi.__bytesToTable64(b,a)if d~=false then table.insert(self.write_buffer,d)if self.debug then print(string.format("[memAPI] __write64() %d bytes in %f s",#d,os.clock()-c))end;return true else return false end end memapi.__write=function(self,a,...)local b=os.clock()local c={...}local d;if type(a)=="string"then d=self.base_offset+tonumber(tostring(a):gsub("0x",""),16)elseif type(a)=="number"then d=self.base_offset+a else error("[memAPI] Invalid offset type (string or number expected)")return end;if#c==1 then if self.is_hooked then if self:arch("x32")then self:__write32(d,c[1])else self:__write64(d,c[1])end else gg.alert("[memAPI] You have to attach to library first")end elseif#c>1 then if self.is_hooked then if self:arch("x32")then local e=0;for f=1,#c do self:__write32(d+e,c[f])e=e+memapi.byteslenght(c[f])end else local e=0;for f=1,#c do self:__write64(d+e,c[f])e=e+memapi.byteslenght(c[f])end end else gg.alert("[memAPI] You have to attach to library first")end end;if self.debug then print(string.format("[memAPI] __write %d ops in %f s",#c,os.clock()-b))end end memapi.__disasm32=function(a,b)local c=gg.disasm(gg.ASM_THUMB,a,b)local d=gg.disasm(gg.ASM_ARM,a,b)local e={}e.thumb=c;e.arm=d;return e end memapi.__disasm64=function(a,b)local c=gg.disasm(gg.ASM_THUMB,a,b)local d=gg.disasm(gg.ASM_ARM64,a,b)local e={}e.thumb=c;e.arm=d;return e end memapi.disasm=function(a,b,c)if type(c)=="string"then c=string.gsub(c,"%s+","")c=string.gsub(c," ","")c=string.gsub(c,"0x","")c=string.gsub(c,"0X","")if#c%8~=0 then gg.alert("4 bytes opcode size required!")end;c=tonumber(c,16)c=string.unpack('>I4',string.pack('<I4',c))end;if b==nil then b=0x0 end;if a=="x32"then return memapi.__disasm32(b,c)else return memapi.__disasm64(b,c)end end memapi.asm=function(a,b)if b==nil then b=0x0 end;local c=a;local d=gg.getRangesList('libc.so')for e,f in ipairs(d)do if f.type:sub(2,2)=='w'then d={{address=f.start,flags=gg.TYPE_DWORD}}end end;if not d[1].address then gg.alert('Failed to get addr (memapi.asm issues)\n'..tostring(d))do return end end;do local d=tonumber(b,16)if d then d=d&0xFFFFFFFF;c=c:gsub('( 0[xX](%x+))',function(g,h)local i=tonumber(h,16)if not i then return g end;i=i&0xFFFFFFFF;i=i-d;local j='+'if i<0 then i=-i;j='-'end;return string.format(' %s0x%X',j,i)end)end end;local k=gg.getValues(d)d[1].value='~A '..c;local l,m=pcall(gg.setValues,d)local n;if not l then m=m:gsub("^.* '1': ",''):gsub('\nlevel = 1.*$','')error("-----------------------\n[memAPI] Error: \n"..tostring(m).."\n-----------------------\n")n='ERR!'else n=gg.getValues(d)n=n[1].value&0xFFFFFFFF;gg.setValues(k)n=string.unpack('>I4',string.pack('<I4',n))n=string.format('%08X',n)return n end end memapi.__formatpatch=function(a)local b=""if type(a)=="string"then if a=="nop"then return"00F020E3"else local c=a:gsub("[h]","")c=c:gsub("%s+","")if string.match(c,"^[0-9A-Fa-f]+$")then a=a:gsub("[h]","")a=a:gsub("%s+","")if string.len(a)%2~=0 then a=a.."0"end;local d=1;for e=1,string.len(a)/2 do b=b..string.sub(a,d,d+1)d=d+2 end else local f=memapi.asm(a)if f==nil then return false else for e=1,#f/2 do b=b..string.sub(f,(e-1)*2+1,(e-1)*2+2)end end end end elseif type(a)=="boolean"then if a then b="h01"else b="h00"end;b=b.."00A0E31EFF2FE1"elseif type(a)=="number"then if a>=0 then if a>=255 then b=memapi.asm("mov r0, #"..tostring(a))b=b.."1EFF2FE1"else b=memapi.convertToHexString(a,2).."00A0E31EFF2FE1"end else b=memapi.asm("mov r0, #"..tostring(a))b=b.."1EFF2FE1"error("value <0, not implemented")return end end;return b end memapi.__bytesToTable64=function(a,b)local c={}if type(a)=="string"then if a=="nop"then local d="1F2003D5"for e=1,4 do c[e]={}c[e].address=b+e-1;c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(d,(e-1)*2+1,(e-1)*2+2)end else local f=a:gsub("[h]","")f=f:gsub("%s+","")if string.match(f,"^[0-9A-Fa-f]+$")then a=a:gsub("[h]","")a=a:gsub("%s+","")if string.len(a)%2~=0 then a=a.."0"end;local g=1;for e=1,string.len(a)/2 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE;local h="h"..string.sub(a,g,g+1)c[e].value=h;g=g+2 end else local i=memapi.asm(a)if i==nil then return false else for e=1,#i/2 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(i,(e-1)*2+1,(e-1)*2+2)end end end end elseif type(a)=="boolean"then local i;if a then i="200080D2"else i="000080D2"end;i=i.."C0035FD6"for e=1,8 do c[e]={}c[e].address=b+e-1;c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(i,(e-1)*2+1,(e-1)*2+2)end elseif type(a)=="number"then local i;i=memapi.asm("mov x0, #"..tostring(a))i=i.."C0035FD6"for e=1,8 do c[e]={}c[e].address=b+e-1;c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(i,(e-1)*2+1,(e-1)*2+2)end end;if#c>0 then return c else return false end end memapi.__bytesToTable32=function(a,b)local c={}if type(a)=="string"then if a=="nop"then local d="00F020E3"for e=1,4 do c[e]={}c[e].address=b+e-1;c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(d,(e-1)*2+1,(e-1)*2+2)end else local f=a:gsub("[h]","")f=f:gsub("%s+","")if string.match(f,"^[0-9A-Fa-f]+$")then a=a:gsub("[h]","")a=a:gsub("%s+","")if string.len(a)%2~=0 then a=a.."0"end;local g=1;for e=1,string.len(a)/2 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE;local h="h"..string.sub(a,g,g+1)c[e].value=h;g=g+2 end else local i=memapi.asm(a)if i==nil then return false else for e=1,#i/2 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE;c[e].value="h"..string.sub(i,(e-1)*2+1,(e-1)*2+2)end end end end elseif type(a)=="boolean"then for e=1,8 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE end;if a then c[1].value="h01"else c[1].value="h00"end;c[2].value="h00"c[3].value="hA0"c[4].value="hE3"c[5].value="h1E"c[6].value="hFF"c[7].value="h2F"c[8].value="hE1"elseif type(a)=="number"then for e=1,8 do c[e]={}c[e].address=string.format("0x%X",tostring(b+e-1))c[e].flags=gg.TYPE_BYTE end;if a>=0 then c[1].value="h"..memapi.convertToHexString(a,2)else c[1].value="h"..memapi.convertToHexString(a,2)end;c[2].value="h00"c[3].value="hA0"c[4].value="hE3"c[5].value="h1E"c[6].value="hFF"c[7].value="h2F"c[8].value="hE1"end;if#c>0 then return c else return false end end memapi.byteslenght=function(a)if type(a)=="string"then if a=="nop"then return 4 else local b=a:gsub("[h]","")b=b:gsub("%s+","")if string.match(b,"^[0-9A-Fa-f]+$")then a=a:gsub("[h]","")a=a:gsub("%s+","")if string.len(a)%2~=0 then a=a.."0"end;return string.len(a)/2 else local c=memapi.asm(a)if c==nil then return false else return#c/2 end end end elseif type(a)=="boolean"then return 8 elseif type(a)=="number"then return 8 else return false end end memapi.__switchconstr=function(a,b,c,d)local e={}if type(b)=="string"then b=tonumber(tostring(b):gsub("0x",""),16)elseif type(b)=="number"then else error("[memAPI] Invalid offset type (string or number expected)")return end;e.hook=deepcopy(a)e.hook.op_buffer={}e.hook.write_buffer={}e.hook.rollbacking=false;e.offset=b;e.patch_to=memapi.__formatpatch(c)e.byteslenght=memapi.byteslenght(e.patch_to)local f=e.hook:read(b,e.byteslenght)if d then if e.byteslenght~=memapi.byteslenght(d)then error("Lenght of patch_to and orig_bytes not equal")return end end;if f==e.patch_to then e.state=true;if d then e.original=d else e.original="false"end else e.state=false;if d then e.original=d else e.original=f end end;e.enable=function()e.state=true;e.hook:write(e.offset,e.patch_to)e.hook:push()gg.alert("enabled")end;e.disable=function()e.state=false;e.hook:write(e.offset,e.original)e.hook:push()gg.alert("disabled")end;e.toggle=function()if e.state then e.disable()return false else e.enable()return true end end;return e end memapi.__bswitch=function(self,a,b)return memapi.__switchconstr(self,a,b,nil)end memapi.__switch=function(self,a,b,c)return memapi.__switchconstr(self,a,b,c)end memapi.__patchconstr=function(a,b,...)local c={...}if#c<1 then error("No data specified")return end;local d={}d.__hook=deepcopy(a)d.__hook.op_buffer={}d.__hook.write_buffer={}d.offset=b;d.__hook:write(b,...)d.__hook:push()local e={}e.__index=function(self,f)if f=="rollbacking"then return d.__hook.rollbacking end end;e.__newindex=function(self,f,g)if f=="rollbacking"then d.__hook.rollbacking=g else d[f]=g end end;d.rollback=function()d.__hook:rollback()end;d.patch=function(...)d.__hook:write(d.offset,...)d.__hook:push()end;d.read=function(h)return d.__hook:read(d.offset,h)end;setmetatable(d,e)return d end memapi.__patch=function(self,a,...)return memapi.__patchconstr(self,a,...)end memapi.hook=function(a)local b={}b.target_info=gg.getTargetInfo()b.user_libname=a;b.is_hooked=false;b.base_offset=nil;b.end_offset=nil;b.libname=nil;b.op_buffer={}b.write_buffer={}b.debug=false;b.rollbacking=false;b.arch=memapi.__arch;b.attach=memapi.__attach;b.read=memapi.__read;b.write=memapi.__write;b.push=memapi.__push;b.rollback=memapi.__rollback;b.__write32=memapi.__write32;b.__write64=memapi.__write64;b.asm=memapi.asm;b.disasm=memapi.disasm;b.bswitch=memapi.__bswitch;b.switch=memapi.__bswitch;b.patch=memapi.__patch;return b end return memapi |