package com.psmreborn.nopsmdrm; import static com.psmreborn.nopsmdrm.Helper.*; import static com.psmreborn.nopsmdrm.Root.*; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; 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.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.Locale; import eu.chainfire.libsuperuser.Shell; // Sorry if this is kinda hard to follow ... public class NoPsmDrmInstaller extends AsyncTask { private boolean wasError = false; private String errorMsg = ""; private ProgressDialog dialog = null; private Context ctx = null; private StringEncryptor stringEncryptor = null; public NoPsmDrmInstaller(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 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 psmFilesDir = new File(getPsmApp().dataDir, "files").getAbsolutePath(); String psmKdcDir = new File(psmFilesDir, "kdc").getAbsolutePath(); String psmActFile = new File(psmKdcDir, "act.dat").getAbsolutePath(); // check if "act.dat" exists -- they've been here before ... if(fileExistRoot(psmActFile)) { String psmSdcardFolder = new File(Environment.getExternalStorageDirectory(), "psm").getAbsolutePath(); new File(psmSdcardFolder).mkdirs(); String filename = "psm_"+getDateTime(); // tar up the files tarRoot(getPsmApp().dataDir,new File(psmSdcardFolder, filename+".tar").getAbsolutePath()); // generate device fingerprint file generateDeviceFingerprint(new File(psmSdcardFolder, filename + "_DEV.txt").getAbsolutePath()); } } private void makeDirs() throws PackageManager.NameNotFoundException, Shell.ShellDiedException { mkdirAndChmodChown(new File(getPsmApp().dataDir, "cache").getAbsolutePath(), 771, String.valueOf(stringEncryptor.getPsmUid())); 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 installSharedPrefs() 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 c_signinInfo = new File(tmpPrefsFolder, "SigninInfo.xml").getAbsolutePath(); String c_psstorePrefs = new File(tmpPrefsFolder, "com.playstation.psstore_preferences.xml").getAbsolutePath(); String c_runningContentInfo = new File(tmpPrefsFolder, "RunningContentInfo.xml").getAbsolutePath(); String c_localLibrary = new File(tmpPrefsFolder, "LocalLibrary.xml").getAbsolutePath(); String r_signinInfo = new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath(); String r_psstorePrefs = new File(sharedPrefsPath, "com.playstation.psstore_preferences.xml").getAbsolutePath(); String r_runningContentInfo = new File(sharedPrefsPath, "RunningContentInfo.xml").getAbsolutePath(); String r_localLibrary = new File(sharedPrefsPath, "LocalLibrary.xml").getAbsolutePath(); // generate shared_prefs writeTxtFile(c_signinInfo, "\n" + "\n"+emailAddress+"\n" + "\n" + ""+password+"\n" + "\n" + "\n"); writeTxtFile(c_psstorePrefs, "\n" + "\n" + "\n" + ""+accountId+"\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "US\n" + "\n\n" + "\n" + "\n" + "387ce7e424258aef426aaa5be8a1638a\n" + "\n" + "\n" + ""+ Locale.getDefault().getLanguage()+"\n" + "\n" + "\n" + "\n"); writeTxtFile(c_runningContentInfo, "\n" + "\n\n" + "\n" + "\n"); writeTxtFile(c_localLibrary, "\n" + "\n\n" + "\n" + "\n" + "\n"); // copy to the correct place and set permissions properly. copyChmodAndChown(c_signinInfo, r_signinInfo, 660, String.valueOf(stringEncryptor.getPsmUid())); copyChmodAndChown(c_psstorePrefs, r_psstorePrefs, 660, String.valueOf(stringEncryptor.getPsmUid())); copyChmodAndChown(c_runningContentInfo, r_runningContentInfo, 660, String.valueOf(stringEncryptor.getPsmUid())); copyChmodAndChown(c_localLibrary, r_localLibrary, 660, String.valueOf(stringEncryptor.getPsmUid())); } } private void installNoPsmDrmModules() throws Exception { String nativeLibsFolder = getPsmApp().nativeLibraryDir; String libPsmKdcFile = new File(nativeLibsFolder, "libpsmkdc_jni.so").getAbsolutePath(); String libDefaultFile = new File(nativeLibsFolder, "libdefault.so").getAbsolutePath(); String realLibDefaultFile = new File(nativeLibsFolder, "libdefault_real.so").getAbsolutePath(); if(!fileExistRoot(realLibDefaultFile)) { // if libdefault_real.so not found, then rename libdefault.so to libdefault_real.so ... moveFileRoot(libDefaultFile, realLibDefaultFile); } // unpack the library files ... unpackResourceToLocationRoot(R.raw.libdefault, libDefaultFile, 755, "1000"); unpackResourceToLocationRoot(R.raw.libpsmkdc_jni, libPsmKdcFile, 755, "1000"); } private void installDatabase() throws Exception { String databasesFolder = new File(getPsmApp().dataDir, "databases").getAbsolutePath(); String libraryDbFile = new File(databasesFolder, "library.db").getAbsolutePath(); unpackResourceToLocationRoot(R.raw.library, libraryDbFile, 660, String.valueOf(stringEncryptor.getPsmUid())); } private void installDeviceList() throws PackageManager.NameNotFoundException, IOException, Shell.ShellDiedException { String cacheFolder = new File(getPsmApp().dataDir, "cache").getAbsolutePath(); // extract the regular device list ... String deviceList2File = new File(cacheFolder, "deviceList2.dat").getAbsolutePath(); unpackResourceToLocationRoot(R.raw.device_list2, deviceList2File, 660, String.valueOf(stringEncryptor.getPsmUid())); // extract the additional certified devices list ... String additionalCertsFile = new File(cacheFolder, "addtionalCertifiedDevList.dat").getAbsolutePath(); unpackResourceToLocationRoot(R.raw.aditional_certified_devices_list, additionalCertsFile, 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 { Root.setContext(ctx); killApplication("com.playstation.psstore"); if (isPsmInstalled()) { backupPsm(); makeDirs(); installSharedPrefs(); installDeviceList(); installNoPsmDrmModules(); installDatabase(); } else{ this.setError("PSM app is not installed."); } } 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",null).show(); } else{ new AlertDialog.Builder((Activity)ctx) .setTitle("Installed!") .setMessage("Your PSM Application was patched successfully!\n\nNote: WI-FI has to be turned off for games to work.") .setCancelable(false) .setPositiveButton("Ok", null).show(); } } }