📜 ⬆️ ⬇️

What makes an owl in ZeroNights 2017 Crackme # 3?


ZeroNights 2017 Crackme # 3 is a fairly simple task, but, nevertheless, there are some interesting moments and an owl in it.


Under the cut - disassembly, decompiling, pull request to IntelliJ IDEA and a single debugger launch.


The task file is available at https://events.kaspersky.com/crackme/files/crackme3.zip
The Android application app-release.apk is lonely in the archive. The APK is, like so much in the modern world, a zip archive. We get and unpack it .


Inside there is a lot of garbage from one of the standard Android application templates in /res , some native libraries in /lib , files with strange names in /assets and, most importantly, the application code in classes.dex . Convert classes.dex to a jar file with dex2jar .


The code inside is organized into several packages:



Keeping the original package names is a rather dubious practice for crackme, but this is only easier for us. It is reasonable to assume that the main logic of the application is in the package com.kaspersky.zeronights2017.nightwatcher . Moreover, that is where the MainActivity class is MainActivity .


We decompile and study it:


MainActivity.java
 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Build.VERSION; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.googlecode.tesseract.android.TessBaseAPI; import java.io.File; public class MainActivity extends Activity { public static EditText a; public static EditText b; public static String c; private String d; private final String e; public MainActivity() { this.d = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q; this.e = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.d); } private void a() { Bitmap var1 = BitmapFactory.decodeResource(this.getResources(), 2131099746); TessBaseAPI var2; if (VERSION.SDK_INT > 19) { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a(); } else { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a().split("\n")[0]; } } private void a(File var1, String var2) { if (!var1.exists() && var1.mkdirs()) { this.a(var2); } if (var1.exists() && !(new File(this.d + this.e + var2)).exists()) { this.a(var2); } } private void a(String param1) { // $FF: Couldn't be decompiled } protected void onCreate(Bundle var1) { super.onCreate(var1); this.requestWindowFeature(1); this.getWindow().setFlags(1024, 1024); this.setContentView(2131296283); Button var2 = (Button)this.findViewById(2131165217); if ((new \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(this)).\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(this, 2131361827, 1).show(); this.finish(); } var2.setOnClickListener(new OnClickListener() { public void onClick(View var1) { MainActivity.a = (EditText)MainActivity.this.findViewById(2131165230); MainActivity.b = (EditText)MainActivity.this.findViewById(2131165280); MainActivity.this.a(); if (!MainActivity.a.getText().toString().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q) && !MainActivity.b.getText().toString().toUpperCase().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q)) { if (\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(MainActivity.this, 2131361829, 1).show(); } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } }); } } uFEFF \ uFEFF (\ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF.d); // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Build.VERSION; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.googlecode.tesseract.android.TessBaseAPI; import java.io.File; public class MainActivity extends Activity { public static EditText a; public static EditText b; public static String c; private String d; private final String e; public MainActivity() { this.d = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q; this.e = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.d); } private void a() { Bitmap var1 = BitmapFactory.decodeResource(this.getResources(), 2131099746); TessBaseAPI var2; if (VERSION.SDK_INT > 19) { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a(); } else { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a().split("\n")[0]; } } private void a(File var1, String var2) { if (!var1.exists() && var1.mkdirs()) { this.a(var2); } if (var1.exists() && !(new File(this.d + this.e + var2)).exists()) { this.a(var2); } } private void a(String param1) { // $FF: Couldn't be decompiled } protected void onCreate(Bundle var1) { super.onCreate(var1); this.requestWindowFeature(1); this.getWindow().setFlags(1024, 1024); this.setContentView(2131296283); Button var2 = (Button)this.findViewById(2131165217); if ((new \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(this)).\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(this, 2131361827, 1).show(); this.finish(); } var2.setOnClickListener(new OnClickListener() { public void onClick(View var1) { MainActivity.a = (EditText)MainActivity.this.findViewById(2131165230); MainActivity.b = (EditText)MainActivity.this.findViewById(2131165280); MainActivity.this.a(); if (!MainActivity.a.getText().toString().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q) && !MainActivity.b.getText().toString().toUpperCase().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q)) { if (\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(MainActivity.this, 2131361829, 1).show(); } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } }); } } \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Build.VERSION; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.googlecode.tesseract.android.TessBaseAPI; import java.io.File; public class MainActivity extends Activity { public static EditText a; public static EditText b; public static String c; private String d; private final String e; public MainActivity() { this.d = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q; this.e = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.d); } private void a() { Bitmap var1 = BitmapFactory.decodeResource(this.getResources(), 2131099746); TessBaseAPI var2; if (VERSION.SDK_INT > 19) { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a(); } else { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a().split("\n")[0]; } } private void a(File var1, String var2) { if (!var1.exists() && var1.mkdirs()) { this.a(var2); } if (var1.exists() && !(new File(this.d + this.e + var2)).exists()) { this.a(var2); } } private void a(String param1) { // $FF: Couldn't be decompiled } protected void onCreate(Bundle var1) { super.onCreate(var1); this.requestWindowFeature(1); this.getWindow().setFlags(1024, 1024); this.setContentView(2131296283); Button var2 = (Button)this.findViewById(2131165217); if ((new \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(this)).\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(this, 2131361827, 1).show(); this.finish(); } var2.setOnClickListener(new OnClickListener() { public void onClick(View var1) { MainActivity.a = (EditText)MainActivity.this.findViewById(2131165230); MainActivity.b = (EditText)MainActivity.this.findViewById(2131165280); MainActivity.this.a(); if (!MainActivity.a.getText().toString().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q) && !MainActivity.b.getText().toString().toUpperCase().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q)) { if (\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(MainActivity.this, 2131361829, 1).show(); } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } }); } } (\ uFEFF \ uFEFF! MainActivity.a.getText () \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF.q) &&! // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Build.VERSION; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.googlecode.tesseract.android.TessBaseAPI; import java.io.File; public class MainActivity extends Activity { public static EditText a; public static EditText b; public static String c; private String d; private final String e; public MainActivity() { this.d = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q; this.e = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.d); } private void a() { Bitmap var1 = BitmapFactory.decodeResource(this.getResources(), 2131099746); TessBaseAPI var2; if (VERSION.SDK_INT > 19) { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a(); } else { this.d = this.getFilesDir() + \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.e; var2 = new TessBaseAPI(); this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.i); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f); var2.a(var1); c = var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.j); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.g); var2.a(var1); c = c + var2.a().split("\n")[0]; this.a(new File(this.d + this.e), \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.k); var2.a(this.d, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h); var2.a(var1); c = c + var2.a().split("\n")[0]; } } private void a(File var1, String var2) { if (!var1.exists() && var1.mkdirs()) { this.a(var2); } if (var1.exists() && !(new File(this.d + this.e + var2)).exists()) { this.a(var2); } } private void a(String param1) { // $FF: Couldn't be decompiled } protected void onCreate(Bundle var1) { super.onCreate(var1); this.requestWindowFeature(1); this.getWindow().setFlags(1024, 1024); this.setContentView(2131296283); Button var2 = (Button)this.findViewById(2131165217); if ((new \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(this)).\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(this, 2131361827, 1).show(); this.finish(); } var2.setOnClickListener(new OnClickListener() { public void onClick(View var1) { MainActivity.a = (EditText)MainActivity.this.findViewById(2131165230); MainActivity.b = (EditText)MainActivity.this.findViewById(2131165280); MainActivity.this.a(); if (!MainActivity.a.getText().toString().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q) && !MainActivity.b.getText().toString().toUpperCase().matches(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.q)) { if (\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF()) { Toast.makeText(MainActivity.this, 2131361829, 1).show(); } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } else { Toast.makeText(MainActivity.this, 2131361828, 1).show(); } } }); } } 

For ease of reading in this and subsequent listings, all symbols with codes greater than 127 are replaced with unicode escape sequences of the \uXXXX .


Some of the names of classes, fields, and methods were obfuscated, some methods could not be decompiled, but the onCreate() method is simple and straightforward. From it, we learn that we have at least two input fields and one button, when clicked, one of the messages is displayed to the user, depending on the result returned by the method with the unreadable name.


Focusing on the number of characters in the class and method names (34 and 62, respectively), we find this method:


Class that validates the key entered
 // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; class \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF { public static boolean \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF() { boolean var0; if ( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.t / \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.r * \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f - \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h == MainActivity.b.getText().toString().toUpperCase().length() && \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( MainActivity.c.getBytes() ) + MainActivity.a.getText().toString() ) ).equals(MainActivity.b.getText().toString().toUpperCase()) ) { var0 = true; } else { var0 = false; } return var0; } } \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF \ uFEFF // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.kaspersky.zeronights2017.nightwatcher; class \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF { public static boolean \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF() { boolean var0; if ( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.t / \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.r * \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.f - \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.h == MainActivity.b.getText().toString().toUpperCase().length() && \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF .\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF( MainActivity.c.getBytes() ) + MainActivity.a.getText().toString() ) ).equals(MainActivity.b.getText().toString().toUpperCase()) ) { var0 = true; } else { var0 = false; } return var0; } } 

At this could be finished.


The length of the value from the second input field is checked. A prefix is ​​added to the value from the first input field, probably constant, some hash is calculated from the resulting line. The value of the latter is compared with the value of the second input field, converted to upper case. Everything.


It is enough to slightly modify the code in the apk-file, adding the logging of the calculated hash before comparing, and the crackme is solved. But it’s pretty boring and doesn’t pull the article, so we’ll go the other way.


Other way


Instead, let us analyze the logic of the work and write the key generator.


First you should get rid of obfuscation of identifiers. Some of them are just single letters, and some are sequences of different lengths from \uFEFF . Most often this symbol is used as a byte order mark at the beginning of text files in one of the unicode encodings. But it has another, outdated, value - zero-width no-break space (ZWNBSP) or, if in Russian, a space of zero width. It is thanks to this property in the open file dialog that we see several “no-name” class files.



By the way, a curious fact: From the point of view of the Java Language Specification, the \uFEFF symbol does not stand out in any way and can be part of the identifier from the second position. But the compiler implementation from Oracle JDK / Open JDK has its own view on some issues and when compiling such characters will be silently cut from the identifier and will not fall into the resulting class file. We will not find a word about this in JLS, information about this is only in the javac source code and bugtracker: JDK-7144981 .


Fernflower, a decompiler running as part of IntelliJ IDEA , has support for automatic renaming of identifiers. To do this, when calling the decompiler from the command line, you must specify the parameter -ren=1 .


But when trying to decompile, we are in a fiasco, the decompiler does not consider such identifiers incorrect. It's time to look inside and find out the reason.


This is how the method looked, whether it is necessary to rename the identifier:


 @Override public boolean toBeRenamed(Type elementType, String className, String element, String descriptor) { String value = elementType == Type.ELEMENT_CLASS ? className : element; return value == null || value.length() <= 2 || Character.isDigit(value.charAt(0)) || KEYWORDS.contains(value) || elementType == Type.ELEMENT_CLASS && ( RESERVED_WINDOWS_NAMESPACE.contains(value.toLowerCase(Locale.US)) || value.length() > 255 - ".class".length()); } 

Rename identifiers that are too short, too long, starting with a digit, or matching a keyword or reserved file names on Windows.


We replace the check with the number in the first position to check the correctness of the identifier according to JLS and the absence of these remarkable “ignorable chars” in it, we make out a pull request .


Obfuscation is defeated, but there are methods that could not be decompiled. Let's do them.


Some assembly language


For assembly and disassembly, we will use asmtools from OpenJDK.


Let's start with the only problematic method in MainActivity :


MainActivity.jasm - void a (String)
 private Method a:"(Ljava/lang/String;)V" stack 4 locals 8 { aload_1; astore 4; try t0; new class java/lang/StringBuilder; astore 5; endtry t0; aload_1; astore 4; try t1; aload 5; invokespecial Method java/lang/StringBuilder."<init>":"()V"; endtry t1; aload_1; astore 4; try t2; aload 5; aload_0; getfield Field d:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_0; getfield Field e:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_1; invokestatic Method \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF."\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF":"(Ljava/lang/String;)Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; invokevirtual Method java/lang/StringBuilder.toString:"()Ljava/lang/String;"; astore 5; endtry t2; aload_1; astore 4; try t3; aload_0; invokevirtual Method getAssets:"()Landroid/content/res/AssetManager;"; astore 6; endtry t3; aload_1; astore 4; try t4; new class java/lang/StringBuilder; astore 7; endtry t4; aload_1; astore 4; try t5; aload 7; invokespecial Method java/lang/StringBuilder."<init>":"()V"; endtry t5; aload_1; astore 4; try t6; aload 6; aload 7; aload_0; getfield Field e:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_1; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; invokevirtual Method java/lang/StringBuilder.toString:"()Ljava/lang/String;"; invokevirtual Method android/content/res/AssetManager.open:"(Ljava/lang/String;)Ljava/io/InputStream;"; astore_1; endtry t6; aload_1; astore 4; try t7; new class java/io/FileOutputStream; astore 7; endtry t7; aload_1; astore 4; try t8; aload 7; aload 5; invokespecial Method java/io/FileOutputStream."<init>":"(Ljava/lang/String;)V"; endtry t8; aload_1; astore 4; try t9; getstatic Field \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.x:"I"; newarray byte; astore 6; endtry t9; L125: aload_1; astore 4; try t10; aload_1; aload 6; invokevirtual Method java/io/InputStream.read:"([B)I"; istore_3; endtry t10; aload_1; astore 4; try t11; iload_3; getstatic Field \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.b:"I"; if_icmpeq L202; endtry t11; aload_1; astore 4; try t12; getstatic Field \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.a:"I"; istore_2; endtry t12; L152: iload_2; iload_3; if_icmpge L179; aload_1; astore 4; try t13; aload 6; iload_2; aload 6; iload_2; baload; getstatic Field \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.l:"I"; ixor; i2b; bastore; endtry t13; iinc 2, 1; goto L152; L179: aload_1; astore 4; try t14; aload 7; aload 6; getstatic Field \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.a:"I"; iload_3; invokevirtual Method java/io/OutputStream.write:"([BII)V"; endtry t14; goto L125; catch t0 java/io/IOException; catch t1 java/io/IOException; catch t2 java/io/IOException; catch t3 java/io/IOException; catch t4 java/io/IOException; catch t5 java/io/IOException; catch t6 java/io/IOException; catch t7 java/io/IOException; catch t8 java/io/IOException; catch t9 java/io/IOException; catch t10 java/io/IOException; catch t11 java/io/IOException; catch t12 java/io/IOException; catch t13 java/io/IOException; catch t14 java/io/IOException; catch t15 java/io/IOException; catch t16 java/io/IOException; catch t17 java/io/IOException; catch t18 java/io/IOException; catch t19 java/io/IOException; catch t20 java/io/IOException; catch t21 java/io/IOException; catch t22 java/io/IOException; catch t23 java/io/IOException; astore_1; aload_1; invokevirtual Method java/io/IOException.printStackTrace:"()V"; L201: return; L202: aload_1; astore 4; try t15; aload 7; invokevirtual Method java/io/OutputStream.flush:"()V"; endtry t15; aload_1; astore 4; try t16; aload 7; invokevirtual Method java/io/OutputStream.close:"()V"; endtry t16; aload_1; astore 4; try t17; aload_1; invokevirtual Method java/io/InputStream.close:"()V"; endtry t17; aload_1; astore 4; try t18; new class java/io/File; astore_1; endtry t18; aload_1; astore 4; try t19; aload_1; aload 5; invokespecial Method java/io/File."<init>":"(Ljava/lang/String;)V"; endtry t19; aload_1; astore 4; try t20; aload_1; invokevirtual Method java/io/File.exists:"()Z"; ifne L201; endtry t20; aload_1; astore 4; try t21; new class java/io/FileNotFoundException; astore_1; endtry t21; aload_1; astore 4; try t22; aload_1; invokespecial Method java/io/FileNotFoundException."<init>":"()V"; endtry t22; aload_1; astore 4; try t23; aload_1; athrow; endtry t23; } 

We immediately see a bunch of try blocks, dividing a single catch block with the commonplace e.printStackTrace(); hidden in the code somewhere in between.


It looks too complicated for a code that has not yet shown any attempts at serious obfuscation. Maybe dex2jar got it wrong when converting?


It's time to take apktool and look at the original Dalvik bytecode before converting it to Java bytecode. At the same time and get the resources.


Suspicions were confirmed, when converting, not everything went smoothly. Although the catch is indeed common, the try block only turns out to be two:


MainActivity.smali - void a (String)
 .method private a(Ljava/lang/String;)V .locals 8 .param p1, "arg0" # Ljava/lang/String; .prologue :try_start_0 new-instance v1, Ljava/lang/StringBuilder; invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V iget-object v2, p0, Lcom/kaspersky/zeronights2017/nightwatcher/MainActivity;->d:Ljava/lang/String; invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 iget-object v2, p0, Lcom/kaspersky/zeronights2017/nightwatcher/MainActivity;->e:Ljava/lang/String; invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 invoke-static {p1}, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(Ljava/lang/String;)Ljava/lang/String; move-result-object v2 invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v1 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v2 invoke-virtual {p0}, Lcom/kaspersky/zeronights2017/nightwatcher/MainActivity;->getAssets()Landroid/content/res/AssetManager; move-result-object v1 new-instance v3, Ljava/lang/StringBuilder; invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V iget-object v4, p0, Lcom/kaspersky/zeronights2017/nightwatcher/MainActivity;->e:Ljava/lang/String; invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v3 invoke-virtual {v3, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; move-result-object v3 invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; move-result-object v3 invoke-virtual {v1, v3}, Landroid/content/res/AssetManager;->open(Ljava/lang/String;)Ljava/io/InputStream; move-result-object p1 new-instance v3, Ljava/io/FileOutputStream; invoke-direct {v3, v2}, Ljava/io/FileOutputStream;-><init>(Ljava/lang/String;)V sget v1, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->x:I new-array v4, v1, [B :goto_0 invoke-virtual {p1, v4}, Ljava/io/InputStream;->read([B)I move-result v5 sget v1, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->b:I if-eq v5, v1, :cond_2 sget v1, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->a:I :goto_1 if-ge v1, v5, :cond_0 aget-byte v6, v4, v1 sget v7, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->l:I xor-int/2addr v6, v7 int-to-byte v6, v6 aput-byte v6, v4, v1 add-int/lit8 v1, v1, 0x1 goto :goto_1 :cond_0 sget v1, Lcom/kaspersky/zeronights2017/nightwatcher/\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF;->a:I invoke-virtual {v3, v4, v1, v5}, Ljava/io/OutputStream;->write([BII)V :try_end_0 .catch Ljava/io/IOException; {:try_start_0 .. :try_end_0} :catch_0 goto :goto_0 :catch_0 move-exception v1 move-object v0, p1 .end local p1 # "arg0":Ljava/lang/String; .local v0, "arg0":Ljava/lang/String; move-object p1, v1 .end local v0 # "arg0":Ljava/lang/String; .restart local p1 # "arg0":Ljava/lang/String; invoke-virtual {p1}, Ljava/io/IOException;->printStackTrace()V :cond_1 return-void :cond_2 :try_start_1 invoke-virtual {v3}, Ljava/io/OutputStream;->flush()V invoke-virtual {v3}, Ljava/io/OutputStream;->close()V invoke-virtual {p1}, Ljava/io/InputStream;->close()V new-instance p1, Ljava/io/File; invoke-direct {p1, v2}, Ljava/io/File;-><init>(Ljava/lang/String;)V invoke-virtual {p1}, Ljava/io/File;->exists()Z move-result v1 if-nez v1, :cond_1 new-instance p1, Ljava/io/FileNotFoundException; invoke-direct {p1}, Ljava/io/FileNotFoundException;-><init>()V throw p1 :try_end_1 .catch Ljava/io/IOException; {:try_start_1 .. :try_end_1} :catch_0 .end method 

We return to the listing obtained with the help of asmtools jdis MainActivity.class and slightly modify it. The body of a catch block is moved to the end of the method body, all the try blocks are deleted, and instead of them we add a new one that starts where the first one started and ends where the last try block ended in the original listing.


MainActivity.jasm - fixed void a (String)
 private Method a:"(Ljava/lang/String;)V" stack 4 locals 8 { aload_1; astore 4; try t0; new class java/lang/StringBuilder; astore 5; aload_1; astore 4; aload 5; invokespecial Method java/lang/StringBuilder."<init>":"()V"; aload_1; astore 4; aload 5; aload_0; getfield Field d:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_0; getfield Field e:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_1; invokestatic Method "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF"."\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF":"(Ljava/lang/String;)Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; invokevirtual Method java/lang/StringBuilder.toString:"()Ljava/lang/String;"; astore 5; aload_1; astore 4; aload_0; invokevirtual Method getAssets:"()Landroid/content/res/AssetManager;"; astore 6; aload_1; astore 4; new class java/lang/StringBuilder; astore 7; aload_1; astore 4; aload 7; invokespecial Method java/lang/StringBuilder."<init>":"()V"; aload_1; astore 4; aload 6; aload 7; aload_0; getfield Field e:"Ljava/lang/String;"; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; aload_1; invokevirtual Method java/lang/StringBuilder.append:"(Ljava/lang/String;)Ljava/lang/StringBuilder;"; invokevirtual Method java/lang/StringBuilder.toString:"()Ljava/lang/String;"; invokevirtual Method android/content/res/AssetManager."open":"(Ljava/lang/String;)Ljava/io/InputStream;"; astore_1; aload_1; astore 4; new class java/io/FileOutputStream; astore 7; aload_1; astore 4; aload 7; aload 5; invokespecial Method java/io/FileOutputStream."<init>":"(Ljava/lang/String;)V"; aload_1; astore 4; getstatic Field "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF".x:"I"; newarray byte; astore 6; L125: aload_1; astore 4; aload_1; aload 6; invokevirtual Method java/io/InputStream.read:"([B)I"; istore_3; aload_1; astore 4; iload_3; getstatic Field "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF".b:"I"; if_icmpeq L202; aload_1; astore 4; getstatic Field "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF".a:"I"; istore_2; L152: iload_2; iload_3; if_icmpge L179; aload_1; astore 4; aload 6; iload_2; aload 6; iload_2; baload; getstatic Field "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF".l:"I"; ixor; i2b; bastore; iinc 2, 1; goto L152; L179: aload_1; astore 4; aload 7; aload 6; getstatic Field "\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF".a:"I"; iload_3; invokevirtual Method java/io/OutputStream.write:"([BII)V"; goto L125; L202: aload_1; astore 4; aload 7; invokevirtual Method java/io/OutputStream.flush:"()V"; aload_1; astore 4; aload 7; invokevirtual Method java/io/OutputStream.close:"()V"; aload_1; astore 4; aload_1; invokevirtual Method java/io/InputStream.close:"()V"; aload_1; astore 4; new class java/io/File; astore_1; aload_1; astore 4; aload_1; aload 5; invokespecial Method java/io/File."<init>":"(Ljava/lang/String;)V"; aload_1; astore 4; aload_1; invokevirtual Method java/io/File.exists:"()Z"; ifne L201; aload_1; astore 4; new class java/io/FileNotFoundException; astore_1; aload_1; astore 4; aload_1; invokespecial Method java/io/FileNotFoundException."<init>":"()V"; aload_1; astore 4; aload_1; athrow; endtry t0; catch t0 java/io/IOException; astore_1; aload_1; invokevirtual Method java/io/IOException.printStackTrace:"()V"; L201: return; } 

class- asmtools jasm MainActivity.jasm .


asmtools : , unicode escape .


:


 --- a/src/org/openjdk/asmtools/jasm/Parser.java +++ b/src/org/openjdk/asmtools/jasm/Parser.java @@ -416,6 +416,12 @@ case STRINGVAL: v = scanner.stringValue; scanner.scan(); + if (uncond || (scanner.token == Token.FIELD)) { + if ((!v.contains("/")) // class identifier doesn't contain "/" + && (!v.contains("["))){ // class identifier doesn't contain "[" + v = pkgPrefix + v; // add package + } + } return pool.FindCellAsciz(v); // Some identifiers might coincide with token names. // these should be OK to use as identifier names. 

:


MainActivity::a(String)
 private void a(String var1) { try { StringBuilder var5 = new StringBuilder(); String var12 = var5.append(this.d).append(this.e).append(\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(var1)).toString(); AssetManager var6 = this.getAssets(); StringBuilder var7 = new StringBuilder(); InputStream var9 = var6.open(var7.append(this.e).append(var1).toString()); FileOutputStream var14 = new FileOutputStream(var12); byte[] var13 = new byte[\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.x]; while(true) { int var3 = var9.read(var13); if (var3 == \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.b) { var14.flush(); var14.close(); var9.close(); File var10 = new File(var12); if (!var10.exists()) { FileNotFoundException var11 = new FileNotFoundException(); throw var11; } break; } for(int var2 = \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.a; var2 < var3; ++var2) { var13[var2] = (byte)(var13[var2] ^ \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.l); } var14.write(var13, \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF.a, var3); } } catch (IOException var8) { var8.printStackTrace(); } } 

. , XOR- , .


.
try - catch -, catch - , , , , try {} catch {} .


 .method public static \uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF\uFEFF(Ljava/lang/String;)Ljava/lang/String; .locals 7 .param p0, "\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff\ufeff" # Ljava/lang/String; .prologue :try_start_0 //      java.security.MessageDigest :cond_0 invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; :try_end_0 .catch Ljava/security/NoSuchAlgorithmException; {:try_start_0 .. :try_end_0} :catch_0 .catch Ljava/io/UnsupportedEncodingException; {:try_start_0 .. :try_end_0} :catch_1 move-result-object p0 :goto_1 return-object p0 :catch_0 move-exception p0 :goto_2 invoke-virtual {p0}, Ljava/lang/Exception;->printStackTrace()V const/4 p0, 0x0 goto :goto_1 :catch_1 move-exception p0 goto :goto_2 .end method 

( android.* , . .) , .



, , .


, class- -ren=1 . 32 . , , , .


GitHub


Android Studio.


MainActivity , resource id . apktool res/values/public.xml , res/values/strings.xml res/values/ids.xml .


, id «email», — «serial», onCreate() «Your Android device is rooted!», method_1297() owl.png :



, EditText emailEditText serialEditText , :


 protected void onCreate(Bundle var1) { super.onCreate(var1); this.requestWindowFeature(1); this.getWindow().setFlags(1024, 1024); this.setContentView(0x7f09001b); Button var2 = (Button)this.findViewById(0x7f070021); if ((new class_108(this)).method_946()) { Toast.makeText(this, "Your Android device is rooted!", 1).show(); this.finish(); } var2.setOnClickListener(new OnClickListener() { public void onClick(View var1) { MainActivity.emailEditText = (EditText)MainActivity.this.findViewById(0x7f07002e); MainActivity.serialEditText = (EditText)MainActivity.this.findViewById(0x7f070060); MainActivity.this.method_1297(); if (!MainActivity.emailEditText.getText().toString().matches(class_170.field_1366) && !MainActivity.serialEditText.getText().toString().toUpperCase().matches(class_170.field_1366)) { if (class_46.method_502()) { Toast.makeText(MainActivity.this, "Congratulations! You did it!", 1).show(); } else { Toast.makeText(MainActivity.this, "Login Failed.", 1).show(); } } else { Toast.makeText(MainActivity.this, "Login Failed.", 1).show(); } } }); } 

GitHub


Root check


. class_108 , method_350 class_33 com.scottyab.rootbeer .


 class class_108 { // $FF: renamed from: a android.content.Context private final Context field_937; public class_108(Context var1) { this.field_937 = var1; } public boolean method_946() { return (new class_33(this.field_937)).method_350(); } } 

GitHub , «su» «busybox». com.scottyab.rootbeer.RootBeer::isRooted()


, , if , class_108 , com.scottyab.rootbeer , .


GitHub



onCreate() .
, class_170::field_1366 , class_46::method_502() . -.


class_170 .


:


class_170
 // $FF: renamed from: q java.lang.String public static String field_1366 = method_1453(method_1452(method_1455(method_1457(method_1451(method_1456(method_1454(method_1458("")))))))); // $FF: renamed from: r java.lang.String public static String field_1367 = method_1453(method_1452(method_1455(method_1457(method_1451(method_1456(method_1454(method_1458("#81]A")))))))); // ... public static String method_1451(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 55); } return new String(var2); } public static String method_1452(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 22); } return new String(var2); } public static String method_1453(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 11); } return new String(var2); } public static String method_1454(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 77); } return new String(var2); } public static String method_1455(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 33); } return new String(var2); } public static String method_1456(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 66); } return new String(var2); } public static String method_1457(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 44); } return new String(var2); } public static String method_1458(String var0) { char[] var2 = var0.toCharArray(); for(int var1 = 0; var1 < var2.length; ++var1) { var2[var1] = (char)(var2[var1] ^ 88); } return new String(var2); } 

, main() :


class_170::main()
 public static void main(String... args) { System.out.print("package com.kaspersky.zeronights2017.nightwatcher;\n\n"); System.out.print("public class class_170 {\n\n"); System.out.printf(" public static final String field_1350 = \"%s\";%n", field_1350.replaceAll("\n", "\\\\n")); System.out.printf(" public static final String field_1351 = \"%s\";%n", field_1351); System.out.printf(" public static final String field_1352 = \"%s\";%n", field_1352); System.out.printf(" public static final String field_1353 = \"%s\";%n", field_1353); System.out.printf(" public static final String field_1354 = \"%s\";%n", field_1354); System.out.printf(" public static final String field_1355 = \"%s\";%n", field_1355); System.out.printf(" public static final String field_1356 = \"%s\";%n", field_1356); System.out.printf(" public static final String field_1357 = \"%s\";%n", field_1357); System.out.printf(" public static final String field_1358 = \"%s\";%n", field_1358); System.out.printf(" public static final String field_1359 = \"%s\";%n", field_1359); System.out.printf(" public static final String field_1360 = \"%s\";%n", field_1360); System.out.printf(" public static final String field_1361 = \"%s\";%n", field_1361); System.out.printf(" public static final String field_1362 = \"%s\";%n", field_1362); System.out.printf(" public static final String field_1363 = \"%s\";%n", field_1363); System.out.printf(" public static final String field_1364 = \"%s\";%n", field_1364); System.out.printf(" public static final String field_1365 = \"%s\";%n", field_1365); System.out.printf(" public static final String field_1366 = \"%s\";%n", field_1366); System.out.printf(" public static final String field_1367 = \"%s\";%n", field_1367); System.out.printf(" public static final String field_1368 = \"%s\";%n", field_1368); System.out.print("\n}\n\n"); } 

GitHub


:


class_170
 package com.kaspersky.zeronights2017.nightwatcher; public class class_170 { public static final String field_1350 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam et maximus eros. Mauris laoreet molestie semper. Aliquam erat volutpat. Sed euismod neque ac ante viverra pellentesque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras efficitur ac augue a mattis. Nunc facilisis elementum lobortis. Ut vehicula malesuada pharetra. Pellentesque a interdum eros, nec pulvinar sem. Morbi dapibus in quam ut ullamcorper. Vivamus volutpat vehicula condimentum.\n\nNullam commodo vestibulum cursus. Aliquam semper ligula ac tortor rutrum molestie. Vivamus nec orci auctor quam vehicula tempor et id neque. Suspendisse fermentum velit ut ipsum pellentesque hendrerit. Fusce convallis aliquam ante non elementum. Donec at scelerisque lacus, eu eleifend nulla. Pellentesque congue nisi in dolor dignissim, non lobortis neque luctus. Mauris ac cursus turpis. Phasellus finibus facilisis justo, convallis mattis lorem lobortis et. Nam ac interdum est. Etiam ac molestie ligula. Maecenas vel purus a odio accumsan venenatis. Nunc ligula dui, pharetra id arcu laoreet, mollis semper leo. Phasellus id magna molestie, semper risus nec, vehicula sem.\n\nDonec eget nisl purus. Phasellus non nisi felis. Aliquam ut odio sit amet neque euismod vulputate non vel mauris. Suspendisse sit amet ligula sed leo condimentum vulputate convallis eu dui. Vestibulum tortor lacus, maximus quis tincidunt a, pretium sed lacus. Maecenas porta dui nisi, vel molestie tortor luctus at. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam odio ante, sollicitudin sed diam quis, ultricies pretium ex. Proin nisi arcu, tristique id leo et, lacinia semper nisi. Fusce posuere lacus at ex pretium venenatis. Sed porta nibh mauris, ut vestibulum nulla aliquam non. Nunc id tortor non nisi blandit volutpat. Phasellus malesuada hendrerit orci a semper. Nam a risus ac arcu dictum imperdiet.\n\nCras ut risus eget leo ultricies dictum vitae et enim. Aliquam erat volutpat. Fusce ut porttitor nisi. Praesent vel pulvinar orci. Aenean ac libero sed tortor sagittis tristique commodo in velit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam eu enim orci. Nullam consectetur lobortis tellus, ac facilisis ex dapibus sed.\n\nAliquam mollis eget turpis id vestibulum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque vitae lectus non metus convallis aliquam. Donec rutrum tincidunt quam, iaculis gravida nisl dictum id. Donec malesuada dapibus magna tristique convallis. Curabitur at turpis sed tellus accumsan condimentum. Nam accumsan nisi a ex hendrerit, in sagittis turpis feugiat. Morbi congue et est eu venenatis. Phasellus erat dui, rutrum sit amet fringilla sit amet, imperdiet in nulla. Quisque laoreet neque ac augue sodales, at mollis magna mollis. Mauris nec consectetur purus, quis aliquam leo. Sed lobortis magna efficitur vehicula finibus."; public static final String field_1351 = "ABCDEFGHIJKLONMPQRSTVUWXYZabcdefghijlkmnopqrstuvwxyz5193406782+/"; public static final String field_1352 = "0123456789ABCDEF"; public static final String field_1353 = "dGUzc9RhdGEv"; public static final String field_1354 = "/whoami/"; public static final String field_1355 = "who"; public static final String field_1356 = "am"; public static final String field_1357 = "i"; public static final String field_1358 = "d9hvLnRyYWkuZWRlYXRh"; public static final String field_1359 = "YW5udHJhaW0kZGRhdGE="; public static final String field_1360 = "aS05cmFpbmUlZGF5YQ=="; public static final String field_1361 = "[^"; public static final String field_1362 = "=]"; public static final String field_1363 = "="; public static final String field_1364 = "AA"; public static final String field_1365 = "A"; public static final String field_1366 = ""; public static final String field_1367 = "SHA-1"; public static final String field_1368 = "UTF-8"; } 

GitHub


BASE64


- , «Inline all and remove the field».


class_87 : "AA" , "A" , "=" , 64- class_170::field_1351 , "dGUzc9RhdGEv" , "d9hvLnRyYWkuZWRlYXRh" , "YW5udHJhaW0kZGRhdGE=" "aS05cmFpbmUlZGF5YQ==" , class_87::method_802() . , class_87 BASE64 encoder/decoder . , class_170::field_1351 U V , .


, , . , IDEA/Android Studio . .


class_170 .


GitHub


BASE64-, , .


: field_1181 MainActivity MainActivity::method_1300() . , .


 private void method_1300(String resourceName) { try { StringBuilder var5 = new StringBuilder(); String var12 = var5.append(this.field_1180).append(this.field_1181).append(CustomBase64.decode(resourceName)).toString(); AssetManager var6 = this.getAssets(); StringBuilder var7 = new StringBuilder(); InputStream var9 = var6.open(var7.append(this.field_1181).append(resourceName).toString()); FileOutputStream var14 = new FileOutputStream(var12); // ... 

:


 private void method_1299(File destDir, String resourceName, String outputFileName) { if (!destDir.exists() && destDir.mkdirs()) { this.method_1300(resourceName, outputFileName); } if (destDir.exists() && !(new File(this.field_1180 + this.field_1181 + resourceName)).exists()) { this.method_1300(resourceName, outputFileName); } } private void method_1300(String resourceName, String outputFileName) { try { String var12 = this.field_1180 + this.field_1181 + outputFileName; AssetManager assets = this.getAssets(); InputStream inputStream = assets.open(this.field_1181 + resourceName); FileOutputStream outputStream = new FileOutputStream(var12); // ... 

, . , class_170 :


 public static void main(String... args) { System.out.printf("\"%s\"\t\"%s\"%n", "dGUzc9RhdGEv" , decode("dGUzc9RhdGEv" )); System.out.printf("\"%s\"\t\"%s\"%n", "d9hvLnRyYWkuZWRlYXRh", decode("d9hvLnRyYWkuZWRlYXRh")); System.out.printf("\"%s\"\t\"%s\"%n", "YW5udHJhaW0kZGRhdGE=", decode("YW5udHJhaW0kZGRhdGE=")); System.out.printf("\"%s\"\t\"%s\"%n", "aS05cmFpbmUlZGF5YQ==", decode("aS05cmFpbmUlZGF5YQ==")); } 

:


dGUzc9RhdGEvtessdata/
d9hvLnRyYWkuZWRlYXRhwho.traineddata
YW5udHJhaW0kZGRhdGE=am.traineddata
aS05cmFpbmUlZGF5YQ==i.traineddata

, , , .


GitHub



, class_44 , .


, class_170 , , . , method_465() :


 public static int field_368 = ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( method_465(0, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0) + method_465(0, 0) ) * method_465(1, 0) * method_465(1, 0); // ... public static int method_465(int var0, int var1) { return var0 + var1; } 

, — . «Inline all and remove the method» , :


 public static int field_368 = ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 0 + 0 + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0) + 0 + 0 ) * (1 + 0) * (1 + 0); 

, IntelliJ IDEA/Android Studio . Alt-Enter , «Compute constant value of ...». — .


, . :


 public static int field_368 = 0; 

class_44 , .


GitHub



class_46::method_502() . , , , :


 class class_46 { public static boolean method_502() { boolean var0; if (2949 / 240 * 4 - 8 == MainActivity.serialEditText.getText().toString().toUpperCase().length() && class_135.method_1132( class_135.method_1133( CustomBase64.encode(MainActivity.field_1179.getBytes()) + MainActivity.emailEditText.getText().toString() ) ).equals(MainActivity.serialEditText.getText().toString().toUpperCase())) { var0 = true; } else { var0 = false; } return var0; } } 

:


 class SerialValidator { public static boolean validateSerial() { String email = MainActivity.emailEditText.getText().toString(); String serial = MainActivity.serialEditText.getText().toString().toUpperCase(); String expectedSerial = class_135.method_1132( class_135.method_1133( CustomBase64.encode(MainActivity.field_1179.getBytes()) + email ) ); return (serial.length() == 40) && serial.equals(expectedSerial); } } 

GitHub


40 , . . , crackme , .


, «email» , BASE64. class_135::method_1133() , . , SHA-1 .


 public static String method_1132(String var0) { try { MessageDigest var2 = MessageDigest.getInstance("SHA-1"); StringBuilder var3 = new StringBuilder(var2.digest(var0.getBytes("UTF-8")).length); for(int var1 = 0; var1 < var2.digest(var0.getBytes("UTF-8")).length; ++var1) { var3 .append(HEX_DIGITS.charAt(var2.digest(var0.getBytes("UTF-8"))[var1] >> 4 & 15)) .append(HEX_DIGITS.charAt(var2.digest(var0.getBytes("UTF-8"))[var1] & 15)); } var0 = var3.toString(); return var0; } catch (UnsupportedEncodingException | NoSuchAlgorithmException var4) { var4.printStackTrace(); return null; } } 

, MainActivity::field_1179 .



MainActivity::method_1297() :


 private void method_1297() { // 0x7f060062: type="drawable" name="owl" Bitmap var1 = BitmapFactory.decodeResource(this.getResources(), 0x7f060062); TessBaseAPI var2; if (VERSION.SDK_INT > 19) { this.field_1180 = this.getFilesDir() + field_1354; var2 = new TessBaseAPI(); this.method_1299(new File(this.field_1180 + this.field_1181), "d9hvLnRyYWkuZWRlYXRh", "who.traineddata"); var2.method_997(this.field_1180, field_1355); var2.method_996(var1); field_1179 = var2.method_995(); this.method_1299(new File(this.field_1180 + this.field_1181), "YW5udHJhaW0kZGRhdGE=", "am.traineddata"); var2.method_997(this.field_1180, field_1356); var2.method_996(var1); field_1179 = field_1179 + var2.method_995(); this.method_1299(new File(this.field_1180 + this.field_1181), "aS05cmFpbmUlZGF5YQ==", "i.traineddata"); var2.method_997(this.field_1180, field_1357); var2.method_996(var1); field_1179 = field_1179 + var2.method_995(); } else { this.field_1180 = this.getFilesDir() + field_1354; var2 = new TessBaseAPI(); this.method_1299(new File(this.field_1180 + this.field_1181), "d9hvLnRyYWkuZWRlYXRh", "who.traineddata"); var2.method_997(this.field_1180, field_1355); var2.method_996(var1); field_1179 = var2.method_995().split("\n")[0]; this.method_1299(new File(this.field_1180 + this.field_1181), "YW5udHJhaW0kZGRhdGE=", "am.traineddata"); var2.method_997(this.field_1180, field_1356); var2.method_996(var1); field_1179 = field_1179 + var2.method_995().split("\n")[0]; this.method_1299(new File(this.field_1180 + this.field_1181), "aS05cmFpbmUlZGF5YQ==", "i.traineddata"); var2.method_997(this.field_1180, field_1357); var2.method_996(var1); field_1179 = field_1179 + var2.method_995().split("\n")[0]; } } 

, - , field_1179 .


, (VERSION.SDK_INT <= 19) , else - .


. com.googlecode.tesseract.android.TessBaseAPI . native- Android- OCR- Tesseract .


, tess-two . , API .


TessBaseAPI , , native-, GitHub. . , . , . crackme , .


Result:


 private void computeSalt() { // 0x7f060062: type="drawable" name="owl" Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), 0x7f060062); TessBaseAPI tessBaseAPI; if (VERSION.SDK_INT > 19) { this.dataPath = this.getFilesDir() + DIRNAME_WHOAMI; tessBaseAPI = new TessBaseAPI(); this.method_1299(new File(this.dataPath + this.DIRNAME_TESSDATA), "d9hvLnRyYWkuZWRlYXRh", "who.traineddata"); tessBaseAPI.init(this.dataPath, LANGANAME_WHO); tessBaseAPI.setImage(bitmap); SALT = tessBaseAPI.getUTF8Text(); this.method_1299(new File(this.dataPath + this.DIRNAME_TESSDATA), "YW5udHJhaW0kZGRhdGE=", "am.traineddata"); tessBaseAPI.init(this.dataPath, LANGANAME_AM); tessBaseAPI.setImage(bitmap); SALT = SALT + tessBaseAPI.getUTF8Text(); this.method_1299(new File(this.dataPath + this.DIRNAME_TESSDATA), "aS05cmFpbmUlZGF5YQ==", "i.traineddata"); tessBaseAPI.init(this.dataPath, LANGANAME_I); tessBaseAPI.setImage(bitmap); SALT = SALT + tessBaseAPI.getUTF8Text(); } else { // ... } } 

, . , "who" , "am" , "i" , crackme MainActivity::method_1299() .


GitHub


MainActivity::method_1299() :


 private void method_1299(File destDir, String resourceName, String outputFileName) { if (!destDir.exists() && destDir.mkdirs()) { this.method_1300(resourceName, outputFileName); } if (destDir.exists() && !(new File(this.dataPath + this.DIRNAME_TESSDATA + resourceName)).exists()) { this.method_1300(resourceName, outputFileName); } } 

, if , - , , , , if . , , — .


, , , Tesseract Android.


, :


 private void checkFile(File dir) { //directory does not exist, but we can successfully create it if (!dir.exists()&& dir.mkdirs()){ copyFiles(); } //The directory exists, but there is no data file in it if(dir.exists()) { String datafilepath = datapath+ "/tessdata/eng.traineddata"; File datafile = new File(datafilepath); if (!datafile.exists()) { copyFiles(); } } } 

MainActivity::method_1300() , xor 0x14 , try-catch .


, :



*.traineddata GitHub



, , , . Tesseract 4.xx, *.traineddata .


:



, 0 DPI, . , «Raw line» , DPI .


 $ tesseract --tessdata-dir ./tessdata -psm 13 -l who owl.png stdout Warning. Invalid resolution 0 dpi. Using 70 instead. 7F6B45B $ tesseract --tessdata-dir ./tessdata -psm 13 -l am owl.png stdout Warning. Invalid resolution 0 dpi. Using 70 instead. 6E8AC25D6A9 $ tesseract --tessdata-dir ./tessdata -psm 13 -li owl.png stdout Warning. Invalid resolution 0 dpi. Using 70 instead. 9E7DB916E40FD0 

*.traineddata , — , « ».


"7F6B45B6E8AC25D6A99E7DB916E40FD0" SALT , com.googlecode.tesseract , , .


GitHub


Keygen


.


K2017Crackme3Keygen , E-Mail, crackme, SerialValidator::validateSerial() :


 import com.kaspersky.zeronights2017.nightwatcher.CustomBase64; import com.kaspersky.zeronights2017.nightwatcher.MainActivity; import com.kaspersky.zeronights2017.nightwatcher.class_135; public class K2017Crackme3Keygen { public static void main(String... args) { System.out.print("E-Mail: "); String email = System.console().readLine(); String expectedSerial = class_135.method_1132( class_135.method_1133( CustomBase64.encode(MainActivity.SALT.getBytes()) + email ) ); System.out.printf("Serial: %s", expectedSerial); } } 

CustomBase64.encode(MainActivity.SALT.getBytes()) TRUE_SALT , , :


K2017Crackme3Keygen.java
 import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class K2017Crackme3Keygen { public static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam et maximus eros. Mauris laoreet molestie semper. Aliquam erat volutpat. Sed euismod neque ac ante viverra pellentesque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras efficitur ac augue a mattis. Nunc facilisis elementum lobortis. Ut vehicula malesuada pharetra. Pellentesque a interdum eros, nec pulvinar sem. Morbi dapibus in quam ut ullamcorper. Vivamus volutpat vehicula condimentum.\n\nNullam commodo vestibulum cursus. Aliquam semper ligula ac tortor rutrum molestie. Vivamus nec orci auctor quam vehicula tempor et id neque. Suspendisse fermentum velit ut ipsum pellentesque hendrerit. Fusce convallis aliquam ante non elementum. Donec at scelerisque lacus, eu eleifend nulla. Pellentesque congue nisi in dolor dignissim, non lobortis neque luctus. Mauris ac cursus turpis. Phasellus finibus facilisis justo, convallis mattis lorem lobortis et. Nam ac interdum est. Etiam ac molestie ligula. Maecenas vel purus a odio accumsan venenatis. Nunc ligula dui, pharetra id arcu laoreet, mollis semper leo. Phasellus id magna molestie, semper risus nec, vehicula sem.\n\nDonec eget nisl purus. Phasellus non nisi felis. Aliquam ut odio sit amet neque euismod vulputate non vel mauris. Suspendisse sit amet ligula sed leo condimentum vulputate convallis eu dui. Vestibulum tortor lacus, maximus quis tincidunt a, pretium sed lacus. Maecenas porta dui nisi, vel molestie tortor luctus at. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam odio ante, sollicitudin sed diam quis, ultricies pretium ex. Proin nisi arcu, tristique id leo et, lacinia semper nisi. Fusce posuere lacus at ex pretium venenatis. Sed porta nibh mauris, ut vestibulum nulla aliquam non. Nunc id tortor non nisi blandit volutpat. Phasellus malesuada hendrerit orci a semper. Nam a risus ac arcu dictum imperdiet.\n\nCras ut risus eget leo ultricies dictum vitae et enim. Aliquam erat volutpat. Fusce ut porttitor nisi. Praesent vel pulvinar orci. Aenean ac libero sed tortor sagittis tristique commodo in velit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam eu enim orci. Nullam consectetur lobortis tellus, ac facilisis ex dapibus sed.\n\nAliquam mollis eget turpis id vestibulum. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque vitae lectus non metus convallis aliquam. Donec rutrum tincidunt quam, iaculis gravida nisl dictum id. Donec malesuada dapibus magna tristique convallis. Curabitur at turpis sed tellus accumsan condimentum. Nam accumsan nisi a ex hendrerit, in sagittis turpis feugiat. Morbi congue et est eu venenatis. Phasellus erat dui, rutrum sit amet fringilla sit amet, imperdiet in nulla. Quisque laoreet neque ac augue sodales, at mollis magna mollis. Mauris nec consectetur purus, quis aliquam leo. Sed lobortis magna efficitur vehicula finibus."; public static final String ALPHABET = "ABCDEFGHIJKLONMPQRSTVUWXYZabcdefghijlkmnopqrstuvwxyz5193406782+/"; public static final String HEX_DIGITS = "0123456789ABCDEF"; public static final String TRUE_SALT = "N5Y9QjQ1QjZFMEFDOjUENlE0MVV3REI0OTZFNDBGRDA="; public static void main(String... args) { System.out.print("E-Mail: "); String email = System.console().readLine(); String expectedSerial = calculateSha1Hex(method_1133(TRUE_SALT + email)); System.out.printf("Serial: %s", expectedSerial); } private static String method_1131(String s1, String s2) { StringBuilder stringBuilder = new StringBuilder(""); for(int i = 0; i < 256; i++) { stringBuilder.append(String.valueOf(s1.charAt(i) ^ s2.charAt(i % s2.length()))); } return encodeCustomBase64(stringBuilder.toString().getBytes()); } public static String method_1133(String s) { StringBuilder stringBuilder = new StringBuilder(""); for(int i = 0; i < 256; i++) { int var2 = ((i << 4 | i) << 240 * i) % 2000000 % 2949; stringBuilder.append(LOREM_IPSUM.substring(var2, 1 + var2)); } return method_1131(stringBuilder.toString(), s); } public static String calculateSha1Hex(String s) { try { byte[] bytes = s.getBytes(StandardCharsets.UTF_8); MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); StringBuilder stringBuilder = new StringBuilder(messageDigest.digest(bytes).length); for(int i = 0; i < messageDigest.digest(bytes).length; i++) { stringBuilder .append(HEX_DIGITS.charAt(messageDigest.digest(bytes)[i] >> 4 & 0xf)) .append(HEX_DIGITS.charAt(messageDigest.digest(bytes)[i] & 0xf)); } return stringBuilder.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static String encodeCustomBase64(byte[] bytes) { char[] alphabetChars = ALPHABET.toCharArray(); StringBuilder stringBuilder = new StringBuilder(); int var1 = 0; int var2; for(int i = 0; i < bytes.length; i += 3) { var2 = (bytes[i] & 0xff) << 16 & 0xffffff; if (1 + i < bytes.length) { var2 |= (bytes[1 + i] & 0xff) << 8; } else { var1++; } if (2 + i < bytes.length) { var2 |= bytes[2 + i] & 0xff; } else { var1++; } int var4 = var2; for(var2 = 0; var2 < 4 - var1; var2++) { stringBuilder.append(alphabetChars[(0xfc0000 & var4) >> 18]); var4 <<= 6; } } for(var2 = 0; var2 < var1; var2++) { stringBuilder.append("="); } return stringBuilder.toString(); } } 

.


GitHub


Check


Habrahabr .
crackme «email», .


 $ java K2017Crackme3Keygen E-Mail: Habrahabr Serial: 3C882D5EC917F92D6637F986BA6DAE02CD7E49E3 

crackme:



, .


')

Source: https://habr.com/ru/post/351142/


All Articles