local function findExecutableSegment(lib) local ranges=gg.getRangesList(lib) for _,v in ipairs(ranges) do if v.type:find("-x") then return v.start end end return nil end local function readValue(address,flags) return gg.getValues({[1]={address=address,flags=flags}})[1].value end local function writeValue(address,flags,value,freeze) local item={address=address,flags=flags,value=value,freeze=freeze} if freeze then gg.addListItems({item}) else gg.setValues({item}) end end function setvalue(address,flags,value,freeze) if address == 0 then return end local tt={} tt[1]={} tt[1].address=address tt[1].flags=flags tt[1].value=value tt[1].freeze=freeze if freeze==false then gg.setValues(tt) end gg.addListItems(tt) end function getvalue(address,flags,value,freeze) if address == 0 then return end local tt={} tt[1]={} tt[1].address=address tt[1].flags=flags gg.addListItems(tt) end function autovalue(address,flags,_o,_v,freeze) if address == 0 then return end local tt={} tt[1]={} tt[1].address=address tt[1].flags=flags tt[1].freeze=freeze local _v_ = gg.getValues(tt)[1].value if math.abs(_v_-_o) < 1e-7 then tt[1].value=_v else tt[1].value=_o end if freeze==false then gg.setValues(tt) end gg.addListItems(tt) end function readD(address) return gg.getValues({{address = address, flags = 4}})[1].value end function S_Pointer(t_So, t_Offset, _bit) local function getRanges() local ranges = {} local t = gg.getRangesList('^/data/*.so*$') for i, v in pairs(t) do if v.type:sub(2, 2) == 'w' then table.insert(ranges, v) end end return ranges end local function Get_Address(N_So, Offset, ti_bit) local ti = gg.getTargetInfo() local t = {} local _t local _S = nil if ti_bit then _t = 32 else _t = 4 end local _S = gg.getRangesList(N_So[1])[1] if _S then t[#t + 1] = {} t[#t].address = _S.start + Offset[1] t[#t].flags = _t if #Offset ~= 1 then for i = 2, #Offset do local S = gg.getValues(t) t = {} for _ in pairs(S) do if not ti.x64 then S[_].value = S[_].value & 0xFFFFFFFF else S[_].value = S[_].value & 0xFFFFFFFFFF end t[#t + 1] = {} t[#t].address = S[_].value + Offset[i] t[#t].flags = _t end end end _S = t[#t].address end return _S end local ttt = Get_Address(t_So, t_Offset, _bit) if ttt ~= nil then local _A = string.format('0x%X', ttt) return _A end return 0 end function RDI(address) return gg.getValues({{address = address, flags = 4}})[1].value & 0xFFFFFFFF end function RQI(address) return gg.getValues({{address = address, flags = gg.TYPE_QWORD}})[1].value end function Format(tab, format, value, type, Function) if format == "查看" then tab[1]["flags"] = type return print(gg.getValues(tab)) elseif format == "修改" then tab[1]["flags"] = type tab[1]["value"] = value return gg.setValues(tab) elseif format == "冻结" then tab[1]["flags"] = type tab[1]["freeze"] = true tab[1]["value"] = value tab[1]["name"] = Function or "功能" return gg.addListItems(tab) elseif format == "加载" then tab[1]["flags"] = type return gg.loadResults(tab) end end function LSQ_Chain(so, offset, format, value, type, Function)--模块设置, 偏移量, 功能参数, 修改值, 类型, 功能 getRanges = getRanges or (function() local ranges = {} local t = gg.getRangesList('^/data/*.so*$') for i, v in pairs(t) do if v["type"]:sub(2, 2) == 'w' then--判断so是否可读可写 ranges[#ranges+1] = v end end return ranges end) local rest, ranges, sostart, valtype = {}, getRanges(), nil , gg.TYPE_DWORD if gg.getTargetInfo()["x64"] then--判断应用程序是否为64位 valtype = gg.TYPE_QWORD end for i in pairs(ranges) do local _name = ranges[i]["internalName"]:gsub('^.*/', '') if so[1] == _name and so[2] == ranges[i]["state"] then sostart = ranges[i]["start"] break end end if sostart then if offset[1] then for i = 1, #offset do rest = {{flags = valtype,address = sostart + offset[i]}} rest = gg.getValues(rest) if i == #offset then break end if valtype == gg.TYPE_DWORD then sostart = rest[1].value & 0xFFFFFFFF--对值进行补位操作 else sostart = rest[1].value end end end if #rest == 1 then end return Format(rest, format, value, type, Function) end gg.toast("功能:" .. Function .. "开启失败") print("功能开启失败原因: 未找到基址头") return os.exit() end -- 读取内存地址的函数 function readPointer(name, offset, i) local re = gg.getRangesList(name) local x64 = gg.getTargetInfo().x64 local va = {[true]=32, [false]=4} if re[i or 1] then local addr = re[i or 1].start + offset[1] for i = 2, #offset do addr = gg.getValues({{address=addr, flags=va[x64]}}) if not x64 then addr[1].value = addr[1].value & 0xFFFFFFFF end addr = addr[1].value + offset[i] end return addr end end -- 修改内存地址的函数 function gg.edits(addr, Table, name) local Table1 = {{}, {}} for k, v in ipairs(Table) do local value = {address = addr+v[3], value = v[1], flags = v[2], freeze = v[4]} if v[4] then Table1[2][#Table1[2]+1] = value else Table1[1][#Table1[1]+1] = value end end gg.addListItems(Table1[2]) gg.setValues(Table1[1]) gg.toast((name or "") .. "开启成功, 共修改"..#Table.."个值") end function readPointer(name, offset, i) local re = gg.getRangesList(name) local x64 = gg.getTargetInfo().x64 local va = { [true] = 32, [false] = 4 } if re[i or 1] then local addr = re[i or 1].start + offset[1] for i = 2, #offset do addr = gg.getValues({ { address = addr, flags = va[x64] } }) if not x64 then addr[1].value = addr[1].value & 0xFFFFFFFF else addr[1].value = addr[1].value & 0xFFFFFFFFFF end addr = addr[1].value + offset[i] end return addr end end -- nullptr local t = {"libtprt.so"} local tt = {0xE057C} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- tprt 代码段完整性校验入口 直接返回 放行被修改的 text 段 local tt = {0x11CA3C} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 NOP", false) -- 跳过 tprt 完整性校验的关键判断指令 local tt = {0x11D028} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- tprt CRC 校验函数 直接返回 不比对 local tt = {0x11D080} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- tprt CRC 校验第二路径 直接返回 local tt = {0x1226EC} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 屏蔽因修改 tprt 触发的闪退分支 local tt = {0x122A4C} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 屏蔽对局中因修改 tprt 触发的闪退分支 -- ===== libtersafe.so 第一批 10 处 全部 RET 放行完整性校验 ===== local t = {"libtersafe.so"} local tt = {0x1D2AB8} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x1DE5A8} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x23B8D0} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x24BE80} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x251064} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x251324} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x4BDBE8} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x4E62AC} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x4EC35C} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 local tt = {0x503A24} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 -- ===== libtersafe.so 第二批 2 处 RET ===== local tt = {0x251324} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 与第一批同偏移 再写一次 RET local tt = {0x4D2848} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 RET", false) -- 完整性校验点 直接返回 不检测 -- ===== libtersafe.so 第三批 1 处 还原为正常取字节读取 ===== local tt = {0x4E0770} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 LDRB W8, [X0]", false) -- 还原正常取字节 让字节扫描循环走正常路径 对应原值 943719432 即 0x38400408 -- ===== libtersafe.so 第四批 1 处 NOP ===== local tt = {0x2103F0} local ttt = S_Pointer(t, tt, true) setvalue(ttt, 4, "~A8 NOP", false) -- 跳过一条校验判断 放行