From c3c854a8dcf6ac19d80472469f89e51fdfda47bb Mon Sep 17 00:00:00 2001 From: Li Date: Sun, 21 Apr 2024 01:57:35 +1200 Subject: [PATCH] Change to an android app --- .gitignore | 20 +- .idea/.gitignore | 3 + .idea/.name | 1 + .idea/compiler.xml | 6 + .idea/deploymentTargetDropDown.xml | 10 + .idea/gradle.xml | 20 + .idea/migrations.xml | 10 + .idea/misc.xml | 9 + LICENSE | 9 - README.md | 12 - app/.gitignore | 1 + app/build.gradle | 35 + app/src/main/AndroidManifest.xml | 20 + .../java/com/psmreborn/nopsmdrm/Helper.java | 34 + .../com/psmreborn/nopsmdrm/Installer.java | 341 ++ .../com/psmreborn/nopsmdrm/MainActivity.java | 26 + .../java/com/psmreborn/nopsmdrm/Startup.java | 61 + .../psmreborn/nopsmdrm/StringEncryptor.java | 110 + app/src/main/res/drawable/app_icon.png | Bin 0 -> 4359 bytes app/src/main/res/layout/activity_main.xml | 30 + {res => app/src/main/res/raw}/busybox | Bin app/src/main/res/raw/libdefault.so | Bin 0 -> 21984 bytes .../src/main/res/raw}/libpsmkdc_jni.so | Bin {res => app/src/main/res/raw}/library.db | Bin app/src/main/res/values/colors.xml | 11 + app/src/main/res/values/strings.xml | 3 + build.gradle | 6 + gradle.properties | 21 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 + gradlew.bat | 89 + install.bat | 146 - libsuperuser/.gitignore | 1 + libsuperuser/build.gradle | 27 + libsuperuser/src/main/AndroidManifest.xml | 6 + .../chainfire/libsuperuser/Application.java | 87 + .../java/eu/chainfire/libsuperuser/Debug.java | 261 ++ .../libsuperuser/HideOverlaysReceiver.java | 62 + .../libsuperuser/MarkerInputStream.java | 186 + .../eu/chainfire/libsuperuser/Policy.java | 243 ++ .../java/eu/chainfire/libsuperuser/Shell.java | 3581 +++++++++++++++++ .../chainfire/libsuperuser/StreamGobbler.java | 257 ++ .../eu/chainfire/libsuperuser/Toolbox.java | 122 + res/AdbWinApi.dll | Bin 108320 -> 0 bytes res/AdbWinUsbApi.dll | Bin 73504 -> 0 bytes res/Psm1.7.0.apk | Bin 21355046 -> 0 bytes res/adb.exe | Bin 5857056 -> 0 bytes res/android_id.apk | Bin 37152 -> 0 bytes res/libdefault.so | Bin 21984 -> 0 bytes res/libs/bcprov-jdk18on-1.78.1.jar | Bin 8324412 -> 0 bytes res/psm.jar | Bin 6989 -> 0 bytes settings.gradle | 18 + 53 files changed, 5907 insertions(+), 169 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/misc.xml delete mode 100644 LICENSE delete mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/psmreborn/nopsmdrm/Helper.java create mode 100644 app/src/main/java/com/psmreborn/nopsmdrm/Installer.java create mode 100644 app/src/main/java/com/psmreborn/nopsmdrm/MainActivity.java create mode 100644 app/src/main/java/com/psmreborn/nopsmdrm/Startup.java create mode 100644 app/src/main/java/com/psmreborn/nopsmdrm/StringEncryptor.java create mode 100644 app/src/main/res/drawable/app_icon.png create mode 100644 app/src/main/res/layout/activity_main.xml rename {res => app/src/main/res/raw}/busybox (100%) create mode 100644 app/src/main/res/raw/libdefault.so rename {res => app/src/main/res/raw}/libpsmkdc_jni.so (100%) rename {res => app/src/main/res/raw}/library.db (100%) create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat delete mode 100644 install.bat create mode 100644 libsuperuser/.gitignore create mode 100644 libsuperuser/build.gradle create mode 100644 libsuperuser/src/main/AndroidManifest.xml create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/Application.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/Debug.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/HideOverlaysReceiver.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/MarkerInputStream.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/Policy.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/Shell.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/StreamGobbler.java create mode 100644 libsuperuser/src/main/java/eu/chainfire/libsuperuser/Toolbox.java delete mode 100644 res/AdbWinApi.dll delete mode 100644 res/AdbWinUsbApi.dll delete mode 100644 res/Psm1.7.0.apk delete mode 100644 res/adb.exe delete mode 100644 res/android_id.apk delete mode 100644 res/libdefault.so delete mode 100644 res/libs/bcprov-jdk18on-1.78.1.jar delete mode 100644 res/psm.jar create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index e8e1b20..e496144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,18 @@ -psm_backup.tar -shared_prefs/* \ No newline at end of file +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/app/build/* +/captures +.externalNativeBuild +.cxx +local.properties +libsuperuser/build/* +app/build/* \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..5478838 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +nopsmdrm \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..587f1ab --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d00cac7..0000000 --- a/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -MIT License - -Copyright (c) 2024 Li - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index f807da9..0000000 --- a/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# NoPsmDrm-Android - -NoPsmDrm patches for PSM APP on XPERIA PLAY. - -- requires JAVA -- requires you to have the Xperia ADB drivers, (see https://developer.sony.com/open-source/aosp-on-xperia-open-devices/downloads/drivers) -- requires root - -!! if you have PSM already installed create a backup of your PSM Application before using this -it *shouldnt* break anything, but ya never know .. - -.. run install.bat ? \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..daa547a --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,35 @@ +plugins { + id 'com.android.application' +} + +android { + namespace 'com.psmreborn.nopsmdrm' + compileSdk 10 + + defaultConfig { + applicationId "com.psmreborn.nopsmdrm" + minSdk 10 + //noinspection ExpiredTargetSdkVersion dont care about google play + targetSdk 10 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + dependencies { + + } +} + +dependencies { + implementation project(':libsuperuser') +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0773224 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/psmreborn/nopsmdrm/Helper.java b/app/src/main/java/com/psmreborn/nopsmdrm/Helper.java new file mode 100644 index 0000000..d2ab818 --- /dev/null +++ b/app/src/main/java/com/psmreborn/nopsmdrm/Helper.java @@ -0,0 +1,34 @@ +package com.psmreborn.nopsmdrm; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class Helper { + + private static Context ctx; + public static void setContext(Context context){ + ctx = context; + } + public static boolean isPsmInstalled(){ + try { + ctx.getPackageManager().getApplicationInfo("com.playstation.psstore", 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + + return true; + } + + public static ApplicationInfo getPsmApp() throws PackageManager.NameNotFoundException { + ApplicationInfo pkg = ctx.getPackageManager().getApplicationInfo("com.playstation.psstore", 0); + return pkg; + } + public static String getDateTime(){ + String formattedDate = new SimpleDateFormat("MM_dd_yyyy_HH_mm_ss").format(new Date()); + return formattedDate; + } +} diff --git a/app/src/main/java/com/psmreborn/nopsmdrm/Installer.java b/app/src/main/java/com/psmreborn/nopsmdrm/Installer.java new file mode 100644 index 0000000..12a9d7a --- /dev/null +++ b/app/src/main/java/com/psmreborn/nopsmdrm/Installer.java @@ -0,0 +1,341 @@ +package com.psmreborn.nopsmdrm; + +import static com.psmreborn.nopsmdrm.Helper.*; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.pm.PackageManager; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Environment; +import android.telephony.TelephonyManager; +import android.util.Log; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import eu.chainfire.libsuperuser.Shell; + +public class Installer extends AsyncTask { + private boolean wasError = false; + private String errorMsg = ""; + + private ProgressDialog dialog = null; + private Context ctx = null; + private StringEncryptor stringEncryptor = null; + private String busyboxBinary = ""; + public Installer(Context context){ + this.ctx = context; + this.stringEncryptor = new StringEncryptor(this.ctx); + } + + private void setError(String msg) throws Exception { + this.wasError = true; + this.errorMsg = msg; + Log.e("INSTALLER",errorMsg); + throw new Exception(msg); + } + private static void writeTxtFile(String txtFile, String txt) throws IOException { + Log.i("INSTALLER", "Writing: "+txtFile); + FileWriter txtStream = new FileWriter(txtFile); + txtStream.write(txt); + txtStream.close(); + } + private void copyTo(InputStream inpStream, OutputStream outStream) throws IOException { + int totalRead = 0; + byte[] buffer = new byte[0x1000]; + + do { + totalRead = inpStream.read(buffer, 0, buffer.length); + outStream.write(buffer, 0, totalRead); + } + while(totalRead >= buffer.length); + + outStream.flush(); + } + + private void unpackResource(int resourceId, File outputFile) throws IOException { + InputStream resourceStream = ctx.getResources().openRawResource(resourceId); + + FileOutputStream fs = new FileOutputStream(outputFile); + copyTo(resourceStream, fs); + fs.close(); + + resourceStream.close(); + } + + private boolean fileExistRoot(String filename) throws Shell.ShellDiedException { + int res = Shell.Pool.SU.run(new String[] { this.busyboxBinary + " stat '" + filename +"'" }); + return res == 0; + } + + private void moveFileRoot(String filename, String destFilename) throws Exception { + int res = Shell.Pool.SU.run(new String[] { this.busyboxBinary +" mv '"+ filename + "' '" +destFilename +"'"}); + if(res != 0){ + this.setError("Failed to rename "+filename+" to "+ destFilename); + } + } + private void mkdirAndChmodChown(String directory, int chmod, String chown) throws Shell.ShellDiedException { + Shell.Pool.SU.run(new String[]{ + this.busyboxBinary + " mkdir '" + directory +"'", + this.busyboxBinary + " chmod " + String.valueOf(chmod) +" '"+directory+"'", + this.busyboxBinary + " chown " + chown +":"+chown+" '"+directory+"'" + }); + } + private void copyChmodAndChown(String srcFile, String dstFile, int chmod, String chown) throws Exception { + int res = Shell.Pool.SU.run(new String[]{ + this.busyboxBinary + " cp '" + srcFile +"' '"+dstFile+"'", + this.busyboxBinary + " chmod " + String.valueOf(chmod) +" '"+dstFile+"'", + this.busyboxBinary + " chown " + chown +":"+chown+" '"+dstFile+"'" + }); + + if(res != 0){ + this.setError("Failed to copy & change mode."); + return; + } + } + + + private void setupBusyBox() throws Exception { + Log.i("INSTALLER","Creating busybox binary"); + File tmpFile = new File(ctx.getCacheDir(), "busybox"); + tmpFile.createNewFile(); + + if(tmpFile.setExecutable(true,false)) { + unpackResource(R.raw.busybox, tmpFile); + this.busyboxBinary = tmpFile.getAbsolutePath(); + } + else { + this.setError("failed to extract busybox binary."); + return; + } + + } + + + private void generateDeviceFingerprint(String outputFilename) throws FileNotFoundException, UnsupportedEncodingException { + + + TelephonyManager tm = ((TelephonyManager) ctx.getSystemService( Context.TELEPHONY_SERVICE)); + + String deviceId = "(blank)"; + if(tm != null) + deviceId = tm.getDeviceId(); + + if(deviceId == null) + deviceId = "(blank)"; + + String serial = Build.SERIAL; + if(serial == null) + serial = "(blank)"; + + String brand = Build.BRAND; + if(brand == null) + brand = "(blank)"; + + String manu = Build.MANUFACTURER; + if(manu == null) + manu = "(blank)"; + + String model = Build.MODEL; + if(model == null) + model = "(blank)"; + + String product = Build.PRODUCT; + if(product == null) + product = "(blank)"; + + String device = Build.DEVICE; + if(device == null) + device = "(blank)"; + + String type = Build.TYPE; + if(type == null) + type = "(blank)"; + + PrintWriter writer = new PrintWriter(outputFilename, "UTF-8"); + writer.println(String.valueOf(stringEncryptor.getPsmUid())); + writer.println(stringEncryptor.getAndroidId()); + writer.println(deviceId); + writer.println(serial); + writer.println(brand); + writer.println(manu); + writer.println(model); + writer.println(product); + writer.println(device); + writer.println(type); + writer.close(); + } + + private void backupPsm() throws Exception { + String psmSdcardFolder = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath(); + new File(psmSdcardFolder).mkdirs(); + String filename = "psm_"+getDateTime(); + + int res = Shell.Pool.SU.run(new String[]{this.busyboxBinary + " tar c '" + getPsmApp().dataDir + "' -f '" + new File(psmSdcardFolder, filename+".tar").getAbsolutePath()+"'"}); + if (res != 0) { + this.setError("Failed to backup existing PSM data. (exit code: " + res + ")"); + return; + } + generateDeviceFingerprint(new File(psmSdcardFolder, filename + "_DEV.txt").getAbsolutePath()); + } + + private void makeDirs() throws PackageManager.NameNotFoundException, Shell.ShellDiedException { + mkdirAndChmodChown(new File(getPsmApp().dataDir, "shared_prefs").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid())); + mkdirAndChmodChown(new File(getPsmApp().dataDir, "files").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid())); + mkdirAndChmodChown(new File(new File(getPsmApp().dataDir, "files"), "kdc").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid())); + mkdirAndChmodChown(new File(getPsmApp().dataDir, "databases").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid())); + } + + private void patchSharedPrefs() throws Exception { + // get the path to the shared_prefs folder + String sharedPrefsPath = new File(getPsmApp().dataDir, "shared_prefs").getAbsolutePath(); + // check if signininfo.xml file exists or not ... + boolean signinInfoExist = fileExistRoot(new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath()); + + if (!signinInfoExist) { // if file not found ... + // then generate our own shared_prefs + + // encrypt the actual strings, username, password, etc + String emailAddress = stringEncryptor.encryptString("nopsmdrm@transrights.lgbt"); + String password = stringEncryptor.encryptString("password"); + String accountId = stringEncryptor.encryptString(String.valueOf(0x123456789ABCDEFL)); + + // get the cache folder for our 'shared_prefs' + String tmpPrefsFolder = ctx.getCacheDir().getAbsolutePath(); + + // work out paths to each file ... + String csigninInfo = new File(tmpPrefsFolder, "SigninInfo.xml").getAbsolutePath(); + String cpsstorePrefs = new File(tmpPrefsFolder, "com.playstation.psstore_preferences.xml").getAbsolutePath(); + String crunningContentInfo = new File(tmpPrefsFolder, "RunningContentInfo.xml").getAbsolutePath(); + String clocalLibrary = new File(tmpPrefsFolder, "LocalLibrary.xml").getAbsolutePath(); + + String rsigninInfo = new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath(); + String rpsstorePrefs = new File(sharedPrefsPath, "com.playstation.psstore_preferences.xml").getAbsolutePath(); + String rrunningContentInfo = new File(sharedPrefsPath, "RunningContentInfo.xml").getAbsolutePath(); + String rlocalLibrary = new File(sharedPrefsPath, "LocalLibrary.xml").getAbsolutePath(); + + // generate shared_prefs + writeTxtFile(csigninInfo, "\n\n"+emailAddress+"\n\n"+password+"\n\n\n"); + writeTxtFile(cpsstorePrefs, "\n\n\n"+accountId+"\n\n\n\n\n\n\nUS\n\n\n\n\n\n387ce7e424258aef426aaa5be8a1638a\n\n\nen\n\n\n\n"); + writeTxtFile(crunningContentInfo, "\n\n\n\n\n"); + writeTxtFile(clocalLibrary, "\n\n\n\n\n\n"); + + // copy to the correct place and set permissions properly. + copyChmodAndChown(csigninInfo, rsigninInfo, 660, String.valueOf(stringEncryptor.getPsmUid())); + copyChmodAndChown(cpsstorePrefs, rpsstorePrefs, 660, String.valueOf(stringEncryptor.getPsmUid())); + copyChmodAndChown(crunningContentInfo, rrunningContentInfo, 660, String.valueOf(stringEncryptor.getPsmUid())); + copyChmodAndChown(clocalLibrary, rlocalLibrary, 660, String.valueOf(stringEncryptor.getPsmUid())); + + } + + } + + private void installNoPsmDrmModules() throws Exception { + String nativeLibsFolder = getPsmApp().nativeLibraryDir; + + String rlibPsmKdcFile = new File(nativeLibsFolder, "libpsmkdc_jni.so").getAbsolutePath(); + String rlibDefaultFile = new File(nativeLibsFolder, "libdefault.so").getAbsolutePath(); + String realLibDefaultFile = new File(nativeLibsFolder, "libdefault_real.so").getAbsolutePath(); + boolean realLibDefaultExist = fileExistRoot(realLibDefaultFile); + + if(!realLibDefaultExist) { + // if libdefault_real.so not found, then rename libdefault.so to libdefault_real.so ... + moveFileRoot(rlibDefaultFile, realLibDefaultFile); + } + + String clibDefault = new File(ctx.getCacheDir(), "libdefault.so").getAbsolutePath(); + String clibPsmKdc = new File(ctx.getCacheDir(), "libpsmkdc_jni.so").getAbsolutePath(); + + // unpack the library files ... + unpackResource(R.raw.libdefault, new File(clibDefault)); + unpackResource(R.raw.libpsmkdc_jni, new File(clibPsmKdc)); + + copyChmodAndChown(clibDefault, rlibDefaultFile, 755, "system"); + copyChmodAndChown(clibPsmKdc, rlibPsmKdcFile, 755, "system"); + + } + private void installDatabase() throws Exception { + String libraryDbFile = new File(ctx.getCacheDir(), "library.db").getAbsolutePath(); + + String databasesFolder = new File(getPsmApp().dataDir, "databases").getAbsolutePath(); + String rlibraryDbFile = new File(databasesFolder, "library.db").getAbsolutePath(); + + unpackResource(R.raw.library, new File(libraryDbFile)); + copyChmodAndChown(libraryDbFile, rlibraryDbFile, 660, String.valueOf(stringEncryptor.getPsmUid())); + } + + @Override + protected void onPreExecute() { + Shell.setRedirectDeprecated(false); + + dialog = new ProgressDialog(ctx); + dialog.setTitle("Installing NoPsmDrm ..."); + dialog.setMessage("Please Wait ..."); + dialog.setIndeterminate(true); + dialog.setCancelable(false); + dialog.show(); + } + @Override + protected Void doInBackground(Void... voids) { + + try { + setupBusyBox(); + + if (isPsmInstalled()) { + backupPsm(); + makeDirs(); + patchSharedPrefs(); + installNoPsmDrmModules(); + installDatabase(); + } + } + catch(Exception e){ + this.wasError = true; + this.errorMsg = e.getMessage(); + return null; + } + + return null; + } + + @Override + protected void onPostExecute(Void result) { + dialog.dismiss(); + + if(wasError) { + new AlertDialog.Builder((Activity)ctx) + .setTitle("Error Occurred.") + .setMessage(this.errorMsg) + .setCancelable(false) + .setPositiveButton("Ok", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).show(); + } + else{ + new AlertDialog.Builder((Activity)ctx) + .setTitle("Installed!") + .setMessage("Your PSM Application was patched successfully!\nNote: WI-FI has to be turned off for games to work.") + .setCancelable(false) + .setPositiveButton("Ok", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }).show(); + } + } +} diff --git a/app/src/main/java/com/psmreborn/nopsmdrm/MainActivity.java b/app/src/main/java/com/psmreborn/nopsmdrm/MainActivity.java new file mode 100644 index 0000000..e0eb187 --- /dev/null +++ b/app/src/main/java/com/psmreborn/nopsmdrm/MainActivity.java @@ -0,0 +1,26 @@ +package com.psmreborn.nopsmdrm; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; + + +public class MainActivity extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + Helper.setContext(this); + + (new Startup(this)).execute(); + } + + @Override + public void onBackPressed(){ + finish(); + } + public void installStart(View view) { + (new Installer(this)).execute(); + } +} diff --git a/app/src/main/java/com/psmreborn/nopsmdrm/Startup.java b/app/src/main/java/com/psmreborn/nopsmdrm/Startup.java new file mode 100644 index 0000000..7060c9d --- /dev/null +++ b/app/src/main/java/com/psmreborn/nopsmdrm/Startup.java @@ -0,0 +1,61 @@ +package com.psmreborn.nopsmdrm; + +import android.app.Activity; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Environment; +import android.widget.Button; +import android.widget.TextView; + +import eu.chainfire.libsuperuser.Shell; +import static com.psmreborn.nopsmdrm.Helper.*; + +public class Startup extends AsyncTask { + private Context ctx; + + private boolean wasError = false; + private String errorMsg = ""; + + public Startup(Context context) { + this.ctx = context; + } + + @Override + protected Void doInBackground(Void... params) { + try { + + if(!Shell.SU.available()){ + wasError = true; + errorMsg = "Unable to get root permission."; + } + if(!Helper.isPsmInstalled()){ + wasError = true; + errorMsg = "PSM Application is not installed, please install it first!"; + } + if(!(getPsmApp().sourceDir.startsWith("/data/") || getPsmApp().sourceDir.startsWith("/system/"))){ + wasError = true; + errorMsg = "PSM Application is installed to the SD Card not internal storage."; + } + if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ + wasError = true; + errorMsg = "No SD Card inserted."; + } + } catch (Exception e) { + wasError = true; + errorMsg = e.getMessage(); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + if(!wasError) { + Button installButton = (Button) ((Activity)ctx).findViewById(R.id.installPsm); + installButton.setEnabled(true); + } + else{ + TextView rootDetectedTV = (TextView) ((Activity)ctx).findViewById(R.id.errorMsg); + rootDetectedTV.setText("Error: "+errorMsg); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/psmreborn/nopsmdrm/StringEncryptor.java b/app/src/main/java/com/psmreborn/nopsmdrm/StringEncryptor.java new file mode 100644 index 0000000..b21d9a7 --- /dev/null +++ b/app/src/main/java/com/psmreborn/nopsmdrm/StringEncryptor.java @@ -0,0 +1,110 @@ +package com.psmreborn.nopsmdrm; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.provider.Settings; +import android.util.Base64; +import android.util.Log; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; + + +public class StringEncryptor { + private static final byte[] iv = {-126, -30, -6, -75, -99, -117, -66, 117, 39, -65, -126, -27, -12, 38, -99, 86}; + private static final byte[] salt = {-92, -102, -105, -123, 71, -33, 69, -39, -27, -32, 21, 33, 126, -81, 69, 59, 57, 29, -83, -15}; + + private Context ctx; + + StringEncryptor(Context ctx){ + this.ctx = ctx; + } + + public String getAndroidId(){ + return Settings.Secure.getString(ctx.getContentResolver(), "android_id"); + } + public int getPsmUid() { + try{ + ApplicationInfo psmAppInfo = this.ctx.getPackageManager().getApplicationInfo("com.playstation.psstore", 0); + if(psmAppInfo != null) { + return psmAppInfo.uid; + } + } + catch (PackageManager.NameNotFoundException e) { }; + return 0; + } + private String base64(byte[] data){ + return Base64.encodeToString(data, Base64.DEFAULT); + } + + public String encryptString(String str) { + byte[] data = str.getBytes(); + byte[] encryptedData = encrypt(data); + if(encryptedData != null){ + byte[] encodedData = Arrays.copyOf(encryptedData, encryptedData.length + 2); + encodedData[encodedData.length - 2] = 1; + encodedData[encodedData.length - 1] = 1; + + return base64(encodedData); + } + return null; + } + + private byte[] encrypt(byte[] input){ + try { + Cipher cipher = generateKeyCipher(StringEncryptor.salt, StringEncryptor.iv, Cipher.ENCRYPT_MODE); + if (cipher != null) { + return cipher.doFinal(input); + } + else { + Log.e("STRINGENCRYPTOR", "cipher was null"); + } + } catch (BadPaddingException | IllegalBlockSizeException e) { System.out.println(e.toString()) ;} + return null; + + } + + private Cipher generateKeyCipher(final byte[] salt, final byte[] iv, final int opmode) { + try { + final String androidId = getAndroidId(); + final String psmUid = String.valueOf(getPsmUid()); + if (androidId == null || psmUid == null) { + throw new InvalidParameterException(); + } + final SecretKeyFactory skeyFactory = SecretKeyFactory.getInstance("PBEWITHSHAAND256BITAES-CBC-BC"); + final char[] charArray = (androidId + psmUid + " com.playstation.psstore ").toCharArray(); + final PBEKeySpec keySpec = new PBEKeySpec(charArray, salt, 16, 256); + Arrays.fill(charArray, '\0'); + final SecretKeySpec key = new SecretKeySpec(skeyFactory.generateSecret(keySpec).getEncoded(), "AES"); + final Cipher newCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + newCipher.init(opmode, key, new IvParameterSpec(iv), new SecureRandom()); + return newCipher; + } + catch (NoSuchPaddingException ex) { + Log.e("STRINGENCRYPTOR", ex.toString()); + return null; + } + catch (InvalidAlgorithmParameterException ex2) { + Log.e("STRINGENCRYPTOR", ex2.toString()); + return null; + } + catch (InvalidKeyException ex3) { + Log.e("STRINGENCRYPTOR", ex3.toString()); + return null; + } + catch (InvalidKeySpecException ex4) { + Log.e("STRINGENCRYPTOR", ex4.toString()); + return null; + } + catch (NoSuchAlgorithmException ex5) { + Log.e("STRINGENCRYPTOR", ex5.toString()); + return null; + } + } +} diff --git a/app/src/main/res/drawable/app_icon.png b/app/src/main/res/drawable/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..238acc8b9a77bab0e3dcab1a1d743ff37c431c03 GIT binary patch literal 4359 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 + +