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

[ @_insidious ]
---
I think it's the best to use traditional passworded script. You can create some algorithm that will match password and the generated hash, you can then log them if the key is already used. Well that's not answering the question, but you can utilize any unique ID stored. Here's my thoughts:

  1. If the script is targetting some specific games, you can grab in-game unique ID by scanning them directly on the Memory (since accessing shell is restricted in newer version of Android), if the result exist atleast one, the script can continue. For example in Minecraft, in-game character have unique identifier bounds to Xbox Live account, usually it's patterned like this: minecraft:player.0.[uuid-here]
  2. You can also utilize Game Guardian random package naming. Each installation, Game Guardian will re-install itself with random package name to avoid Game detection. You can somehow use this with pattern search: com.[length-string], etc.
  3. I don't have Android 12+ since I'm already getting comfortable in Android 10, but each process sits under /proc. Theoretically, you can get information from /proc/cpuinfo, which then you can find any Unique ID in there (or atleast anything from /proc).

---

  • 0
Posted
2 minutes ago, Xaviesz said:

[ @_insidious ]
---
I think it's the best to use traditional passworded script. You can create some algorithm that will match password and the generated hash, you can then log them if the key is already used. Well that's not answering the question, but you can utilize any unique ID stored. Here's my thoughts:

  1. If the script is targetting some specific games, you can grab in-game unique ID by scanning them directly on the Memory (since accessing shell is restricted in newer version of Android), if the result exist atleast one, the script can continue. For example in Minecraft, in-game character have unique identifier bounds to Xbox Live account, usually it's patterned like this: minecraft:player.0.[uuid-here]
  2. You can also utilize Game Guardian random package naming. Each installation, Game Guardian will re-install itself with random package name to avoid Game detection. You can somehow use this with pattern search: com.[length-string], etc.
  3. I don't have Android 12+ since I'm already getting comfortable in Android 10, but each process sits under /proc. Theoretically, you can get information from /proc/cpuinfo, which then you can find any Unique ID in there (or atleast anything from /proc).

---

Ok ty but i prefer doing by locking script to a device

  • 0
Posted

[ @_insidious ]
---
Then you can use option number 2 & 3. Game Guardian installation is different device to device. If you really want it depends on HWID, you can poke anything inside /proc, especially /proc/cpuinfo.
---

  • 0
Posted
1 hour ago, Xaviesz said:

[ @_insidious ]
---
Then you can use option number 2 & 3. Game Guardian installation is different device to device. If you really want it depends on HWID, you can poke anything inside /proc, especially /proc/cpuinfo.
---

i just said android 12 has some limitations.. like opening root files or running shell commands

  • 0
Posted (edited)

I have been working on this for a long time, and it is really hard to do without a m*ded gg, even with a m*ded gg android restriction still kick in if you are not rooted.
First of all. If you want to do this kind of validation avoid doing it locally, you should make it server sided.
And @Xaviesz proposition are pretty good you should explore it.
And for me til now the the best i have done using normal gg is combining some static data returned by gg.getTargetInfo() that i know will remain static trough the app life-cycle

so there is:

['publicSourceDir'] = '/data/app/~~Tjacue3E3QG5Zy6KYvAIxw==/com.absinthe.libchecker-9LGZY2hk_GBOyGOovtH-Dg==/base.apk',
['nativeLibraryDir'] = '/data/app/~~Tjacue3E3QG5Zy6KYvAIxw==/com.absinthe.libchecker-9LGZY2hk_GBOyGOovtH-Dg==/lib/arm64',
['uid'] = 10576,
['sourceDir'] = '/data/app/~~Tjacue3E3QG5Zy6KYvAIxw==/com.absinthe.libchecker-9LGZY2hk_GBOyGOovtH-Dg==/base.apk',

And also gg.PACKAGE

 I have created a simple algorithm that when provided some data will output an unique id, this is consistent, mean if you call the function two+ time with the same data it will provide the same output

local function generateIdentifier(...)
  local concatenatedString = table.concat({ ... })

  local hash = 0
  for i = 1, #concatenatedString do
    hash = (hash + string.byte(concatenatedString, i)) % 4294967296
  end

  local uniqueIdentifier = string.format("%08x", hash)

  return uniqueIdentifier
end


Here is a simple usage example
 

local gg = gg

local target = gg.getTargetInfo()

if not target then
  print('Target not found')
  return
end

local uuid = generateIdentifier(
  target.uid,
  target.nativeLibraryDir,
  target.packageName,
  gg.PACKAGE
)

print("uuid:", uuid) --=> uuid: 00003188
-- With the uuid you could now just query your server and perform check if there is a key associated with that uuid


But there is a catch, expect target.uid everything will change if user update or reinstall the game. So they will loose access, You may want to only use target.uid it is consistent but may change in some specific case.
Here are some research i have done about it:
https://stackoverflow.com/questions/20979478/how-uid-of-an-app-determined-during-install-in-android
https://pierrchen.blogspot.com/2016/09/an-walk-through-of-android-uidgid-based.html

And also i have tested uninstalling/reinstall install a different version of the game, the uid remain the same unless the app is signed with a different certificate.
If you are running this validation server sided you additionally have access to  the device User-Agent but i dont really like relying on it cause it can be easily spoofed. but still.
Here is an example of the http header you get

{
  'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 13; M2012K11AG Build/TQ2B.230505.005.A1)',
  host: '10.245.201.18:3000',
  connection: 'Keep-Alive',
  'accept-encoding': 'gzip'
}

With some text manipulation you could extract the OS Version and Build + the device Model

That pretty much it, with all this you may lock the script to a single device.
Note: nothing can stop someone who is determined.
You should also use a good encryption cause all of this will be for nothing if someone decrypt your code.
Note: uuid stand for User Unique Identifier

Edited by MAARS
  • 0
Posted
17 hours ago, _insidious said:

i just said android 12 has some limitations.. like opening root files or running shell commands

[ @_insidious ]
---
Sorry, I should've explain it better. Since processes sits under /proc, you can infact see your device information only through process memory, so you doesn't necessarily need to use some shell command or even accessing /proc externally. There's a lot of way to do this, the @MAARS approach is universally applicable since it's utilizing package naming, awesome stuff. You can also invoke some device properties through User-Agent (used when making a request), but as mentioned, it is easy to spoof, thus it's weak.
---
Well, I usually liked the #1 option, which utilize game stored ID. You can explore /data/data/shared_prefs or /data/data/database of the game, and find some Unique ID that bounds to the device. For example: PUBGM has a file called "device_id.xml" which contain User ID and Device ID. The Device ID is unique, since the game generate it based on your Device. Then you can either scan it through memory or dumping it based on /proc/maps and parse it's content.
---
For example in Minecraft, the device ID is stored inside /data/data/shared_prefs/com.mojang.minecraftpe_preferences, which will looks like:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="com_mojang_file_storage">Ji0PKAQqaXELCUg0AyQwdBUXPTgKZyJ3cgQiBTMFOQk/ECF1TAkLelIyCHN6bVhaWyplBlcqIFoEOGR9OwABB3AaLyg1I3cpVBQSQDFFDwIQOAYoAzN5ew==</string>
    <string name="deviceId">ce78c99876d04dfe80312166d94a4229</string>
    <int name="correlationAttempts" value="8" />
</map>

Which then it will be parsed by the game (you can find it in Memory)

{
	"device": "ce78c99876d04dfe80312166d94a4229", --device id
	"branch": "r/19_u8",
	"build": "1.19.80.22",
	"commit": "059f41fd2fecb3b7c568aa89b088ea3d1baf5a96",
	"id": "c7a648a4-4158-443d-9cc9-16c2f04bc83b",
	"tags": {
		"experiments": "[]",
		"versionCode": "981908022"
	},
	"begin": 1687328730,
	"flavor": "Publish",
	"crash": 0
}

---
My point is: Memory is already exposing a lot, so you shouldn't need to use Shell or accessing root namespace.

  • 0
Posted

thanks now i undrstand but is not easy to get the uuid,is there an app common for all androids where i can take that? like settings but gg disappears when i go there

  • 0
Posted (edited)

[ @_insidious ]
---
Are you refering to uuid that mentioned by @MAARS ? or using the way I did?
---
As answers, perhaps you can start with Google Play Store itself. Since Google acquires Android, so Playstore will exist in most devices (excluding Custom ROM). Then, you can take some Token values or any values in general from /data/data/com.android.vending. For example: com.google.android.gcm.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="appVersion" value="83621110" />
    <string name="regId">ffY2DJdZRw-cpaNyeWAwWj:APA91bHN7PMqL3vWendxHZ4eAH9Eq1j9hKzO47WA-qvhqYfj6m5LKCD9BLDELJ1gUg96GhmpsCaqRvAGhRvCVgxBBZNNyP1sleUcvco1WwQvvnMf-BD6lYzb-cFNoHYTRmc2YSVXmxNo</string>
</map>

You can then later check if the "regId" is exist, by scanning it on memory.
---

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

or using the way I did?

 

4 hours ago, Xaviesz said:

[ @_insidious ]
---
Are you refering to uuid that mentioned by @MAARS ? or using the way I did?
---
As answers, perhaps you can start with Google Play Store itself. Since Google acquires Android, so Playstore will exist in most devices (excluding Custom ROM). Then, you can take some Token values or any values in general from /data/data/com.android.vending. For example: com.google.android.gcm.xml

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <int name="appVersion" value="83621110" />
    <string name="regId">ffY2DJdZRw-cpaNyeWAwWj:APA91bHN7PMqL3vWendxHZ4eAH9Eq1j9hKzO47WA-qvhqYfj6m5LKCD9BLDELJ1gUg96GhmpsCaqRvAGhRvCVgxBBZNNyP1sleUcvco1WwQvvnMf-BD6lYzb-cFNoHYTRmc2YSVXmxNo</string>
