AbhiModszYT

DexDump-Tools

Aug 25th, 2024
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.11 KB | Gaming | 0 0
  1. gg.alert("Welcome To Dex Dump Script\nScript By : AbhiModszYT\nTelegram Channel : @AMBOTYT\nScript Version : 1.1\nScript Dump Also 360 Protection")
  2.  
  3. local dumpDex = {}
  4.  
  5. function dumpDex:getTargetPackage()
  6.     return gg.getTargetPackage()
  7. end
  8.  
  9. function dumpDex:getPackageName()
  10.     return self.targetPackage
  11. end
  12.  
  13. function dumpDex:setPackageName(targetPackage)
  14.     self.targetPackage = targetPackage
  15. end
  16.  
  17. function dumpDex:getRootDir()
  18.     return string.format('%s/dumpDex', gg.EXT_STORAGE)
  19. end
  20.  
  21. function dumpDex:getDumpDir()
  22.     return string.format('%s/%s', self:getRootDir(), self:getPackageName())
  23. end
  24.  
  25. function dumpDex:getRangeMap()
  26.     local rangeMap = self.rangeMap
  27.     if rangeMap then
  28.         return rangeMap
  29.     end
  30.  
  31.     rangeMap = {
  32.         Jh = gg.REGION_JAVA_HEAP,
  33.         Ch = gg.REGION_C_HEAP,
  34.         Ca = gg.REGION_C_ALLOC,
  35.         Cd = gg.REGION_C_DATA,
  36.         Cb = gg.REGION_C_BSS,
  37.         PS = gg.REGION_PPSSPP,
  38.         A = gg.REGION_ANONYMOUS,
  39.         J = gg.REGION_JAVA,
  40.         S = gg.REGION_STACK,
  41.         As = gg.REGION_ASHMEM,
  42.         V = gg.REGION_VIDEO,
  43.         O = gg.REGION_OTHER,
  44.         B = gg.REGION_BAD,
  45.         Xa = gg.REGION_CODE_APP,
  46.         Xs = gg.REGION_CODE_SYS
  47.     }
  48.     self.rangeMap = rangeMap
  49.     return rangeMap
  50. end
  51.  
  52. function dumpDex:getRangeText()
  53.     local rangeMap = self:getRangeMap()
  54.     local rangeValue = gg.getRanges()
  55.     local ranges = {}
  56.  
  57.     for k, v in pairs(rangeMap) do
  58.         if (rangeValue & v) == v then
  59.             ranges[#ranges + 1] = k
  60.             rangeValue = rangeValue & ~v
  61.         end
  62.     end
  63.  
  64.     return table.concat(ranges, ' | ')
  65. end
  66.  
  67. function dumpDex:getRangeNames()
  68.     local map = self:getRangeMap()
  69.     local list = {}
  70.     for k, v in pairs(map) do
  71.         list[#list + 1] = k
  72.     end
  73.     return list
  74. end
  75.  
  76. function dumpDex:selectRange()
  77.     local names = self:getRangeNames()
  78.     local selection = {}
  79.     local rangeMsg = self:getRangeText()
  80.  
  81.     local curRangName = {}
  82.     for name in string.gmatch(rangeMsg, '%w+') do
  83.         curRangName[name] = true
  84.     end
  85.  
  86.     for i, name in ipairs(names) do
  87.         selection[i] = (curRangName[name] == true)
  88.     end
  89.  
  90.     local inputs = gg.multiChoice(names, selection, string.format('Current selection:%s', rangeMsg))
  91.     if not inputs then
  92.         return
  93.     end
  94.  
  95.     local map = self:getRangeMap()
  96.     local rangeValue = 0
  97.     for i, v in pairs(inputs) do
  98.         if v then
  99.             local name = names[i]
  100.             rangeValue = rangeValue | map[name]
  101.         end
  102.     end
  103.  
  104.     gg.setRanges(rangeValue)
  105. end
  106.  
  107. function dumpDex:stringToHex(s)
  108.     return (string.gsub(s, '.', function(s)
  109.         return string.format('%02x', string.byte(s))
  110.     end))
  111. end
  112.  
  113. function dumpDex:getDexHeader()
  114.     return 'dex\x0A035\x00'
  115. end
  116.  
  117. function dumpDex:getResultsStep()
  118.     return #self:getDexHeader()
  119. end
  120.  
  121. function dumpDex:newDex(address)
  122.     local dex = {}
  123.     setmetatable(dex, {
  124.         __index = self
  125.     })
  126.  
  127.     function dex:getAddress()
  128.         return address
  129.     end
  130.  
  131.     function dex:getName()
  132.         local dexName
  133.         local index = self.index
  134.         if type(index) ~= 'number' then
  135.             error('need dex.index = number', 2)
  136.         end
  137.         if index == 1 then
  138.             dexName = 'classes.dex'
  139.         else
  140.             dexName = string.format('classes%d.dex', index)
  141.         end
  142.         return dexName
  143.     end
  144.  
  145.     function dex:getRangesInfo()
  146.         local rangesInfo = self.rangesInfo
  147.         if rangesInfo then
  148.             return rangesInfo
  149.         end
  150.  
  151.         local address = self:getAddress()
  152.         local rangesInfo
  153.         local RangesList = gg.getRangesList()
  154.         for _, info in ipairs(RangesList) do
  155.             local startAddr = info.start
  156.             local endAddr = info['end']
  157.  
  158.             -- Find the information about dex in memory
  159.             if startAddr <= address and address <= endAddr then
  160.  
  161.  
  162.                 if not rangesInfo or rangesInfo['end'] < info['end'] then
  163.                     rangesInfo = info
  164.                 end
  165.             end
  166.         end
  167.  
  168.         if not rangesInfo then
  169.             error(string.format('%s could not find it rangesInfo', self:getName()), 2)
  170.         end
  171.  
  172.         self.rangesInfo = rangesInfo
  173.         return rangesInfo
  174.     end
  175.  
  176.     function dex:getStartAddr()
  177.         return self:getRangesInfo().start
  178.     end
  179.  
  180.     function dex:getEndAddr()
  181.         return self:getRangesInfo()['end']
  182.     end
  183.  
  184.     function dex:getDexPosition()
  185.         return self:getAddress() - self:getStartAddr()
  186.     end
  187.  
  188.     function dex:assertProcess()
  189.         local targetPackage = self:getTargetPackage()
  190.         local packageName = self:getPackageName()
  191.  
  192.         if targetPackage ~= packageName then
  193.             error(string.format('The process has changed %s>%s', packageName, targetPackage), 2)
  194.         end
  195.     end
  196.  
  197.     function dex:getDumpMemoryPath(startAddr, endAddr, dumpDir, packageName)
  198.         if not packageName then
  199.             packageName = gg.getTargetPackage()
  200.         end
  201.         return string.format('%s/%s-%x-%x.bin', dumpDir, packageName, startAddr, endAddr)
  202.     end
  203.  
  204.     function dex:dumpMemory(startAddr, endAddr, dumpDir)
  205.         local res = gg.dumpMemory(startAddr, endAddr - 1, dumpDir)
  206.         if res ~= true then
  207.             return false, res
  208.         end
  209.  
  210.         return self:getDumpMemoryPath(startAddr, endAddr, dumpDir, self:getPackageName())
  211.     end
  212.  
  213.     function dex:dump()
  214.         self:assertProcess()
  215.  
  216.         local startAddr = self:getStartAddr()
  217.         local endAddr = self:getEndAddr()
  218.         local dumpDir = self:getDumpDir()
  219.  
  220.         local path, err = self:dumpMemory(startAddr, endAddr, dumpDir)
  221.         if not path then
  222.             error(string.format('Unable to export memory\n%s', err), 2)
  223.         end
  224.  
  225.         return path
  226.     end
  227.  
  228.     function dex:getSize()
  229.         local dexSize = self.dexSize
  230.         if dexSize then
  231.             return dexSize
  232.         end
  233.  
  234.         local offset = 32
  235.         local value = {
  236.             address = self:getAddress() + offset,
  237.             flags = gg.TYPE_DWORD
  238.         }
  239.         local vlaues = {value}
  240.         vlaues = gg.getValues(vlaues)
  241.         dexSize = vlaues[1].value
  242.  
  243.         self.dexSize = dexSize
  244.         return dexSize
  245.     end
  246.  
  247.     function dex:getDexOutPath()
  248.         return string.format('%s/%s', self:getDumpDir(), self:getName())
  249.     end
  250.  
  251.     function dex:getDexOutFile(path)
  252.         return assert(io.open(path, 'w'))
  253.     end
  254.  
  255.     function dex:getDexInputFile(path)
  256.         local f = assert(io.open(path, 'r'))
  257.         f:seek('cur', self:getDexPosition())
  258.         return f
  259.     end
  260.  
  261.     function dex:checkSize()
  262.         -- Normally, the DEX size should be a positive number and smaller than the maximum range of memory.
  263.         return dex:getSize() > 0 and dex:getSize() < (dex:getEndAddr() - dex:getStartAddr())
  264.     end
  265.  
  266.     function dex:out(outPath)
  267.         local binPath = self:dump()
  268.         local inputf = self:getDexInputFile(binPath)
  269.         local dexSize = self:getSize()
  270.         local readSize = 1024 * 1024 * 1
  271.         if dexSize < readSize then
  272.             readSize = dexSize
  273.         end
  274.  
  275.         if not outPath then
  276.             outPath = self:getDexOutPath()
  277.         end
  278.         local outf = self:getDexOutFile(outPath)
  279.  
  280.         local readLength = 0
  281.  
  282.         -- Extract DEX from the bin file exported from memory
  283.         local function copy()
  284.             while true do
  285.                 local tmp = inputf:read(readSize)
  286.                 outf:write(tmp)
  287.                 readLength = readLength + readSize
  288.  
  289.                 if readLength >= dexSize then
  290.                     inputf:close()
  291.                     outf:close()
  292.                     break
  293.                 end
  294.             end
  295.         end
  296.  
  297.         local ok, err = pcall(copy)
  298.  
  299.         -- Delete exported memory files
  300.         os.remove(binPath)
  301.  
  302.         if not ok then
  303.             -- An error occurred while copying DEX. Delete the error file.
  304.             os.remove(outPath)
  305.             return false, err
  306.         end
  307.  
  308.         -- Returns the exported DEX file path
  309.         return outPath
  310.     end
  311.  
  312.     return dex
  313. end
  314.  
  315. function dumpDex:results2dexs(results)
  316.     local dexs = {}
  317.  
  318.     for i = 1, #results, self:getResultsStep() do
  319.         local value = results[i]
  320.         local address = value.address
  321.         local dex = self:newDex(address)
  322.  
  323.         if dex and dex:checkSize() then
  324.             local index = #dexs + 1
  325.             dex.index = index
  326.             dexs[index] = dex
  327.         end
  328.     end
  329.  
  330.     return dexs
  331. end
  332.  
  333. function dumpDex:getDexs()
  334.  
  335.     -- Clear current search results
  336.     gg.clearResults()
  337.  
  338.     gg.toast('Searching for DEX files...')
  339.  
  340.     -- DEX file header
  341.     local dexhead = self:getDexHeader()
  342.  
  343.     -- h means searching in HEX (hexadecimal) format, followed by the hexadecimal number to be searched
  344.     local text = 'h ' .. self:stringToHex(dexhead)
  345.  
  346.     -- Search for DEX header information in hexadecimal format
  347.     local res = gg.searchNumber(text)
  348.     if res ~= true then
  349.         error(string.format('Search DEX failed\n%s', res), 2)
  350.     end
  351.  
  352.     -- Get all search results
  353.     local results = gg.getResults(gg.getResultsCount())
  354.  
  355.     -- Parse the search results into DEX objects
  356.     local dexs = self:results2dexs(results)
  357.  
  358.     -- Clear search
  359.     gg.clearResults()
  360.  
  361.     return dexs
  362. end
  363.  
  364. function dumpDex:getLogPath()
  365.     return string.format('%s/dump.log', self:getDumpDir())
  366. end
  367.  
  368. function dumpDex:getLogFile()
  369.     return assert(io.open(self:getLogPath(), 'w'))
  370. end
  371.  
  372. function dumpDex:start()
  373.  
  374.     local function dumpAll(dexs)
  375.         local log
  376.         local ok, err = pcall(function()
  377.             log = self:getLogFile()
  378.         end)
  379.  
  380.         -- if not ok then
  381.         --  if gg.alert(string.format('Unable to create LOG file\n%s', err), 'continue', 'quit') ~= 1 then
  382.         --      return
  383.         --  end
  384.         -- end
  385.  
  386.         local function outLog(msg)
  387.             msg = tostring(msg)
  388.  
  389.             if log then
  390.                 log:write(msg .. '\n')
  391.             end
  392.  
  393.             if msg:find('%S') then
  394.                 gg.toast(msg)
  395.             end
  396.         end
  397.  
  398.         local msg = string.format('Export package name:%s', self:getTargetPackage())
  399.         outLog(msg)
  400.  
  401.         local successCount = 0
  402.         local failCount = 0
  403.  
  404.         for i, dex in ipairs(dexs) do
  405.             local name = dex:getName()
  406.             local msg = string.format('Exporting:%s', name)
  407.             outLog(msg)
  408.  
  409.             local path, err = dex:out()
  410.             if not path then
  411.                 failCount = failCount + 1
  412.                 local msg = string.format('Export failed:%s', err)
  413.                 outLog(msg)
  414.             else
  415.                 successCount = successCount + 1
  416.                 local msg = string.format('Export successful:%s', path)
  417.                 outLog(msg)
  418.  
  419.                 local msg = string.format('File size:%s', dex:getSize())
  420.                 outLog(msg)
  421.             end
  422.             outLog('\n')
  423.         end
  424.  
  425.         local msg = string.format('Exported successfully %s 个DEX', successCount)
  426.         if failCount > 0 then
  427.             msg = msg .. '\n' .. string.format('Export failed %s 个DEX', failCount)
  428.         end
  429.         msg = msg .. '\n' .. string.format('saved on path %s', self:getDumpDir())
  430.  
  431.         outLog(msg)
  432.  
  433.         gg.alert(msg)
  434.  
  435.         -- Close LOG file
  436.         if log then
  437.             log:close()
  438.         end
  439.     end
  440.  
  441.  
  442.     local startTime = os.clock()
  443.  
  444.     -- Cache package names to avoid package name inconsistencies caused by process switching
  445.     self:setPackageName(self:getTargetPackage())
  446.  
  447.     -- Get DEX object set
  448.     local dexs = self:getDexs()
  449.  
  450.     -- Get the time it takes to parse DEX
  451.     local consuming = os.clock() - startTime
  452.  
  453.     local dexCount = #dexs
  454.     local msg = string.format('It took %.2fs to search %d dex files in the memory.', consuming, dexCount)
  455.  
  456.     local operationNames = {'Export everything with one click'}
  457.     local operationFuns = {}
  458.     operationFuns[1] = function()
  459.         return dumpAll(dexs)
  460.     end
  461.  
  462.     for i, dex in ipairs(dexs) do
  463.         local name = dex:getName()
  464.         local text = name .. '\n' .. dex:getSize() .. 'Size'
  465.         local i = #operationNames + 1
  466.         operationNames[i] = text
  467.  
  468.         operationFuns[i] = function()
  469.             local path, err = dex:out()
  470.             if not path then
  471.                 gg.alert(string.format('%sExport failed! \n\n%s', name, err))
  472.                 return
  473.             end
  474.  
  475.             gg.alert(string.format('%sExport successful! \n\n%s', name, path))
  476.         end
  477.     end
  478.  
  479.     while true do
  480.         if gg.isVisible() then
  481.  
  482.             local input = gg.choice(operationNames, nil, msg)
  483.             if not input then
  484.                 local input2 = gg.alert('Are you sure to quit? ', 'Sure', 'No')
  485.                 if input2 == 1 then
  486.                     return
  487.                 else
  488.                     gg.setVisible(false)
  489.                 end
  490.  
  491.             else
  492.                 local func = operationFuns[input]
  493.                 self:trySelfCall(func)
  494.             end
  495.         else
  496.             gg.sleep(100)
  497.         end
  498.     end
  499. end
  500.  
  501. function dumpDex:try(err)
  502.     gg.alert(string.format('try error:\n%s', err))
  503.     return err
  504. end
  505.  
  506. function dumpDex:trySelfCall(func, ...)
  507.     local ok, err = pcall(func, self, ...)
  508.     if not ok then
  509.         self:try(err)
  510.     end
  511. end
  512.  
  513. function dumpDex:main()
  514.  
  515.     local function getMsg()
  516.         local process = string.format('Package:%s', self:getTargetPackage())
  517.         local range = string.format('Memory:%s', self:getRangeText())
  518.         local msg = process .. '\n' .. range
  519.         return msg
  520.     end
  521.  
  522.     while true do
  523.  
  524.         if gg.isVisible() then
  525.             local input = gg.choice({'Select memory', 'Start export', 'exit the program','Join My Telegram Channel'}, nil, getMsg())
  526.             if not input then
  527.                 gg.setVisible(false)
  528.  
  529.             elseif input == 1 then
  530.                 self:trySelfCall(self.selectRange)
  531.  
  532.             elseif input == 2 then
  533.                 self:trySelfCall(self.start)
  534.  
  535.             elseif input == 3 then
  536.                 return
  537.            
  538.             elseif input == 4 then
  539.             gg.alert('Join our Telegram channel : https://t.me/AbhiModszYT_Return')
  540.    
  541.             end
  542.         else
  543.             gg.sleep(100)
  544.         end
  545.     end
  546. end
  547.  
  548. dumpDex:main()
Advertisement
Add Comment
Please, Sign In to add comment