panraven

custom_jump_call_assembler_with_trampoline.lua

Nov 22nd, 2020 (edited)
739
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --
  2. if not _cutsomJumpCall then
  3. _pidContext = _pidContext or {now=os.clock()+3; reset=os.clock()+60}
  4. function getPidContext()
  5.   local p, pid, now = _pidContext, getOpenedProcessID(), os.clock()
  6.   if now > p.reset then
  7.     p.reset = now + 60
  8.     local ps = getProcessList()
  9.     for k,v in pairs(p)do
  10.       if type(k)=='number' and (not ps[k] or ps[k]~=v[1]) then p[k] = nil end
  11.     end
  12.   end
  13.   if now > p.now and not readInteger(process)then
  14.     return {}
  15.   elseif p[pid] and now<p.now and p.pid == pid and p.process==process then
  16.     return p[pid][2]
  17.   elseif not readInteger(process) then
  18.     return {}
  19.   end
  20.   p.now, p.pid, p.process = now+3, pid, process
  21.   if not p[pid] or p[pid][1]~=process then
  22.     local px = enumModules()[1]
  23.     p[pid] = {process,{PID=pid,PROCESS=process,ExeBase=px.Address, ExeFile=px.PathToFile,ExeSize=getModuleSize(process)}}
  24.   end
  25.   return p[pid][2]
  26. end
  27. getPidContext()
  28. local EMPTY = {}
  29. local function toInt(n)return type(n)=='number'and math.tointeger(n)end
  30. function GetTrampoline(target, hint, noNewAlloc)
  31.   if not toInt(target)or not toInt(hint) then return nil end
  32.   local p = getPidContext()
  33.   p.Trampoline = p.Trampoline or {}
  34.   local t,tcnt, diff = p.Trampoline,0
  35.   for from, to in pairs(t) do
  36.     diff = from - hint
  37.     if diff>-0x7ffffffb and diff<0x80000005 then
  38.       if to==target then return from end
  39.       if to==EMPTY then
  40.         local bs, r = string.pack('I8I8',0xb8480000000225ff ,target),{}
  41.         for c in bs:gmatch'.'do r[1+#r]=c:byte()end
  42.         if writeBytes(from, r)==16 then
  43.           t[from] = target
  44.           return from
  45.         end
  46.       end
  47.     end
  48.   end
  49.   -- no previous allocation, make new one
  50.   if not noNewAlloc then
  51.     local addr = allocateMemory(0x1000,hint)
  52.     diff = addr and addr - hint
  53.     if not diff or diff<=-0x7ffffffb or diff>=0x7ffff005 then
  54.       if addr then deAlloc(addr)end
  55.       return nil,'fail allocate trampoline'
  56.     end
  57.     p.TrmpAllocCnt = not p.TrmpAllocCnt and 1 or p.TrmpAllocCnt + 1
  58.     for i=0,255 do t[addr+i*16]=EMPTY end
  59.     return GetTrampoline(target, hint, true)
  60.   end
  61. end
  62.  
  63. if _cutsomJumpCall then
  64.   _cutsomJumpCall = nil,unregisterAssembler(_cutsomJumpCall)
  65. end
  66.  
  67. _cutsomJumpCall = registerAssembler(function (addr, inst)
  68.   local force, target, isJmp, forceShort, forceNear, forceLong =
  69.     inst:match'^%s*[jJ][mM][pP]!(%a*)%s+(.-)%s*$'
  70.   if target then isJmp = true else
  71.     force, target = inst:match'^%s*[cC][aA][lL][lL]!(%a*)%s+(.-)%s*$'
  72.   end
  73.   if not target then return end
  74.  
  75.   target = target and target:len()>1 and GetAddressSafe(target)
  76.  
  77.   if target and force:len()>1 then
  78.     force=force:lower()
  79.     if force=='short' then forceShort = true-- should be redundancy?
  80.     elseif force=='near' then forceNear = true
  81.     elseif force=='long' then forceLong = true
  82.     else target = nil end -- unknown jump distance modifier, error
  83.   end
  84.  
  85.   if not target then
  86.     return --nil,'invalid :'..inst
  87.   else
  88.     local cmd = isJmp and {0xeb,0xe9,0x25ff} or {0xe8,0xe8,0x08eb0000000215ff}
  89.     local diff, r, bs = target - addr, {}
  90.     if isJmp and (forceShort or not forceNear and not forceLong) and diff>-0x7e and diff <0x82 then
  91.       bs = string.pack('Bb',cmd[1], diff-2)
  92.     elseif not targetIs64Bit() or not forceLong and diff>-0x7ffffffb and diff<0x80000005 then
  93.       bs = string.pack('Bi4',cmd[2],diff-5)
  94.     elseif not forceNear or addr<0x1000 then
  95.       if isJmp then
  96.         bs = string.pack('I6I8',cmd[3],target)
  97.       else
  98.         bs = string.pack('I8I8',cmd[3],target)
  99.       end
  100.     elseif diff<=-0x7ffffffb or diff>=0x80000005 then
  101.       local trmp, errmsg = GetTrampoline(target, addr)
  102.       if not trmp then return nil,(errmsg or '!')..', no trampoline:'..inst end
  103.       bs = string.pack('Bi4',cmd[2], trmp - addr -5)
  104.     end
  105.     if bs then
  106.       for c in bs:gmatch'.' do r[1+#r]=c:byte()end
  107.       return r
  108.     end
  109.   end
  110. end)
  111. end --- cutsomJumpCall
RAW Paste Data