Advertisement
panraven

aacomp.lua

Feb 27th, 2023 (edited)
734
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.61 KB | None | 0 0
  1. function bt2aob(bt)
  2.   local r = {}
  3.   for i=1,#bt do r[i]=string.format('%02X',bt[i])end
  4.   return table.concat(r,' ' )
  5. end
  6.  
  7.  
  8. local fmt, cat = string.format, table.concat
  9.  
  10. local loadcode = assert(load == loadstring and loadstring or load or loadstring,'no loadcode')
  11. local function pcall_ret(ok, ...)if ok then return ... else return nil,... end end
  12. local function ret_pcall(...)return pcall_ret(pcall(...))end
  13. local function eval(chunks,ctx)
  14.   local ok, r = pcall(loadcode, chunks, '_', nil, ctx or _G)
  15.   if type(r)=='function'then return ret_pcall(r)else return nil, r end
  16. end
  17. local function eval_exp(exp,ctx)return ret_pcall(eval,'return '..exp,ctx)end
  18.  
  19. local function of_int(int,...)if int then return math.tointeger(int),of_int(...)end end
  20.  
  21. local function calc_rip(Adr, ofs_rip, ofs_end, rip_size, Read_Adr)
  22.   ofs_rip, ofs_end, rip_size = of_int(ofs_rip or 4, ofs_end or 5, rip_size or 4) -- defaults
  23.   if not (ofs_rip and ofs_end and rip_size)then
  24.     return nil,'format: base ofs_rip ofs_end ?rip_size ?read_adr'
  25.   end
  26.   local adr, read_adr = getAddressSafe(Adr),getAddressSafe(Read_Adr)
  27.   if not adr then return nil, Adr..' not known' end
  28.   local read =
  29.     rip_size == 4 and function(addr)return readInteger(addr,true)end or
  30.     rip_size == 1 and function(addr)
  31.       addr = readBytes(addr)
  32.       if addr and addr>0x7f then addr = 0x100 - addr end
  33.       return addr
  34.     end
  35.   if not read then return nil,'only 1 or 4 bytes rip'end
  36.   local RIP = read_adr and read(read_adr)
  37.   RIP = not RIP and not read_adr and read(adr + ofs_rip)
  38.   if not RIP then return nil,'no RIP from '..Adr end
  39.   return RIP + adr + ofs_end
  40. end
  41. _G.calc_rip = calc_rip
  42.  
  43. local cmd = 'COMP'
  44. unregisterAutoAssemblerCommand(cmd)
  45. registerAutoAssemblerCommand(cmd,function(s,sc)
  46.   local sym, exp = s:match'^%s*([_#@%.%w]+)%s*,%s*(.-)%s*$'
  47.   if not sym then exp = s end
  48.   if not exp or exp:len()==0  then return nil,'empty expression'end
  49.   local r, errmsg = eval_exp(exp)
  50.   errmsg = not r and errmsg and tostring(errmsg) or 'unknown error'
  51.   if sym and sym:len()>0 then
  52.     if of_int(r)then
  53.       return r<0 and fmt('define(%s,-%X)',sym,-r)or fmt('define(%s,0%X)',sym,r)
  54.     elseif r then
  55.       return fmt('define(%s,%s)',sym, tostring(r))
  56.     elseif sc then
  57.       return fmt('define(%s,666)',sym)
  58.     end
  59.   elseif not sc then
  60.     return nil,'failed '..exp..' -> '..errmsg
  61.   end
  62. end)
  63.  
  64. function forget_fcomp(key)
  65.   if type(key)=='string' and type(_G.__aa_comp_result)=='table'then
  66.     _G.__aa_comp_result['&'..key] = nil
  67.   end
  68. end
  69.  
  70. local function assembled_bytes(start_addr, tmpl, ctx)
  71.   local rid = '_'..math.random(10000,99999)..'_'
  72.   local ret, prefix, post_code, subfix = {}, {}, {}
  73.   local code = string.format([[
  74.   %X:
  75.   %s
  76.   <END_BYTES>:]], start_addr, tmpl)
  77.     :gsub('(&[_#@%.%w]+)', function(name)
  78.       local r = ctx[name]
  79.       if of_int(r)then return fmt('%X',r)end
  80.      end)
  81.     :gsub('<%s*([_%a][_%w]*)%s*>',function(sym)
  82.       local rsym = rid..sym
  83.       if not ret[sym] then
  84.         local idx = 1+#ret
  85.         ret[sym], ret[idx] = idx, sym
  86.         prefix[idx] = fmt('registerSymbol(%s)',rsym)
  87.         post_code[idx] = 'un'..prefix[idx]
  88.       end
  89.       return rsym
  90.     end)
  91.     :gsub('%(%s*%%([xXdDsS])%s+([_%a][_%w]*)%s*%)',function(fms, name)
  92.       local v = ctx[name]
  93.       if v then return fmt('%'..fms,v)end
  94.     end)
  95.   code = cat({cat(prefix,'\n'), code}, '\n')
  96.   local ok = autoAssemble(code)
  97.   if ok then
  98.     for i=1,#ret do
  99.       local sym, rsym = ret[i], rid .. ret[i]
  100.       ret[sym] = getAddressSafe(rsym)
  101.     end
  102.     autoAssemble(cat(post_code,'\n'))-- unreg symbols
  103.     if ret.END_BYTES then
  104.       local len = ret.END_BYTES - start_addr
  105.       local bt = readBytes(start_addr, len, true)
  106.       return bt, len, ret
  107.     end
  108.   end
  109. end
  110.  
  111.  
  112.  
  113. if next_rip_reg_asm_id then
  114.   next_rip_reg_asm_id = nil, unregisterAssembler(next_rip_reg_asm_id)
  115. end
  116. if aa_comp_reg_asm_id then
  117.   aa_comp_reg_asm_id = nil, unregisterAssembler(aa_comp_reg_asm_id)
  118. end
  119. local regs = 'rax;rbx;rcx;rdx;rsi;rdi;rbp;r11;r12;r13;r14;r15;'
  120. aa_comp_reg_asm_id = registerAssembler(function(adr, inst)
  121.   if adr < 0x1000 then return {0x90}end
  122.   local op, ops, ctx = inst:match'^%s*([_%a][_%w]*)%s*(.-)%s*$'
  123.   if not op or ops:len()==0 then return end -- don't know what to do, let ce handle
  124.   while ops and #ops>0 and ops:match'^%b()$' do ops = ops:sub(2,-2)end
  125.   op = op:lower()
  126.   if op=='fcomp' then
  127.     local reg, exp = ops:match'^&([_#@%.%w]+)%s*,%s*(.-)%s*$'
  128.     if not reg or exp:len()==0 then return end
  129.     local r, errmsg, addr = eval_exp(exp)
  130.     if not of_int(r)then return end
  131.     if #reg==3 and regs:find(reg) or reg=='_' then
  132.       _G.one_off_reg_addr_setup = { reg = reg~='_' and reg,addr = r}
  133.     elseif not _G.__aa_comp_result or
  134.            not _G.__aa_comp_result[reg] -- don't overwrite existed, use forget_comp to refresh
  135.     then
  136.       local t = _G.__aa_comp_result
  137.       t = type(t)=='table' and t or {}
  138.       t['&'..reg] = r
  139.       _G.__aa_comp_result = t
  140.     end
  141.     return {0x90}
  142.   elseif _G.one_off_reg_addr_setup then
  143.     ctx, _G.one_off_reg_addr_setup = _G.one_off_reg_addr_setup
  144.     ctx.op, ctx.lhs, ctx.rhs = op, ops:match'^(.-%[)%s*.+%s*(%].-)$'
  145.     if _G.__aa_comp_result and ops:find'&[_#@%.%w]'then
  146.       for k,v in pairs(_G.__aa_comp_result)do if not ctx[k]then ctx[k] = v end end
  147.     end
  148.     if op=='jmp' or op=='call'then
  149.       if ops:find(ctx.reg)then
  150.         return assembled_bytes(adr, [[
  151.             mov  (%s reg),(%X addr)
  152.             (%s op)  (%s reg)
  153.           ]], ctx)
  154.       end
  155.     elseif op:match'^j' then --- format 1, should be jcc
  156.       return assembled_bytes(adr, [[
  157.         (%s op) short <__yes_path>
  158.         <no_path>:
  159.         jmp short <__done>
  160.         <__yes_path>:
  161.         jmp  (%X addr)
  162.         <__done>:
  163.       ]], ctx)
  164.     elseif ctx.lhs then -- format 2
  165.       return assembled_bytes(adr, [[
  166.         push     (%s reg)
  167.           mov    (%s reg),(%X addr)
  168.           (%s op) (%s lhs)(%s reg)(%s rhs)
  169.         pop      (%s reg)
  170.       ]], ctx)
  171.     end
  172.   elseif _G.__aa_comp_result and ops:find'&[_#@%.%w]'then
  173.     return assembled_bytes(adr, inst, _G.__aa_comp_result)
  174.   end
  175. end)
  176. ---[===[
  177.  
  178. --- may place the following in a memory record, replace 'jmp %X' properly
  179.  
  180. cnt = type(cnt)=='number'and cnt+0x111111 or 0x10000000
  181.  
  182. local code = string.format([[
  183. globalalloc(__X,$1000)
  184. __X:
  185. mov eax,%X
  186. mov rax,-1
  187.  
  188. //// lua53-64.lua_absindex+B:
  189. //// - 77 13                 - ja lua53-64.lua_absindex+20
  190.  
  191. reassemble(lua53-64.lua_absindex+B) /// ce seem do it not right, ja * -> jmp *,
  192.                                     /// but my ce version may be outdated and it already been fixed.
  193. fcomp &rax,calc_rip('lua53-64.lua_absindex+B',1,2,1)
  194. ///  if what follow & is a int register, then it is in ONE_OFF_mode,
  195. ///  the result addr only use in next instruction and forget;
  196. ///  otherwise, it is a VARIABLE <name> stored persisted,
  197. ///  next time (not just next) &<name> will be replaced
  198. reassemble(lua53-64.lua_absindex+B)
  199.  
  200. mov rax,-1
  201. fcomp &_,calc_rip('lua53-64.lua_absindex+B',1,2,1)
  202. jna 1 /// jcc in ONE_OFF_mode can have a dummy target address, result addr will replace it
  203. mov rax,-1
  204.  
  205. //// lua53-64.lua_version+5:
  206. //// - 48 8D 05 FC7B0600     - lea rax,[lua53-64.dll.rdata+9F28] /// also displace as lua53-64.dll+68F28
  207.  
  208. reassemble(lua53-64.lua_version+5)
  209. mov rax,-1
  210. fcomp &r15,calc_rip('lua53-64.lua_version+5',3,7) /// note there is 2 number following base addr,
  211.                                                   /// the 3rd rip-size default to 4 bytes
  212. reassemble(lua53-64.lua_version+5) //// ONE_OFF_mode value can use in reassemble
  213. mov rax,-1
  214. fcomp &r15,calc_rip('lua53-64.lua_version+5',3,7)
  215. mov    rbx,[rax] /// similar to jcc, anything between [*dummy] is replaced
  216. mov   rax,-1
  217. fcomp &VARNAME,calc_rip('lua53-64.lua_version+5',3,7) /// using store VARIABLE, they must be integer
  218. fcomp &B1Bytes,0x66 /// prepare to use multiple store VARIABLE
  219. fcomp &W2Bytes,0x666
  220. cmp   [rax+&W2Bytes],&B1Bytes /// multiple VARIABLE, note that if some value is 64bit, most won't compile in this case
  221. call  &VARNAME
  222. mov   rax,-1
  223. jmp   &VARNAME+&W2Bytes
  224. {
  225. call  &VARNAME
  226. mov   rax,-1
  227. jmp   &VARNAME
  228. }
  229. mov rax,-1
  230. mov rax,-1
  231. mov rax,-1
  232. ret
  233. @@:
  234. mov rax,-1
  235. mov rax,-1
  236. comp(XXXX,calc_rip('lua53-64.lua_version+5',3,7)) /// --> define(XXXX,<calc-result>)
  237. jmp XXXX
  238. mov rax,-1
  239. mov rax,-1
  240. //
  241. ]], cnt)
  242.  
  243. autoAssembleCheck(code)
  244. autoAssemble(code)
  245. --[[  edited output
  246. __X:
  247. 07CF0000- mov eax,10333333
  248. 07CF0005- mov rax,FFFFFFFFFFFFFFFF
  249. 07CF000F- nop
  250. 07CF0010- nop
  251. 07CF0011- jmp lua53-64.lua_absindex+20
  252. 07CF001F- nop
  253. 07CF0020- ja 07CF0024
  254. 07CF0022- jmp 07CF0032
  255. 07CF0024- jmp lua53-64.lua_absindex+20
  256. 07CF0032- mov rax,FFFFFFFFFFFFFFFF
  257. 07CF003C- nop
  258. 07CF003D- jna 07CF0041
  259. 07CF003F- jmp 07CF004F
  260. 07CF0041- jmp lua53-64.lua_absindex+20
  261. 07CF004F- mov rax,FFFFFFFFFFFFFFFF
  262. 07CF0059- mov rax,lua53-64.dll.rdata+9F28
  263. 07CF0063- mov rax,FFFFFFFFFFFFFFFF
  264. 07CF006D- nop
  265. 07CF006E- mov rax,lua53-64.dll.rdata+9F28
  266. 07CF0078- mov rax,FFFFFFFFFFFFFFFF
  267. 07CF0082- nop
  268. 07CF0083- push r15
  269. 07CF0085- mov r15,lua53-64.dll.rdata+9F28
  270. 07CF008F- mov rbx,[r15]
  271. 07CF0092- pop r15
  272. 07CF0094- mov rax,FFFFFFFFFFFFFFFF
  273. 07CF009E- nop
  274. 07CF009F- nop
  275. 07CF00A0- nop
  276. 07CF00A1- cmp dword ptr [rax+00000666],66
  277. 07CF00A8- call lua53-64.dll.rdata+9F28
  278. 07CF00B8- mov rax,FFFFFFFFFFFFFFFF
  279. 07CF00C2- jmp lua53-64.dll.rdata+A58E
  280. 07CF00D0- mov rax,FFFFFFFFFFFFFFFF
  281. 07CF00DA- mov rax,FFFFFFFFFFFFFFFF
  282. 07CF00E4- mov rax,FFFFFFFFFFFFFFFF
  283. 07CF00EE- ret
  284. 07CF00EF- mov rax,FFFFFFFFFFFFFFFF
  285. 07CF00F9- mov rax,FFFFFFFFFFFFFFFF
  286. 07CF0103- jmp lua53-64.dll.rdata+9F28
  287. 07CF0111- mov rax,FFFFFFFFFFFFFFFF
  288. 07CF011B- mov rax,FFFFFFFFFFFFFFFF
  289. --]]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement