11package com .fox2code .mmm .androidacy ;
22
3- import android .content .Context ;
43import android .content .SharedPreferences ;
54import android .os .Looper ;
65import android .util .Log ;
76import android .widget .Toast ;
87
98import androidx .annotation .NonNull ;
109
11- import com .fingerprintjs .android .fingerprint .Fingerprinter ;
12- import com .fingerprintjs .android .fingerprint .FingerprinterFactory ;
13- import com .fingerprintjs .android .fpjs_pro .Configuration ;
14- import com .fingerprintjs .android .fpjs_pro .FingerprintJS ;
15- import com .fingerprintjs .android .fpjs_pro .FingerprintJSFactory ;
1610import com .fox2code .mmm .BuildConfig ;
1711import com .fox2code .mmm .MainApplication ;
1812import com .fox2code .mmm .R ;
2418import com .fox2code .mmm .utils .HttpException ;
2519import com .fox2code .mmm .utils .PropUtils ;
2620import com .google .android .material .dialog .MaterialAlertDialogBuilder ;
21+ import com .topjohnwu .superuser .Shell ;
2722
2823import org .json .JSONArray ;
2924import org .json .JSONException ;
3025import org .json .JSONObject ;
3126
3227import java .io .File ;
3328import java .io .IOException ;
29+ import java .security .MessageDigest ;
30+ import java .security .NoSuchAlgorithmException ;
3431import java .util .ArrayList ;
3532import java .util .Iterator ;
3633import java .util .List ;
@@ -48,6 +45,9 @@ public final class AndroidacyRepoData extends RepoData {
4845 OK_HTTP_URL_BUILDER .build ();
4946 }
5047
48+ @ SuppressWarnings ("unused" )
49+ public final String ClientID = BuildConfig .ANDROIDACY_CLIENT_ID ;
50+
5151 private final boolean testMode ;
5252 private final String host ;
5353 public String token = MainApplication .getINSTANCE ().getSharedPreferences ("androidacy" , 0 ).getString ("pref_androidacy_api_token" , null );
@@ -84,42 +84,57 @@ private static String filterURL(String url) {
8484
8585 // Generates a unique device ID. This is used to identify the device in the API for rate
8686 // limiting and fraud detection.
87- public static String generateDeviceId () {
87+ public static String generateDeviceId () throws NoSuchAlgorithmException {
8888 // Try to get the device ID from the shared preferences
8989 SharedPreferences sharedPreferences = MainApplication .getINSTANCE ().getSharedPreferences ("androidacy" , 0 );
9090 String deviceIdPref = sharedPreferences .getString ("device_id" , null );
9191 if (deviceIdPref != null ) {
9292 return deviceIdPref ;
9393 } else {
94- Context context = MainApplication .getINSTANCE ().getApplicationContext ();
95- FingerprintJSFactory factory = new FingerprintJSFactory (context );
96- Configuration .Region region = Configuration .Region .US ;
97- Configuration configuration = new Configuration (
98- "NiZiHi266YaTLreOIOzc" ,
99- region ,
100- region .getEndpointUrl (),
101- true
102- );
103-
104- FingerprintJS fpjsClient = factory .createInstance (
105- configuration
106- );
107-
108- fpjsClient .getVisitorId (visitorIdResponse -> {
109- // Use the ID
110- String visitorId = visitorIdResponse .getVisitorId ();
111- // Save the ID in the shared preferences
112- SharedPreferences .Editor editor = sharedPreferences .edit ();
113- editor .putString ("device_id" , visitorId );
114- editor .apply ();
115- return null ;
116- });
117- // return the id
118- return sharedPreferences .getString ("device_id" , null );
94+ // AAAA we're fingerprintiiiiing
95+ // Really not that scary - just hashes some device info. We can't even get the info
96+ // we originally hashed, so it's not like we can use it to track you.
97+ String deviceId = null ;
98+ // Get ro.serialno if it exists
99+ // First, we need to get an su shell
100+ Shell .Result result = Shell .cmd ("getprop ro.serialno" ).exec ();
101+ // Check if the command was successful
102+ if (result .isSuccess ()) {
103+ // Get the output
104+ String output = result .getOut ().get (0 );
105+ // Check if the output is valid
106+ if (output != null && !output .isEmpty ()) {
107+ deviceId = output ;
108+ }
109+ }
110+ // Now, get device model, manufacturer, and Android version
111+ String deviceModel = android .os .Build .MODEL ;
112+ String deviceManufacturer = android .os .Build .MANUFACTURER ;
113+ String androidVersion = android .os .Build .VERSION .RELEASE ;
114+ // Append it all together
115+ deviceId += deviceModel + deviceManufacturer + androidVersion ;
116+ // Hash it
117+ MessageDigest digest = MessageDigest .getInstance ("SHA-256" );
118+ byte [] hash = digest .digest (deviceId .getBytes ());
119+ // Convert it to a hex string
120+ StringBuilder hexString = new StringBuilder ();
121+ for (byte b : hash ) {
122+ String hex = Integer .toHexString (0xff & b );
123+ if (hex .length () == 1 ) {
124+ hexString .append ('0' );
125+ }
126+ hexString .append (hex );
127+ }
128+ // Save it to shared preferences
129+ SharedPreferences .Editor editor = sharedPreferences .edit ();
130+ editor .putString ("device_id" , hexString .toString ());
131+ editor .apply ();
132+ // Return it
133+ return hexString .toString ();
119134 }
120135 }
121136
122- public boolean isValidToken (String token ) throws IOException {
137+ public boolean isValidToken (String token ) throws IOException , NoSuchAlgorithmException {
123138 String deviceId = generateDeviceId ();
124139 try {
125140 Http .doHttpGet ("https://" + this .host + "/auth/me?token=" + token + "&device_id=" + deviceId , false );
@@ -139,23 +154,8 @@ public boolean isValidToken(String token) throws IOException {
139154 }
140155
141156 @ Override
142- protected boolean prepare () {
157+ protected boolean prepare () throws NoSuchAlgorithmException {
143158 if (Http .needCaptchaAndroidacy ()) return false ;
144- // Check if we have a device ID yet
145- SharedPreferences sharedPreferences = MainApplication .getINSTANCE ().getSharedPreferences ("androidacy" , 0 );
146- String deviceIdPref = sharedPreferences .getString ("device_id" , null );
147- if (deviceIdPref == null ) {
148- // Generate a device ID
149- generateDeviceId ();
150- // Loop until we have a device ID
151- while (sharedPreferences .getString ("device_id" , null ) == null ) {
152- try {
153- Thread .sleep (100 );
154- } catch (InterruptedException e ) {
155- e .printStackTrace ();
156- }
157- }
158- }
159159 // Implementation details discussed on telegram
160160 // First, ping the server to check if it's alive
161161 try {
@@ -240,7 +240,7 @@ protected boolean prepare() {
240240 }
241241
242242 @ Override
243- protected List <RepoModule > populate (JSONObject jsonObject ) throws JSONException {
243+ protected List <RepoModule > populate (JSONObject jsonObject ) throws JSONException , NoSuchAlgorithmException {
244244 if (!jsonObject .getString ("status" ).equals ("success" ))
245245 throw new JSONException ("Response is not a success!" );
246246 String name = jsonObject .optString ("name" , "Androidacy Modules Repo" );
@@ -353,12 +353,12 @@ public boolean tryLoadMetadata(RepoModule repoModule) {
353353 }
354354
355355 @ Override
356- public String getUrl () {
356+ public String getUrl () throws NoSuchAlgorithmException {
357357 return this .token == null ? this .url :
358358 this .url + "?token=" + this .token + "&v=" + BuildConfig .VERSION_CODE + "&c=" + BuildConfig .VERSION_NAME + "&device_id=" + generateDeviceId ();
359359 }
360360
361- private String injectToken (String url ) {
361+ private String injectToken (String url ) throws NoSuchAlgorithmException {
362362 // Do not inject token for non Androidacy urls
363363 if (!AndroidacyUtil .isAndroidacyLink (url )) return url ;
364364 if (this .testMode ) {
0 commit comments