Add NoPs1Drm !!

This commit is contained in:
Li 2024-05-17 17:32:46 +12:00
parent 780278c9fa
commit 6acd9fb269
25 changed files with 582 additions and 187 deletions

4
.gitignore vendored
View File

@ -16,4 +16,6 @@
local.properties
libsuperuser/build/*
app/build/*
app/release/*
app/release/*
libNpTicket/*

View File

@ -12,8 +12,8 @@ android {
minSdk 10
//noinspection ExpiredTargetSdkVersion dont care about google play
targetSdk 23
versionCode 8
versionName "1.8"
versionCode 9
versionName "1.9"
}
buildTypes {

View File

@ -20,12 +20,18 @@
<application
android:allowBackup="true"
android:icon="@drawable/app_icon"
android:label="@string/app_name">
android:label="@string/name_nopsmdrm">
<activity android:name="com.psmreborn.nopsmdrm.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:launchMode="singleTop" android:name="com.psmreborn.nops1drm.LicenseCheckActivity" android:label="@string/name_nops1drm" android:icon="@drawable/nops1drm_icon" android:screenOrientation="landscape">
<intent-filter>
<action android:name="com.playstation.android.intent.action.CHECK_ENTITLEMENT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,78 @@
package com.psmreborn.nops1drm;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import com.psmreborn.shared.Logger;
import com.psmreborn.shared.Root;
public class LicenseCheckActivity extends Activity {
private static final int RESPONSE_CODE = 19941203;
public void respond(byte[] response, int resp){
Intent resIntent = new Intent();
resIntent.putExtra("result_data", response);
this.setResult(resp, resIntent);
this.finish();
}
@Override
protected void onActivityResult(int res, int res_code, Intent intent) {
if(res == RESPONSE_CODE) {
byte[] result_data = intent.getByteArrayExtra("result_data");
Logger.logBytes("RESULT_DATA", result_data);
Logger.logText( "RES", String.valueOf(res_code));
respond(result_data, res_code);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Read intent from ps1 game
String entitlement_id = this.getIntent().getStringExtra("entitlement_id");
byte[] input_data = this.getIntent().getByteArrayExtra("input_data");
Logger.logText("ENTITLEMENT_ID", entitlement_id);
Logger.logBytes("INPUT_DATA", input_data);
// Generate ticket and put it into com.playstation.psstore databases.
Handler handler = new Handler(this.getMainLooper());
new Thread(()->{
try {
if(Root.init(this)){
PsmStartupCache.addEntitlement(this, entitlement_id);
handler.post(() ->{
// Forward intent to psm.apk
Intent intent = new Intent("com.playstation.android.intent.action.CHECK_ENTITLEMENT");
intent.putExtra("entitlement_id", entitlement_id);
intent.putExtra("input_data", input_data);
intent.setPackage("com.playstation.psstore");
startActivityForResult(intent, RESPONSE_CODE);
});
}
else{
handler.post(() -> {
respond(new byte[]{}, 0);
});
}
} catch (Exception e) {
Log.e("LicenseCheckerActivity", e.toString());
handler.post(() -> {
respond(new byte[]{}, 0);
});
}
}).start();
}
}

View File

@ -0,0 +1,149 @@
package com.psmreborn.nops1drm;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.psmreborn.nopsmdrm.R;
import com.psmreborn.shared.Helper;
import com.psmreborn.shared.Logger;
import com.psmreborn.shared.Root;
import com.psmreborn.shared.StringEncryptor;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
public class PsmStartupCache {
private static StringEncryptor stringEncryptor = null;
private static String sha256HexStr(String str) {
String lowerStr = str.toLowerCase();
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(lowerStr.getBytes("UTF-8"));
byte[] digest = messageDigest.digest();
StringBuilder sb = new StringBuilder();
for (byte hexDigit : digest) {
sb.append(Integer.toHexString(hexDigit & 255));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
return null;
} catch (UnsupportedEncodingException e) {
return null;
}
}
private static void copyToPsm(Context ctx) throws Exception {
String psmDataDir = Helper.getPsmAppInfo(ctx).dataDir;
String psmDatabasesDir = new File(psmDataDir, "databases").getAbsolutePath();
String psmStartContentDb = new File(psmDatabasesDir, "start_content.db").getAbsolutePath();
String myDataDir = Helper.getAppInfo(ctx, ctx.getPackageName()).dataDir;
String myDatabasesDir = new File(myDataDir, "databases").getAbsolutePath();
String myStartContentDb = new File(myDatabasesDir, "start_content.db").getAbsolutePath();
Root.mkdirAndChmodChown(psmDatabasesDir, 771, String.valueOf(Helper.getPsmUid(ctx)));
Root.copyChmodAndChown(myStartContentDb, psmStartContentDb, 660, String.valueOf(Helper.getPsmUid(ctx)));
}
private static void copyFromPsm(Context ctx) throws Exception {
String psmDataDir = Helper.getPsmAppInfo(ctx).dataDir;
String psmDatabasesDir = new File(psmDataDir, "databases").getAbsolutePath();
String psmStartContentDb = new File(psmDatabasesDir, "start_content.db").getAbsolutePath();
String myDataDir = Helper.getAppInfo(ctx, ctx.getPackageName()).dataDir;
String myDatabasesDir = new File(myDataDir, "databases").getAbsolutePath();
String myStartContentDb = new File(myDatabasesDir, "start_content.db").getAbsolutePath();
Root.mkdirAndChmodChown(myDatabasesDir, 771, String.valueOf(Helper.getMyUid(ctx)));
Root.copyChmodAndChown(psmStartContentDb, myStartContentDb, 660, String.valueOf(Helper.getMyUid(ctx)));
}
private static int dbRemoveEntry(StartContentDb cdb, String entitlementId) {
Logger.logText("DELETE, ENTITLEMENT_ID", entitlementId);
SQLiteDatabase db = cdb.getWritableDatabase();
int v = db.delete("cache_table", "entitlement_id = ?", new String[]{entitlementId});
db.close();
return v;
}
private static byte[] dbGetEntry(StartContentDb cdb, String entitlementId){
Log.i("TicketGen", "dbGetEntry, "+entitlementId);
SQLiteDatabase db = cdb.getReadableDatabase();
Cursor query = db.query("cache_table", new String[] {"_id", "user_id", "entitlement_id", "ticket_data", "last_update"}, "entitlement_id = ?", new String[]{entitlementId}, null, null, null);
if (query == null || query.getCount() != 1) {
db.close();
return null;
} else {
query.moveToFirst();
byte[] ticketEnc = query.getBlob(query.getColumnIndex("ticket_data"));
query.close();
db.close();
return stringEncryptor.decrypt(ticketEnc);
}
}
private static void dbAddEntry(StartContentDb cdb, String userId, String entitlementId, byte[] ticket) throws Exception {
Log.i("TicketGen", "dbAddEntry, "+entitlementId);
SQLiteDatabase db = cdb.getWritableDatabase();
ContentValues values = new ContentValues();
byte[] encryptedTicket = stringEncryptor.encrypt(ticket);
String shaUserId = sha256HexStr(userId);
values.put("user_id", shaUserId);
values.put("entitlement_id", entitlementId);
values.put("ticket_data", encryptedTicket);
values.put("last_update", System.currentTimeMillis());
Logger.logText("USER_ID", shaUserId);
Logger.logText("ENTITLEMENT_ID", entitlementId);
Logger.logBytes("TICKET_DATA", ticket);
Logger.logBytes("ENCRYPTED_TICKET_DATA", encryptedTicket);
Long pos = db.insert("cache_table", null, values);
db.close();
if(pos <= -1)
throw new Exception("failed to insert");
}
public static void addEntitlement(Context ctx, String entitlement_id) throws Exception {
stringEncryptor = new StringEncryptor(Helper.getAndroidIdOfPsm(ctx), Helper.getPsmUid(ctx));
try{copyFromPsm(ctx);} catch (Exception ignored) { };
// get default values for onlineid, accountid, etc.
String email = stringEncryptor.decryptString(Helper.getSharedPrefFromPsm(ctx, "SigninInfo", "SignedInUsername"), ctx.getResources().getString(R.string.default_email));
Long accountId = Long.valueOf(stringEncryptor.decryptString(Helper.getSharedPrefFromPsm(ctx, "com.playstation.psstore_preferences", "last_signin_account_id"), String.valueOf(Helper.getDefaultAccountId(ctx))));
String onlineId = ctx.getResources().getString(R.string.default_online_id);
// read psm start content.db file ..
StartContentDb scdb = new StartContentDb(ctx);
byte[] ticket = dbGetEntry(scdb, entitlement_id);
if(ticket == null){
Log.i("TicketGen", "No ticket found, generating new!");
dbAddEntry(scdb, email, entitlement_id, TicketGen.generateTicket(entitlement_id, Locale.getDefault().getLanguage(), onlineId, accountId));
}
else{
if(!TicketGen.ticketExpired(ticket)) {
Log.i("TicketGen", "Previous ticket expired, generating new one!");
dbRemoveEntry(scdb, entitlement_id);
dbAddEntry(scdb, email, entitlement_id, TicketGen.generateTicket(entitlement_id, Locale.getDefault().getLanguage(), onlineId, accountId));
}
else{
Log.i("TicketGen", "Existing ticket is all good! continuing to PSM!");
}
}
scdb.close();
try{copyToPsm(ctx);} catch (Exception ignored) { };
}
}

View File

@ -0,0 +1,26 @@
package com.psmreborn.nops1drm;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
final class StartContentDb extends SQLiteOpenHelper {
public StartContentDb(Context context) {
this(context, "start_content.db");
}
private StartContentDb(Context context, String str) {
super(context, str, (SQLiteDatabase.CursorFactory) null, 1);
}
@Override // android.database.sqlite.SQLiteOpenHelper
public final void onCreate(SQLiteDatabase sqllite) {
sqllite.execSQL("CREATE TABLE IF NOT EXISTS cache_table (_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,user_id TEXT,entitlement_id TEXT NOT NULL,ticket_data BLOB NOT NULL,last_update LONG NOT NULL)");
}
@Override // android.database.sqlite.SQLiteOpenHelper
public final void onUpgrade(SQLiteDatabase sqllite, int i, int i2) {
sqllite.execSQL("DROP TABLE IF EXISTS cache_table");
sqllite.execSQL("CREATE TABLE IF NOT EXISTS cache_table (_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,user_id TEXT,entitlement_id TEXT NOT NULL,ticket_data BLOB NOT NULL,last_update LONG NOT NULL)");
}
}

View File

@ -0,0 +1,82 @@
package com.psmreborn.nops1drm;
import com.psmreborn.shared.Logger;
import java.util.Arrays;
public class TicketGen {
private static final byte[] baseTicket = {(byte)0x41, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x5D, (byte)0x30, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x0F, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x14, (byte)0xBA, (byte)0x1D, (byte)0x80, (byte)0x73, (byte)0xC1, (byte)0xAE, (byte)0x02, (byte)0x75, (byte)0xD5, (byte)0xD3, (byte)0xED, (byte)0x8C, (byte)0x18, (byte)0x72, (byte)0x5A, (byte)0xA3, (byte)0x29, (byte)0x1C, (byte)0xC9, (byte)0xDF, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x65, (byte)0x95, (byte)0x4D, (byte)0xAC, (byte)0x7B, (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x03, (byte)0xB9, (byte)0x03, (byte)0x74, (byte)0xCF, (byte)0x60, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x12, (byte)0x34, (byte)0x56, (byte)0x89, (byte)0xAB, (byte)0xCD, (byte)0xEF, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x20, (byte)0x4F, (byte)0x6E, (byte)0x6C, (byte)0x69, (byte)0x6E, (byte)0x65, (byte)0x49, (byte)0x64, (byte)0x68, (byte)0x65, (byte)0x72, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x04, (byte)0x65, (byte)0x6E, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x04, (byte)0x64, (byte)0x37, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x18, (byte)0x45, (byte)0x50, (byte)0x34, (byte)0x31, (byte)0x33, (byte)0x34, (byte)0x2D, (byte)0x4E, (byte)0x50, (byte)0x45, (byte)0x46, (byte)0x30, (byte)0x30, (byte)0x32, (byte)0x32, (byte)0x33, (byte)0x5F, (byte)0x30, (byte)0x30, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x30, (byte)0x11, (byte)0x00, (byte)0x04, (byte)0x07, (byte)0xC8, (byte)0x0C, (byte)0x06, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x19, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x30, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0F, (byte)0x06, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x31, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x62, (byte)0x3F, (byte)0xCE, (byte)0x27, (byte)0xD0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x40, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x30, (byte)0x02, (byte)0x00, (byte)0x44, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x04, (byte)0xBD, (byte)0x97, (byte)0x9F, (byte)0x07, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x38, (byte)0x30, (byte)0x35, (byte)0x02, (byte)0x18, (byte)0x08, (byte)0xA4, (byte)0xC8, (byte)0xD2, (byte)0x50, (byte)0x74, (byte)0xCC, (byte)0xFA, (byte)0xF2, (byte)0xBF, (byte)0xF8, (byte)0x49, (byte)0x27, (byte)0xC3, (byte)0x04, (byte)0xA7, (byte)0x79, (byte)0xE2, (byte)0x3C, (byte)0x30, (byte)0xCA, (byte)0xE6, (byte)0x2C, (byte)0xE5, (byte)0x02, (byte)0x19, (byte)0x00, (byte)0xE0, (byte)0x4C, (byte)0x84, (byte)0x9F, (byte)0x41, (byte)0x4D, (byte)0x6B, (byte)0x0E, (byte)0xFA, (byte)0xBE, (byte)0x38, (byte)0xC4, (byte)0x72, (byte)0x2A, (byte)0x11, (byte)0x46, (byte)0x8A, (byte)0x04, (byte)0x3D, (byte)0x50, (byte)0x68, (byte)0xDC, (byte)0x99, (byte)0xA7, (byte)0x00};
private static byte[] longToBytes(long l) {
byte[] result = new byte[8];
for (int i = 8 - 1; i >= 0; i--) {
result[i] = (byte)(l & 0xFF);
l >>= Byte.SIZE;
}
return result;
}
private static long bytesToLong(final byte[] b) {
long result = 0;
for (int i = 0; i < 8; i++) {
result <<= Byte.SIZE;
result |= (b[i] & 0xFF);
}
return result;
}
private static void cpy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int cpMaxLen){
for(int i = 0; i < cpMaxLen; i++){
byte b = 0;
if((i + srcOffset) < src.length) {
b = src[i + srcOffset];
}
dst[i + dstOffset] = b;
}
}
public static boolean ticketExpired(byte[] ticket){
byte[] expireDateBytes = new byte[0x8];
cpy(ticket, 0x40, expireDateBytes, 0, 0x8);
long expDate = bytesToLong(expireDateBytes);
return expDate >= System.currentTimeMillis();
}
public static byte[] generateTicket(String entitlmentId, String language, String onlineId, Long accountId) throws Exception {
Logger.logText("ENTITLEMENT_ID", entitlmentId);
Logger.logText("LANGUAGE", language);
Logger.logText("ONLINE_ID", onlineId);
Logger.logText("ACCOUNT_ID", String.valueOf(accountId));
long curTime = System.currentTimeMillis();
long expireTime = System.currentTimeMillis() + (1209600 * 1000);
Logger.logText("CUR_TIME", String.valueOf(curTime));
Logger.logText("EXPIRE_TIME", String.valueOf(expireTime));
String servicePart = entitlmentId.substring(0x0, 0x13);
String entitlementPart = entitlmentId.substring(0x14);
Logger.logText("SERVICE_PART", servicePart);
Logger.logText("ENTITLEMENT_PART", entitlementPart);
// get a copy of the base ticket ...
byte[] newTicket = Arrays.copyOf(baseTicket, baseTicket.length);
// copy strings to new ticket ..
cpy(servicePart.getBytes("UTF-8"), 0, newTicket, 0x8C, 0x18);
cpy(entitlementPart.getBytes("UTF-8"), 0, newTicket, 0xBB, 0x6);
cpy(onlineId.getBytes("UTF-8"), 0, newTicket, 0x58, 0x20);
cpy(language.getBytes("UTF-8"), 0, newTicket, 0x7C, 0x2);
// copy longs to ticket
cpy(longToBytes(accountId), 0, newTicket, 0x4C, 0x8);
cpy(longToBytes(curTime), 0, newTicket, 0x34, 0x8);
cpy(longToBytes(expireTime), 0, newTicket, 0x40, 0x8);
// return the patched ticket.
return newTicket;
}
}

View File

@ -10,6 +10,8 @@ import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import com.psmreborn.shared.Helper;
import java.io.File;
import java.io.IOException;
@ -29,7 +31,7 @@ public class DumpAllRifs {
File psmAndroidFolder = new File(new File(new File(new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"), "com.playstation.psstore"), "files"), "psm");
// stop psm
Helper.killPsm();
Helper.killPsm(ctx);
try {
psmDumpAllFlagFile.createNewFile();

View File

@ -3,20 +3,13 @@ package com.psmreborn.nopsmdrm;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import com.psmreborn.shared.Helper;
import com.psmreborn.shared.Root;
import java.io.File;
import java.io.IOException;
import eu.chainfire.libsuperuser.Shell;
public class FixPermissions {
public static void changePermissionsToPsm(Activity ctx) {
@ -30,11 +23,11 @@ public class FixPermissions {
new Thread(() -> {
Handler handler = new Handler(ctx.getMainLooper());
Helper.killPsm();
Helper.killPsm(ctx);
String androidDataFolder = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data").getAbsolutePath();
try {
String groupId = Root.getFileGroup(androidDataFolder);
String userId = String.valueOf(Helper.getPsmAppInfo().uid);
String userId = String.valueOf(Helper.getPsmAppInfo(ctx).uid);
Root.chownRoot(new File(new File(new File(androidDataFolder, "com.playstation.psstore"), "files"), "psm").getAbsolutePath(), userId, groupId);
handler.post(() -> {

View File

@ -8,8 +8,10 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import com.psmreborn.nopsmdrm.pscertified.PlayStationCertified;
import com.psmreborn.nopsmdrm.pscertified.PsCertificatesInstaller;
import com.psmreborn.pscertified.PlayStationCertified;
import com.psmreborn.pscertified.PsCertificatesInstaller;
import com.psmreborn.shared.Downloader;
import com.psmreborn.shared.Helper;
import java.io.File;
@ -21,7 +23,6 @@ public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Helper.setContext(this);
(new Startup(this)).execute();
}
@ -69,7 +70,7 @@ public class MainActivity extends Activity {
if(!PlayStationCertified.isPlaystationCertified(this.getApplicationContext())){
psCertifiedAlert();
}
else if(!Helper.isPsmInstalled()) {
else if(!Helper.isPsmInstalled(this)) {
downloadPsmAlert();
}
else {

View File

@ -1,14 +1,14 @@
package com.psmreborn.nopsmdrm;
import static com.psmreborn.nopsmdrm.Helper.*;
import static com.psmreborn.nopsmdrm.Root.*;
import static com.psmreborn.shared.Helper.*;
import static com.psmreborn.shared.Root.*;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
@ -18,20 +18,18 @@ import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import org.xmlpull.v1.XmlPullParserException;
import com.psmreborn.shared.Files;
import com.psmreborn.shared.Helper;
import com.psmreborn.shared.Root;
import com.psmreborn.shared.StringEncryptor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import eu.chainfire.libsuperuser.Shell;
// Sorry if this is kinda hard to follow ...
@ -54,6 +52,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
throw new Exception(msg);
}
@SuppressLint("MissingPermission")
private void generateDeviceFingerprint(String outputFilename) throws Exception {
TelephonyManager tm = ((TelephonyManager) ctx.getSystemService( Context.TELEPHONY_SERVICE));
@ -93,8 +92,8 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
type = "(blank)";
PrintWriter writer = new PrintWriter(outputFilename, "UTF-8");
writer.println(String.valueOf(Helper.getPsmUid()));
writer.println(Helper.getAndroidIdOfPsm());
writer.println(String.valueOf(Helper.getPsmUid(ctx)));
writer.println(Helper.getAndroidIdOfPsm(ctx));
writer.println(deviceId);
writer.println(serial);
writer.println(brand);
@ -109,7 +108,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
private void backupPsm() throws Exception {
String psmFilesDir = new File(getPsmAppInfo().dataDir, "files").getAbsolutePath();
String psmFilesDir = new File(Helper.getPsmAppInfo(ctx).dataDir, "files").getAbsolutePath();
String psmKdcDir = new File(psmFilesDir, "kdc").getAbsolutePath();
String psmActFile = new File(psmKdcDir, "act.dat").getAbsolutePath();
String psmAndroidFolder = new File(new File(new File(new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data"), "com.playstation.psstore"), "files"), "psm").getAbsolutePath();
@ -128,7 +127,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
generateDeviceFingerprint(devinfoFile);
ArrayList<String> filesToTar = new ArrayList<String>();
filesToTar.add(getPsmAppInfo().dataDir);
filesToTar.add(Helper.getPsmAppInfo(ctx).dataDir);
filesToTar.add(devinfoFile);
// add all license folders ....
@ -151,15 +150,15 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
}
private void makeDirs() throws PackageManager.NameNotFoundException, Shell.ShellDiedException {
mkdirAndChmodChown(new File(getPsmAppInfo().dataDir, "cache").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid()));
mkdirAndChmodChown(new File(getPsmAppInfo().dataDir, "shared_prefs").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid()));
mkdirAndChmodChown(new File(getPsmAppInfo().dataDir, "files").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid()));
mkdirAndChmodChown(new File(new File(getPsmAppInfo().dataDir, "files"), "kdc").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid()));
mkdirAndChmodChown(new File(getPsmAppInfo().dataDir, "databases").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid()));
mkdirAndChmodChown(new File(Helper.getPsmAppInfo(ctx).dataDir, "cache").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid(ctx)));
mkdirAndChmodChown(new File(Helper.getPsmAppInfo(ctx).dataDir, "shared_prefs").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid(ctx)));
mkdirAndChmodChown(new File(Helper.getPsmAppInfo(ctx).dataDir, "files").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid(ctx)));
mkdirAndChmodChown(new File(new File(Helper.getPsmAppInfo(ctx).dataDir, "files"), "kdc").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid(ctx)));
mkdirAndChmodChown(new File(Helper.getPsmAppInfo(ctx).dataDir, "databases").getAbsolutePath(), 771, String.valueOf(Helper.getPsmUid(ctx)));
}
private void generateWorkaroundSharedPrefs(String sharedPrefsPath, String androidId, int psmUid) throws Exception {
StringEncryptor stringEncryptor = new StringEncryptor(this.ctx, androidId, psmUid);
StringEncryptor stringEncryptor = new StringEncryptor(androidId, psmUid);
String emailAddress = stringEncryptor.encryptString("nopsmdrm@transrights.lgbt");
String password = stringEncryptor.encryptString("password");
@ -170,22 +169,22 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
String signinInfo = new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath();
// generate shared_prefs
writeTxtFile(aidSigninInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
Files.writeTxtFile(aidSigninInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
"<map>\n<string name=\"SignedInUsername\">"+emailAddress+"</string>\n" +
"<boolean name=\"PassSave\" value=\"true\" />\n" +
"<string name=\"Password\">"+password+"</string>\n" +
"<boolean name=\"AutoSignIn\" value=\"true\" />\n" +
"</map>\n");
copyChmodAndChown(aidSigninInfo, signinInfo, 660, String.valueOf(Helper.getPsmUid()));
copyChmodAndChown(aidSigninInfo, signinInfo, 660, String.valueOf(Helper.getPsmUid(ctx)));
}
private void generateSharedPrefs(String sharedPrefsPath, String androidId, int psmUid) throws Exception {
StringEncryptor stringEncryptor = new StringEncryptor(this.ctx, androidId, psmUid);
StringEncryptor stringEncryptor = new StringEncryptor(androidId, psmUid);
// 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));
String emailAddress = stringEncryptor.encryptString(ctx.getResources().getString(R.string.default_email));
String password = stringEncryptor.encryptString(ctx.getResources().getString(R.string.default_password));
String accountId = stringEncryptor.encryptString(String.valueOf(Long.valueOf(ctx.getResources().getString(R.string.default_account_id), 16)));
// get the cache folder for our 'shared_prefs'
String tmpPrefsFolder = ctx.getCacheDir().getAbsolutePath();
@ -202,14 +201,14 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
String r_localLibrary = new File(sharedPrefsPath, "LocalLibrary.xml").getAbsolutePath();
// generate shared_prefs
writeTxtFile(c_signinInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
Files.writeTxtFile(c_signinInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
"<map>\n<string name=\"SignedInUsername\">"+emailAddress+"</string>\n" +
"<boolean name=\"PassSave\" value=\"true\" />\n" +
"<string name=\"Password\">"+password+"</string>\n" +
"<boolean name=\"AutoSignIn\" value=\"true\" />\n" +
"</map>\n");
writeTxtFile(c_psstorePrefs, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
Files.writeTxtFile(c_psstorePrefs, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
"<map>\n" +
"<boolean name=\"key_upgradeDownloadTableForNeedWifi\" value=\"true\" />\n" +
"<string name=\"last_signin_account_id\">"+accountId+"</string>\n" +
@ -230,46 +229,53 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
"<int name=\"key_signinfo\" value=\"2\" />\n" +
"</map>\n");
writeTxtFile(c_runningContentInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
Files.writeTxtFile(c_runningContentInfo, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
"<map>\n<null name=\"title_id\" />\n" +
"<null name=\"next_title_id\" />\n" +
"</map>\n");
writeTxtFile(c_localLibrary, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
Files.writeTxtFile(c_localLibrary, "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
"<map>\n<boolean name=\"notDisplayAgain\" value=\"true\" />\n" +
"<int name=\"sortType\" value=\"0\" />\n" +
"<boolean name=\"isList\" value=\"false\" />\n" +
"</map>\n");
// copy to the correct place and set permissions properly.
copyChmodAndChown(c_signinInfo, r_signinInfo, 660, String.valueOf(Helper.getPsmUid()));
copyChmodAndChown(c_psstorePrefs, r_psstorePrefs, 660, String.valueOf(Helper.getPsmUid()));
copyChmodAndChown(c_runningContentInfo, r_runningContentInfo, 660, String.valueOf(Helper.getPsmUid()));
copyChmodAndChown(c_localLibrary, r_localLibrary, 660, String.valueOf(Helper.getPsmUid()));
copyChmodAndChown(c_signinInfo, r_signinInfo, 660, String.valueOf(Helper.getPsmUid(ctx)));
copyChmodAndChown(c_psstorePrefs, r_psstorePrefs, 660, String.valueOf(Helper.getPsmUid(ctx)));
copyChmodAndChown(c_runningContentInfo, r_runningContentInfo, 660, String.valueOf(Helper.getPsmUid(ctx)));
copyChmodAndChown(c_localLibrary, r_localLibrary, 660, String.valueOf(Helper.getPsmUid(ctx)));
}
private boolean isNoPsmDrmAccountId(String androidId, int psmUid) throws Exception {
StringEncryptor stringEncryptor = new StringEncryptor(androidId, psmUid);
long accountId = Long.parseLong(stringEncryptor.decryptString(Helper.getSharedPrefFromPsm(ctx, "com.playstation.psstore_preferences", "last_signin_account_id"), null));
return accountId == getDefaultAccountId(ctx);
}
private void installSharedPrefs() throws Exception {
// get the path to the shared_prefs folder
String sharedPrefsPath = new File(getPsmAppInfo().dataDir, "shared_prefs").getAbsolutePath();
String sharedPrefsPath = new File(Helper.getPsmAppInfo(ctx).dataDir, "shared_prefs").getAbsolutePath();
String tmpPrefsFolder = ctx.getCacheDir().getAbsolutePath();
File aidSigninFile = new File(tmpPrefsFolder, "AIDSigninInfo.xml");
String androidId = Helper.getAndroidIdOfPsm(ctx);
int psmUid = Helper.getPsmUid(ctx);
// check if signininfo.xml file exists or not ...
boolean signinInfoExist = fileExistRoot(new File(sharedPrefsPath, "SigninInfo.xml").getAbsolutePath());
boolean aidSigninExist = ( aidSigninFile.exists() && Build.VERSION.SDK_INT >= 26 );
boolean isNoPsmDrmAccount = signinInfoExist && isNoPsmDrmAccountId(androidId, psmUid);
if (!signinInfoExist || aidSigninExist) { // if no signininfo file was found
// then generate our own shared_prefs
String androidId = Helper.getAndroidIdOfPsm();
int psmUid = Helper.getPsmUid();
if (!signinInfoExist || isNoPsmDrmAccount) {
// if no SigninInfo.xml file was not found
// or if it was found, but it is using the default account id ...
// then generate our own shared_prefs
if(androidId != null){
generateSharedPrefs(sharedPrefsPath, androidId, psmUid);
aidSigninFile.delete();
}
else {
generateWorkaroundSharedPrefs(sharedPrefsPath, "1234567890abcdef", psmUid);
Helper.killPsm();
Helper.killPsm(ctx);
handler.post(() ->{
new AlertDialog.Builder((Activity)ctx)
.setTitle("Android 8+ android_id...")
@ -308,7 +314,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
}
private void installNoPsmDrmModules() throws Exception {
String nativeLibsFolder = getPsmAppInfo().nativeLibraryDir;
String nativeLibsFolder = getPsmAppInfo(ctx).nativeLibraryDir;
String libPsmKdcFile = new File(nativeLibsFolder, "libpsmkdc_jni.so").getAbsolutePath();
String libDefaultFile = new File(nativeLibsFolder, "libdefault.so").getAbsolutePath();
@ -332,7 +338,7 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
if(Build.VERSION.SDK_INT >= 21){
String cachedLibDefault = new File(ctx.getCacheDir(), "libdefault_real.so").toString();
Root.copyChmodAndChown(realLibDefaultFile, cachedLibDefault, 777, String.valueOf(Helper.getMyUid()));
Root.copyChmodAndChown(realLibDefaultFile, cachedLibDefault, 777, String.valueOf(Helper.getMyUid(ctx)));
patchLibdefault(cachedLibDefault);
Root.copyChmodAndChown(cachedLibDefault, realLibDefaultFile, 755, systemUid);
}
@ -340,36 +346,36 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
}
// unpack the library files ...
unpackResourceToLocationRoot(R.raw.libdefault, libDefaultFile, 755, systemUid);
unpackResourceToLocationRoot(R.raw.libpsmkdc_jni, libPsmKdcFile, 755, systemUid);
unpackResourceToLocationRoot(ctx, R.raw.libdefault, libDefaultFile, 755, systemUid);
unpackResourceToLocationRoot(ctx, R.raw.libpsmkdc_jni, libPsmKdcFile, 755, systemUid);
if(installedToSd) remountRo(folderContainingLibs);
}
private void installDatabase() throws Exception {
String databasesFolder = new File(getPsmAppInfo().dataDir, "databases").getAbsolutePath();
String databasesFolder = new File(getPsmAppInfo(ctx).dataDir, "databases").getAbsolutePath();
String libraryDbFile = new File(databasesFolder, "library.db").getAbsolutePath();
unpackResourceToLocationRoot(R.raw.library, libraryDbFile, 660, String.valueOf(Helper.getPsmUid()));
unpackResourceToLocationRoot(ctx, R.raw.library, libraryDbFile, 660, String.valueOf(Helper.getPsmUid(ctx)));
}
private void installDeviceList() throws PackageManager.NameNotFoundException, IOException, Shell.ShellDiedException {
String cacheFolder = new File(getPsmAppInfo().dataDir, "cache").getAbsolutePath();
String cacheFolder = new File(getPsmAppInfo(ctx).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(Helper.getPsmUid()));
unpackResourceToLocationRoot(ctx, R.raw.device_list2, deviceList2File, 660, String.valueOf(Helper.getPsmUid(ctx)));
// 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(Helper.getPsmUid()));
unpackResourceToLocationRoot(ctx, R.raw.aditional_certified_devices_list, additionalCertsFile, 660, String.valueOf(Helper.getPsmUid(ctx)));
}
@Override
protected void onPreExecute() {
dialog = new ProgressDialog(ctx);
if(!Helper.isNoPsmDrmAlreadyInstalled())
if(!Helper.isNoPsmDrmAlreadyInstalled(ctx))
dialog.setTitle("Installing NoPsmDrm ...");
else
dialog.setTitle("Updating NoPsmDrm ...");
@ -384,9 +390,9 @@ public class NoPsmDrmInstaller extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... voids) {
try {
Helper.killPsm();
Helper.killPsm(ctx);
if (isPsmInstalled()) {
if (isPsmInstalled(ctx)) {
backupPsm();
makeDirs();
installSharedPrefs();

View File

@ -1,17 +1,16 @@
package com.psmreborn.nopsmdrm;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.widget.Button;
import android.widget.TextView;
import com.psmreborn.nopsmdrm.pscertified.PlayStationCertified;
import com.psmreborn.pscertified.PlayStationCertified;
import com.psmreborn.shared.Helper;
import com.psmreborn.shared.Root;
import eu.chainfire.libsuperuser.Shell;
public class Startup extends AsyncTask<Void, Void, Void> {
@ -26,9 +25,9 @@ public class Startup extends AsyncTask<Void, Void, Void> {
if(!PlayStationCertified.isPlaystationCertified(activity.getApplicationContext()))
installButton.setText("Install PS Certify");
else if(!Helper.isPsmInstalled())
else if(!Helper.isPsmInstalled(activity))
installButton.setText("Install PSM");
else if(Helper.isNoPsmDrmAlreadyInstalled())
else if(Helper.isNoPsmDrmAlreadyInstalled(activity))
installButton.setText("Update NoPsmDrm");
else
installButton.setText("Install NoPsmDrm");
@ -53,14 +52,14 @@ public class Startup extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
try {
if(!Shell.SU.available()){
if(!Root.init(ctx)){
wasError = true;
errorMsg = "Unable to get root permission.";
return null;
}
if(Helper.isPsmInstalled() && Helper.getPsmAppPkg().versionCode != 1170) {
if(Helper.isPsmInstalled(ctx) && Helper.getPsmAppPkg(ctx).versionCode != 1170) {
wasError = true;
errorMsg = "PSM Application is installed, but an older version, please update to 1.7.0 (have: "+String.valueOf(Helper.getPsmAppPkg().versionCode)+")";
errorMsg = "PSM Application is installed, but an older version, please update to 1.7.0 (have: "+String.valueOf(Helper.getPsmAppPkg(ctx).versionCode)+")";
return null;
}
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
@ -70,8 +69,7 @@ public class Startup extends AsyncTask<Void, Void, Void> {
}
Permissions.requestPermissions(this.ctx);
Root.setContext(this.ctx);
Helper.killPsm();
Helper.killPsm(ctx);
} catch (Exception e) {
@ -91,7 +89,7 @@ public class Startup extends AsyncTask<Void, Void, Void> {
handler.post(() -> {
statusTV.setText("");
if(Helper.isNoPsmDrmAlreadyInstalled()){
if(Helper.isNoPsmDrmAlreadyInstalled(ctx)){
setPsmInstalled(ctx);
};
updateNames(ctx);

View File

@ -1,4 +1,4 @@
package com.psmreborn.nopsmdrm.pscertified;
package com.psmreborn.pscertified;
public class CertifiedDeviceEntry {

View File

@ -1,4 +1,4 @@
package com.psmreborn.nopsmdrm.pscertified;
package com.psmreborn.pscertified;
public class CertifiedDeviceList {
private String manufacturer = null;

View File

@ -1,4 +1,4 @@
package com.psmreborn.nopsmdrm.pscertified;
package com.psmreborn.pscertified;
import android.content.Context;
import android.os.Build;

View File

@ -1,12 +1,10 @@
package com.psmreborn.nopsmdrm.pscertified;
package com.psmreborn.pscertified;
import static com.psmreborn.nopsmdrm.Root.*;
import static com.psmreborn.shared.Root.*;
import com.psmreborn.nopsmdrm.Helper;
import com.psmreborn.nopsmdrm.MainActivity;
import com.psmreborn.nopsmdrm.NoPsmDrmInstaller;
import com.psmreborn.nopsmdrm.R;
import com.psmreborn.nopsmdrm.Root;
import com.psmreborn.shared.Files;
import com.psmreborn.shared.Root;
import android.app.Activity;
import android.app.AlertDialog;
@ -16,7 +14,6 @@ import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import java.io.File;
@ -32,7 +29,7 @@ public class PsCertificatesInstaller extends AsyncTask<Void, Void, Void> {
public void installPlaystationCertificationMagisk() throws Exception {
File magiskZip = new File(ctx.getCacheDir(), "MagiskCertify.zip");
Root.unpackResource(R.raw.magiskcertify, magiskZip);
Files.unpackResource(ctx, R.raw.magiskcertify, magiskZip);
Root.installMagiskModule(magiskZip.getAbsolutePath());
}
public void installPlaystationCertification() throws IOException, Shell.ShellDiedException {
@ -42,8 +39,8 @@ public class PsCertificatesInstaller extends AsyncTask<Void, Void, Void> {
String psCertifiedPermissionFile = "/system/etc/permissions/com.playstation.playstationcertified.xml";
String psCertifiedJarFile = "/system/framework/com.playstation.playstationcertified.jar";
Root.unpackResourceToLocationRoot(R.raw.ps_certified_permission, psCertifiedPermissionFile, 644, "0");
Root.unpackResourceToLocationRoot(R.raw.ps_certified_jar, psCertifiedJarFile, 644, "0");
Root.unpackResourceToLocationRoot(ctx, R.raw.ps_certified_permission, psCertifiedPermissionFile, 644, "0");
Root.unpackResourceToLocationRoot(ctx, R.raw.ps_certified_jar, psCertifiedJarFile, 644, "0");
// make it read-only again.
remountRo("/system");

View File

@ -1,10 +1,12 @@
package com.psmreborn.nopsmdrm;
package com.psmreborn.shared;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.os.Handler;
import com.psmreborn.nopsmdrm.Startup;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -40,19 +42,7 @@ public class Downloader {
.setPositiveButton("Ok",null).show();
}
private static void copyTo(InputStream inpStream, OutputStream outStream) throws IOException {
byte[] buffer = new byte[8192];
int totalRead;
while(true){
totalRead = inpStream.read(buffer, 0, buffer.length);
if(totalRead == -1)
break;
outStream.write(buffer, 0, totalRead);
}
outStream.flush();
}
private static void download(String uri, String dstFile) throws IOException {
URL url = new URL(uri);
@ -62,7 +52,7 @@ public class Downloader {
InputStream input = new BufferedInputStream(url.openStream(), 8192);
OutputStream output = new FileOutputStream(dstFile);
copyTo(input, output);
Files.copyTo(input, output);
output.close();
input.close();
}
@ -81,7 +71,7 @@ public class Downloader {
new Thread(() -> {
Handler handler = new Handler(ctx.getMainLooper());
Helper.killPsm();
Helper.killPsm(ctx);
try {
download(url, saveLocation);
handler.post(() -> {dialog.setTitle("Installing "+filename+"...");});
@ -118,7 +108,7 @@ public class Downloader {
new Thread(() -> {
Handler handler = new Handler(ctx.getMainLooper());
Helper.killPsm();
Helper.killPsm(ctx);
try {
download(url, saveLocation);
} catch (IOException e) {

View File

@ -0,0 +1,44 @@
package com.psmreborn.shared;
import android.content.Context;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Files {
public static void unpackResource(Context ctx, int resourceId, File outputFile) throws IOException {
Log.i("ROOT", "Unpacking resource to : " + outputFile);
InputStream resourceStream = ctx.getResources().openRawResource(resourceId);
FileOutputStream fs = new FileOutputStream(outputFile, false);
copyTo(resourceStream, fs);
fs.close();
resourceStream.close();
}
public static void writeTxtFile(String txtFile, String txt) throws IOException {
Log.i("ROOT", "Writing: " + txtFile);
FileWriter txtStream = new FileWriter(txtFile);
txtStream.write(txt);
txtStream.close();
}
public static void copyTo(InputStream inpStream, OutputStream outStream) throws IOException {
byte[] buffer = new byte[8192];
int totalRead;
while(true){
totalRead = inpStream.read(buffer, 0, buffer.length);
if(totalRead == -1)
break;
outStream.write(buffer, 0, totalRead);
}
outStream.flush();
}
}

View File

@ -1,16 +1,17 @@
package com.psmreborn.nopsmdrm;
package com.psmreborn.shared;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import com.psmreborn.nopsmdrm.R;
import com.rosstonovsky.abxutils.BinaryXmlPullParser;
import org.xmlpull.v1.XmlPullParser;
@ -23,17 +24,12 @@ import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import eu.chainfire.libsuperuser.Shell;
public class Helper {
private static Context ctx;
public static void setContext(Context context){
ctx = context.getApplicationContext();
}
public static boolean isNoPsmDrmAlreadyInstalled() {
private static final String psmAppPackage = "com.playstation.psstore";
public static boolean isNoPsmDrmAlreadyInstalled(Context ctx) {
try {
if(new File(getPsmAppInfo().nativeLibraryDir, "libdefault_real.so").exists()){
if(new File(getPsmAppInfo(ctx).nativeLibraryDir, "libdefault_real.so").exists()){
return true;
}
} catch (PackageManager.NameNotFoundException e) {
@ -41,9 +37,26 @@ public class Helper {
}
return false;
}
public static boolean isPsmInstalled(){
public static long getDefaultAccountId(Context ctx){
return Long.valueOf(ctx.getResources().getString(R.string.default_account_id), 16);
}
public static String getSharedPrefFromPsm(Context ctx, String prefName, String prefKey) throws Exception {
String psmSharedPrefs = new File(Helper.getPsmAppInfo(ctx).dataDir, "shared_prefs").getAbsolutePath();
String psmPrefFile = new File(psmSharedPrefs, prefName+".xml").getAbsolutePath();
String mySharedPrefs = new File(Helper.getAppInfo(ctx, ctx.getPackageName()).dataDir, "shared_prefs").getAbsolutePath();
String myPrefFile = new File(mySharedPrefs, prefName+".xml").getAbsolutePath();
Root.mkdirAndChmodChown(mySharedPrefs, 771, String.valueOf(Helper.getMyUid(ctx)));
Root.copyChmodAndChown(psmPrefFile, myPrefFile, 660, String.valueOf(Helper.getMyUid(ctx)));
SharedPreferences pref = ctx.getSharedPreferences(prefName, 0);
return pref.getString(prefKey, null);
}
public static boolean isPsmInstalled(Context ctx){
try {
ctx.getPackageManager().getApplicationInfo("com.playstation.psstore", 0);
ctx.getPackageManager().getApplicationInfo(psmAppPackage, 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
@ -91,13 +104,13 @@ public class Helper {
}
@SuppressLint("HardwareIds")
public static String getAndroidIdOfPsm() throws Exception {
public static String getAndroidIdOfPsm(Context ctx) throws Exception {
if(Build.VERSION.SDK_INT >= 26){
String[] files = Root.findFiles("/data/system", "settings_ssaid.xml");
File ssaidCacheFile = new File(ctx.getCacheDir(), "settings_ssaid.xml");
for(String ssaidFile : files){
Root.copyChmodAndChown(ssaidFile, ssaidCacheFile.getAbsolutePath(), 777, String.valueOf(getAppInfo(ctx.getPackageName()).uid));
Root.copyChmodAndChown(ssaidFile, ssaidCacheFile.getAbsolutePath(), 777, String.valueOf(Helper.getMyUid(ctx)));
try{
FileInputStream stream = new FileInputStream(ssaidCacheFile);
return parseSsaidBinary(stream);
@ -115,7 +128,7 @@ public class Helper {
}
}
public static int getMyUid() {
public static int getMyUid(Context ctx) {
try{
ApplicationInfo myAppInfo = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), 0);
if(myAppInfo != null) {
@ -125,9 +138,9 @@ public class Helper {
catch (PackageManager.NameNotFoundException e) { };
return 0;
}
public static int getPsmUid() {
public static int getPsmUid(Context ctx) {
try{
ApplicationInfo psmAppInfo = ctx.getPackageManager().getApplicationInfo("com.playstation.psstore", 0);
ApplicationInfo psmAppInfo = ctx.getPackageManager().getApplicationInfo(psmAppPackage, 0);
if(psmAppInfo != null) {
return psmAppInfo.uid;
}
@ -136,23 +149,23 @@ public class Helper {
return 0;
}
public static void killPsm(){
public static void killPsm(Context ctx){
ActivityManager am = (ActivityManager) ctx.getSystemService(Activity.ACTIVITY_SERVICE);
if (am != null) {
am.killBackgroundProcesses("com.playstation.psstore");
am.killBackgroundProcesses(psmAppPackage);
}
}
public static PackageInfo getPackageInfo(String pkg) throws PackageManager.NameNotFoundException {
public static PackageInfo getPackageInfo(Context ctx, String pkg) throws PackageManager.NameNotFoundException {
return ctx.getPackageManager().getPackageInfo(pkg, 0);
}
public static ApplicationInfo getAppInfo(String pkg) throws PackageManager.NameNotFoundException {
public static ApplicationInfo getAppInfo(Context ctx, String pkg) throws PackageManager.NameNotFoundException {
return ctx.getPackageManager().getApplicationInfo(pkg, 0);
}
public static PackageInfo getPsmAppPkg() throws PackageManager.NameNotFoundException {
return getPackageInfo("com.playstation.psstore");
public static PackageInfo getPsmAppPkg(Context ctx) throws PackageManager.NameNotFoundException {
return Helper.getPackageInfo(ctx,psmAppPackage);
}
public static ApplicationInfo getPsmAppInfo() throws PackageManager.NameNotFoundException {
return getAppInfo("com.playstation.psstore");
public static ApplicationInfo getPsmAppInfo(Context ctx) throws PackageManager.NameNotFoundException {
return Helper.getAppInfo(ctx,psmAppPackage);
}
@SuppressLint("SimpleDateFormat")
public static String getDateTime(){

View File

@ -0,0 +1,24 @@
package com.psmreborn.shared;
import android.util.Log;
public class Logger {
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
private static String bytesToHex(byte[] bytes) {
if(bytes == null) return "(nulL)";
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static void logText(String description, String text){
Log.i("NoPsmDrmApp", description + " = "+text);
}
public static void logBytes(String description, byte[] data){
Log.i("NoPsmDrmApp", description + " = " + bytesToHex(data));
}
}

View File

@ -1,9 +1,11 @@
package com.psmreborn.nopsmdrm;
package com.psmreborn.shared;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import com.psmreborn.nopsmdrm.R;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
@ -17,7 +19,6 @@ import eu.chainfire.libsuperuser.Shell;
public class Root {
private static String busyboxBinary = null;
private static Context ctx = null;
public static void installMagiskModule(String magiskModuleFile) throws Exception {
int res = 0;
@ -213,50 +214,23 @@ public class Root {
}
}
private static 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();
}
public static void unpackResourceToLocationRoot(int resourceId, String outputDir, int chmod, String chown) throws IOException, Shell.ShellDiedException {
public static void unpackResourceToLocationRoot(Context ctx, int resourceId, String outputDir, int chmod, String chown) throws IOException, Shell.ShellDiedException {
Log.i("ROOT", "Unpacking resource and root copying to : " + outputDir);
File tmpFile = File.createTempFile("tmp", "file", ctx.getCacheDir());
tmpFile.createNewFile();
unpackResource(resourceId, tmpFile);
Files.unpackResource(ctx, resourceId, tmpFile);
moveChmodAndChown(tmpFile.getAbsolutePath(), outputDir, chmod, chown);
}
public static void unpackResource(int resourceId, File outputFile) throws IOException {
Log.i("ROOT", "Unpacking resource to : " + outputFile);
InputStream resourceStream = ctx.getResources().openRawResource(resourceId);
FileOutputStream fs = new FileOutputStream(outputFile, false);
copyTo(resourceStream, fs);
fs.close();
resourceStream.close();
}
public static void writeTxtFile(String txtFile, String txt) throws IOException {
Log.i("ROOT", "Writing: " + txtFile);
FileWriter txtStream = new FileWriter(txtFile);
txtStream.write(txt);
txtStream.close();
}
private static void setupBusyBox() throws IOException {
private static void setupBusyBox(Context ctx) throws IOException {
Log.i("ROOT","Creating busybox binary");
File tmpFile = new File(ctx.getCacheDir(), "busybox");
if(!tmpFile.exists()) {
tmpFile.createNewFile();
if(tmpFile.setExecutable(true,false)) {
unpackResource(R.raw.busybox, tmpFile);
Files.unpackResource(ctx, R.raw.busybox, tmpFile);
}
else {
throw new IOException("failed to extract busybox binary.");
@ -266,9 +240,11 @@ public class Root {
busyboxBinary = tmpFile.getAbsolutePath();
}
public static void setContext(Context context) throws IOException {
ctx = context.getApplicationContext();
Shell.setRedirectDeprecated(false);
setupBusyBox();
public static boolean init(Context ctx) throws IOException {
if(Shell.SU.available()){
setupBusyBox(ctx);
return true;
}
return false;
}
}

View File

@ -1,4 +1,4 @@
package com.psmreborn.nopsmdrm;
package com.psmreborn.shared;
import android.content.Context;
import android.util.Base64;
@ -19,12 +19,10 @@ 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 final Context ctx;
private String android_id = null;
private int psm_uid = 0;
StringEncryptor(Context ctx, String androidId, int psmUid) {
this.ctx = ctx;
public StringEncryptor(String androidId, int psmUid) {
this.android_id = androidId;
this.psm_uid = psmUid;
}
@ -45,7 +43,9 @@ public class StringEncryptor {
return null;
}
public String decryptString(String str) {
public String decryptString(String str, String def) {
if(str == null) return null;
byte[] data = decodeBase64(str);
byte[] arrayData = Arrays.copyOf(data, data.length - 2);
@ -55,12 +55,13 @@ public class StringEncryptor {
return new String(decryptedData, "UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e("STRINGENCRYPTOR", e.toString());
return null;
return def;
}
}
return null;
return def;
}
public byte[] decrypt(byte[] input){
if(input == null) return null;
try {
Cipher cipher = generateKeyCipher(StringEncryptor.salt, StringEncryptor.iv, Cipher.DECRYPT_MODE);
if (cipher != null) {
@ -74,6 +75,7 @@ public class StringEncryptor {
}
public byte[] encrypt(byte[] input){
if(input == null) return null;
try {
Cipher cipher = generateKeyCipher(StringEncryptor.salt, StringEncryptor.iv, Cipher.ENCRYPT_MODE);
if (cipher != null) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,3 +1,8 @@
<resources>
<string name="app_name">NoPsmDrm</string>
<string name="name_nopsmdrm">NoPsmDrm</string>
<string name="name_nops1drm">NoPs1Drm</string>
<string name="default_email">nopsmdrm@transrights.lgbt</string>
<string name="default_password">password</string>
<string name="default_online_id">TransgenderPS1</string>
<string name="default_account_id">0123456789abcdef</string>
</resources>

View File

@ -17,3 +17,4 @@ rootProject.name = "nopsmdrm"
include ':app'
include ':libsuperuser'
include ':libABX'
//include ':libNpTicket'