Jump to content

Question

Posted

i just wanted to my script its locked to a device, i found a topic where was needed to grab mac address from root files, But its not possible anymore due to android 12 and up resctrictions, Not even shell commands. doing it with ip address its useless because its dynamic, i just need a way to do thisz the only problem is to take unique data from devices like imei as example.

Recommended Posts

  • 0
Posted (edited)

[ @_insidious ]
---
It means that the pattern being searched is already flushed out of memory, thus resulting in "false" result. There's several ways to avoid this:

  • - Freeze the game first while searching the value.
  • - Perform with multiple pattern search, meaning if one value is non-existent, the script will perform another search with different pattern.
  • - You can do "something" inside the app/game to make the value appear again on memory. For example: you can do comment / download some apps on the playstore to spawn "gsf id" on memory. GSF ID is unique and it is bound to the device, formerly known as Android ID.

---
In this case, I recommend to find a static value, usually only exist in Read-Only region of memory. Off course you can also use the @MAARS suggestion that use Package Naming, but doing it with memory, you can do more beyond that. For example, you can bounds the script to only work with certain in-game account, etc.
---
In this case, I definitely recommends you to do some multiple pattern search (instead of one), if you're going to use this way. Memory is unreliable.

Edited by Xaviesz
  • 0
Posted
7 hours ago, Xaviesz said:

[ @_insidious ]
---
It means that the pattern being searched is already flushed out of memory, thus resulting in "false" result. There's several ways to avoid this:

  • - Freeze the game first while searching the value.
  • - Perform with multiple pattern search, meaning if one value is non-existent, the script will perform another search with different pattern.
  • - You can do "something" inside the app/game to make the value appear again on memory. For example: you can do comment / download some apps on the playstore to spawn "gsf id" on memory. GSF ID is unique and it is bound to the device, formerly known as Android ID.

---
In this case, I recommend to find a static value, usually only exist in Read-Only region of memory. Off course you can also use the @MAARS suggestion that use Package Naming, but doing it with memory, you can do more beyond that. For example, you can bounds the script to only work with certain in-game account, etc.
---
In this case, I definitely recommends you to do some multiple pattern search (instead of one), if you're going to use this way. Memory is unreliable.

bro i reccomend for you to create one that grabs uuid instead mars its right i tried didnt work

  • 0
Posted

[ @expensivedebris ]
---
Mine also already grabs UUID from "ADID-CACHED-VALUE" :

Quote

Script ended:
Ads Unique ID:     e087a7cb-b04f-4e5d-a527-f665a3a1625

---
The different with @MAARS, he's merging the result of "gg.getTargetInfo()" -> Convert it's character into bytes with some hash key "4294967296" -> and the result is custom unique ID, it is not UUID though. Meanwhile, I'm getting the info purely from Memory which isn't really reliable (but the value is consistent).
---
I might look into this and search some static value.

  • 0
Posted
38 minutes ago, Xaviesz said:

Script ended:
Ads Unique ID:     e087a7cb-b04f-4e5d-a527-f665a3a1625

You should not rely on ads id

image.png

  • 0
Posted

[ @MAARS ]
---
Oh right. Finding json generated content on memory based on @XEKEX suggestion, only found these at runtime:

{"backend":"dex","compilation-mode":"release","has-checksums":false,"min-api":15,"pg-map-id":"8207912","r8-mode":"full","sha-1":"d0a9eb1e5efb08c60145b38f7ff5028013d0bbc1","version":"8.2.5-dev"}

{"packageName":"com.pubg.newstate","productId":"google.global.preorder.permanent.evcar","purchaseTime":1622560953876,"purchaseState":0,"purchaseToken":"elhfcoiikbmbgocondejdmgf.AO-J1OxvkT-wu3mT46MmpzmK5wGgq19l4jktOmwuRtyieslSRth-3YUi5S2S3rZ6YYlyy3AWCjl523MiI2A0Hlr2UHwXHX_syA"}

Which nothing really unique.
---
I have explore more directories from Google Play Store, which there's only quite amount of thing, unless you're planning to bounds the account with Google Account, there's a lot of them.

print("GMS ID:", is_unique("h 6E 3A 24", 3, 39, "^[a-zA-Z0-9-]*$"))

--Result:
Script ended:
GMS ID: 	2b00f672-c6f5-45ce-b515-a7f2fcdbd6d2

Script ended:
GMS ID: 	9d24361c-5eca-40a2-8f92-382c005a5795

---
Well, that's the concept, I think it should be enough for someone to figure it out themself.

  • 0
Posted

[ @everyone ]
---
I have fixed the pattern to be applicable on most devices, tested on Emulators and Virtual Machine:

print("GMS ID:", is_unique("h 3A 24", 2, 38, "^[a-zA-Z0-9-]*$"))

---

  • 0
Posted (edited)
On 6/27/2023 at 7:23 PM, Xaviesz said:

[ @everyone ]
---
I have fixed the pattern to be applicable on most devices, tested on Emulators and Virtual Machine:

print("GMS ID:", is_unique("h 3A 24", 2, 38, "^[a-zA-Z0-9-]*$"))

---