</map>

You can then later check if the "regId" is exist, by scanning it on memory.
---

ok but whats the code for it

  • 0
Posted

[ @_insidious ]
---
I don't know what you're expecting, this is not some kind of algorithm or anything that should be made-up from scratch. The concept is really simple:

  • Initialization: script get the unique from memory -> reserve it to the server / pastebin / dispenser (server with dynamic address / ip) -> create some cache file to indicate the script is already initialized (avoid duplicate initialization)
  • Verification: script scrapping to the server -> parse the key from the server (per line) -> if the key exist, user can access the menu.

---
Even though the user can intercept request that game guardian have made (to see the server address), the user can't do anything since the password is using unique id. In theory, you can also save it within the script (bundled inside), but I prefer to store it somewhere on the server or atleast pastebin. For initialization, you can get the unique ID from memory using this script:

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

gg.searchNumber("h 67 63 6D 2D 72 65 67 69 73 74 72 61 74 69 6F 6E 2D 69 64 2D 6F 6E 2D 73 65 72 76 65 72", gg.TYPE_BYTE, false, gg.SIGN_EQUAL, 0, -1, 0)
result_count = gg.getResultsCount()
base_addr = gg.getResults(result_count)
for _ = 1, result_count do
	raw_init = const(base_addr[_].address, 47)
	raw_end = const(base_addr[_].address, 138)
	deciph = hexdecode(raw_end:gsub(raw_init, ""))
	if string.match(deciph, "^[a-zA-Z0-9-]*$") then
		break
	end
end

---
If you're interested in some explanation, ask me.

  • 0
Posted (edited)

[ @_insidious ]
---
Then you can change it with another ID from both location I mentioned earlier (or app generated ID on memory): Concept. You can use the code above as templates, don't be lazy.

---
Since I don't have multiple device, I can only test it on Emulator with multiple instances. Here's the working one, choose between Google Play & Google Play Services:

function is_unique(headers, init, ends, pattern)
	unique = false
	gg.searchNumber(headers, gg.TYPE_BYTE, false, gg.SIGN_EQUAL, 0, -1, 0)
	result_count = gg.getResultsCount()
	bases = gg.getResults(result_count)
	for _ = 1, result_count do
		raw_init = const(bases[_].address, init)
		raw_end = const(bases[_].address, ends)
		deciph = hexdecode(raw_end:gsub(raw_init, ""))
		if deciph:match(pattern) then
			unique = deciph
			break
		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

app = gg.getTargetInfo().packageName

if app == "com.android.vending" then --Google Play Store
	--[shared_pref] finsky.xml
	print("Ads Unique ID:", is_unique("h 61 64 69 64 2D 63 61 63 68 65 64 2D 76 61 6C 75 65", 64, 99, "^[a-zA-Z0-9-]*$"))
elseif app == "com.google.android.gms" then --Google Play Services
	--[database] google_app_measurement.db
	print("Instance ID:", is_unique("h 63 6F 6D 2E 67 6F 6F 67 6C 65 2E 61 6E 64 72 6F 69 64 2E 70 6C 61 79 2E 67 61 6D 65 73", 29, 61, "^[a-z0-9]*$"))
end

---
I'm expecting some effort on your part and not just "this don't work, meh". Atleast ask me what parts that you don't understand.

Edited by Xaviesz
remove print
  • 0
Posted (edited)

i tried multiple times in multiple devices, now this output: "Script terminato:
Ads Unique ID:     false" now ill test it in the play services: Script terminato:
Instance ID: (my id) this time worked all perfect... but in my nox, in my phone juts false, tried both google play services and still false, i mean there are results but prints: false. try instead with the uuid

Edited by _insidious
  • 0
Posted (edited)

Try to search the HWID or the UUID/GUID in the memory of that game ( in json format  "GUID": or "HWID":) as a string
some games use this as a unique identifer for the user data or for the file encryption key you can use it for your script aswell it will remain the same even the game get updated 

Edited by XEKEX
  • 0
Posted (edited)

[ @XEKEX ]
---
I have mention this above, looks like the OP is having a difficulty in finding one. So I will add more to the suggestion:

{"
["
{[
{{
},
],

You can find the json generated using the pattern above.
---
Another problem, Memory is often flushed once in a while, as OP Mention here:

Quote

this time worked all perfect... but in my nox, in my phone juts false

There's several way to avoid this which I will explain it later.

Edited by Xaviesz

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.