android - pie - Proteger las compras en la aplicación de Freedom Hack
android pie (3)
He buscado exhaustivamente en este sitio, así como en otros, en busca de respuestas y no he encontrado ninguna real.
Mi pregunta es qué hace exactamente el Freedom Hack (que permite a los usuarios comprar en la aplicación sin pagar). Es decir, qué parte del proceso se altera. He encontrado esta lista de aplicaciones para las que funciona el pirateo, y algunas de las entradas con fecha de este mes, lo que significa que aún no se ha corregido por completo. Las respuestas que he visto fueron "verificar la aplicación en su servidor", pero si el hack, por ejemplo, altera la función de verificación de firma de Java.Security, por lo que siempre devuelve verdadero, entonces agregar mi propia firma en el servidor no lo haría. ayuda mucho
Entonces, agregar mi propia firma en el servidor no ayudaría mucho.
Eso no es correcto, la firma que utiliza "Libertad" no es válida y la identificación del pedido también es inválida.
Lo que hice para garantizar que mi aplicación sea segura es:
Enviar
isPurchaseValid(myPurchase.getSignature(), myPurchase.getOriginalJson())
a mi servidor para verificar allí y funciona con compras reales, pero la libertad siempre falla.En el servidor compruebo si la firma coincide.
Si coincide, me comunico con "API de Google Play Android Developer API de Google> androidpublisher.inapppurchases.get" para verificar que exista la compra y que devuelva mi carga de desarrollador.
Luego uso la carga útil del desarrollador para asegurarme de que esta compra es para este usuario específico y no para otro usuario y este usuario me está enviando sus datos.
PD: la carga útil del desarrollador es una String
que establece antes de que se realice la compra desde su aplicación de Android, debe ser algo exclusivo de su usuario.
Tal vez sea mucho trabajo, pero asegura que nadie comprará tus cosas con libertad y tendrá éxito.
Lo único que no puedo hacer es no permitir que la libertad tenga un efecto en mi solicitud, por ejemplo, la gente en Path hizo algo que no sé lo que hizo que Freedom no tenga ningún efecto.
Estoy usando algo como esto, sé que no es una buena solución en comparación con una verificación remota del servidor para su firma. Estoy comprobando si la aplicación Freedom está instalada, si es así no estoy abriendo mi aplicación.
@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
if(isHackerAppIsntalled())
finish();
}
private boolean isHackerAppInstalled() {
final PackageManager pm = getApplication().getPackageManager();
List<ApplicationInfo> packages = pm
.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo packageInfo : packages) {
String packageName = packageInfo.packageName;
if (packageName.contains("cc.madkite.freedom")
|| packageName.contains("madkite.freedom")) {
return true;
}
}
return false;
}
No sé si el autor todavía sigue este tema o no. Pero dediqué algún tiempo a descubrir (buscar en Google) cómo funciona la libertad y cómo evitarla (hasta que actualicen la forma en que funciona la libertad) en mi proyecto y cómo funciona. Mi implementación es realmente simple y no es necesario verificarla enviando la solicitud al servidor (lo que afecta el rendimiento y requiere más esfuerzo para implementarlo).
La implementación actual de freedom es que reemplazará (redirigirá) todas las llamadas de método de java.security.Signature.verify(byte[])
al método jni de freedom, que a su vez simplemente devolverá true (or 1)
.
Eche un vistazo a java.security.Signature.verify(byte[])
:
public final boolean verify(byte[] signature) throws SignatureException {
if (state != VERIFY) {
throw new SignatureException("Signature object is not initialized properly");
}
return engineVerify(signature);
}
Aquí, el método engineVerify
es un método abstract protected
que se define primero en java.security.SignatureSpi
( Signature extends SignatureSpi
). OK, eso es suficiente, porque ya no puedo creer el java.security.Signature.verify(byte[])
, engineVerify
método engineVerify
directamente. Para hacer eso, necesitamos usar la reflexión. Modifique el método de verify
de IABUtil/Security
desde:
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (!sig.verify(Base64.decode(signature))) {
Log.e(TAG, "Signature verification failed.");
return false;
}
return true;
} catch (...) {
...
}
return false;
}
A:
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
Signature sig;
try {
sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
Method verify = java.security.SignatureSpi.class.getDeclaredMethod("engineVerify", byte[].class);
verify.setAccessible(true);
Object returnValue = verify.invoke(sig, Base64.decode(signature));
if (!(Boolean)returnValue) {
Log.e(TAG, "Signature verification failed.");
return false;
}
return true;
} catch (...) {
...
}
return false;
}
Eso es simple pero funciona con la implementación actual de libertad hasta que actualicen su algoritmo en el futuro.