Tried your script multiple times in multiple device but sometimes bot otputs are false, so its not guaranteed that it works + gmd id never worked

Edited by _insidious
  • 0
Posted

[ @_insidious ]
---
For the last couple of days, I found Universal pattern to find most ID on Google Play.

  • - Most UUID starts with "$" sign
  • - Hash starts with "AB-"
  • - Token starts with "CAMS"
  • - Long unique string often carries ":" on the front
  • - Cached memory usually starts with six "00", then the content comes after it.

---
I've utilize most of that and come up with multiple pattern, save it as "tablet.lua" :

patterns =
{
	[1]= {
		[1]= {
			["pattern"] = "h 24",
			["init"] = 1,
			["ended"] = 37
		},
		["message"] = "Universal ID",
		["regex"] = "^[a-zA-Z0-9-]*$",
		["must"] = "",
		["flags"] = true
	},
	[2]= {
		[1]= {
			["pattern"] = "h 41 42 2D",
			["init"] = 0,
			["ended"] = 204
		},
		["message"] = "Universal Hash",
		["regex"] = "^[a-zA-Z0-9-_]*$",
		["must"] = "",
		["flags"] = true
	},
	[3]= {
		[1]= {
			["pattern"] = "h 43 41 4D 53",
			["init"] = 0,
			["ended"] = 208
		},
		["message"] = "Universal Header",
		["regex"] = "^(.*=)",
		["must"] = "^[a-zA-Z0-9-_=]*$",
		["flags"] = true
	},
	[4]= {
		[1]= {
			["pattern"] = "h 63 6F 6D 2E 67 6F 6F 67 6C 65 2E 61 6E 64 72 6F 69 64 2E 67 6D 73",
			["init"] = 29,
			["ended"] = 65
		},
		[2]= {
			["pattern"] = "h 67 6D 73",
			["init"] = 10,
			["ended"] = 46
		},
		["message"] = "GMS UUID",
		["regex"] = "^[a-zA-Z0-9-]*$",
		["must"] = "-",
		["flags"] = true
	},
	[5]= {
		[1]= {
			["pattern"] = "h 70 68 65 6E 6F 74 79 70 65 5F 73 65 72 76 65 72 5F 74 6F 6B 65 6E",
			["init"] = 38,
			["ended"] = 246
		},
		["message"] = "Phenotype Server Token",
		["regex"] = "^(.*=)",
		["must"] = "^[a-zA-Z0-9-_=]*$",
		["flags"] = false
	}
}

---
Now you can call the pattern from "tablet.lua" (save it on the same Directory!) into our main script:

app = gg.getTargetInfo().packageName
dofile("./tablet.lua")
options = {}
results = {}

function is_unique(datas, parent, flags)
	unique = false
	gg.clearResults()
	gg.searchNumber(datas["pattern"], gg.TYPE_BYTE, false, gg.SIGN_EQUAL, 0, -1, 0)
	result_count = gg.getResultsCount()
	if result_count > 0 then
		bases = gg.getResults(result_count)
		for _ = 1, result_count do
			raw_init = const(bases[_].address, datas["init"])
			raw_end = const(bases[_].address, datas["ended"])
			deciph = hexdecode(raw_end:gsub(raw_init, ""))
			regex = deciph:match(parent["regex"])
			must = false
			if regex ~= nil then
				if regex:match(parent["must"]) then
					must = true
				end
			end
			if regex ~= nil and must ~= false then
				unique = regex
				table.insert(results[parent["message"]], regex)
				if flags == true then
					break
				end
			end
		end
	end
	return unique
end

function const(addr, buffer)
	construct = ""
	current = {}
	for _ = 1, buffer do
		current[_] = {address = (addr - 1) + _, flags = gg.TYPE_BYTE}
	end
	for k, v in ipairs(gg.getValues(current)) do
		construct = construct .. string.format("%02X", v.value & 0xFF)
    end
	return construct
end

function hexdecode(hex)
   return (hex:gsub("%x%x", function(digits) return string.char(tonumber(digits, 16)) end))
end

function looper(datas, flags)
	pattern = false
	results[datas["message"]] = {}
	for key, value in ipairs(datas) do
		if type(key) == "number" then
			for ___ = 1, 2 do
				pattern = is_unique(value, datas, flags)
				if pattern ~= false then
					break
				end
			end
		end
		if pattern ~= false then
			break
		end
	end
end

function printer()
	flags = false
	for k in pairs(results) do
		if flags == true then
			break
		end
		for v in pairs(results[k]) do
			print(results)
			choice = gg.alert(k .. ': ' .. results[k][v], 'OK', 'Exit')
			if choice == 2 then
				flags = true
				break
			end
		end
	end
end

for k, v in ipairs(patterns) do
	table.insert(options, v["message"])
end

while true do
	choice = gg.choice({"Exit", "Search", "Printer"}, nil, "Selections:")
	if choice == 2 then
		choice = gg.choice(options, nil, "Patterns:")
		looper(patterns[choice], patterns[choice]['flags'])
	elseif choice == 3 then
		printer()
	else
		os.exit()
	end
end

---
Using Universal pattern can take a while (even long time), but it can captures all possible unique ID.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.