A week ago Norton Security started to find Trojan horse (Trojan.Gen.NPE.2) in file R.class located:
app\build\intermediates\transforms\instantrun\debug\folders\1\5\main\android\support\v4\ r.class
and
app\build\intermediates\transforms\instantrunslicer\debug\folders\1\5\slice_2\android\support\v4\ r.class
Link to virustotal.com scan: https://www.virustotal.com/pl/file/282f4e09c102cd93c2f849c9fe9ed570188f5a03395ab84d2457a7c64d7acb1c/analysis/1499458308/
And the code:
package android.support.v4;
import com.android.tools.fd.runtime.IncrementalChange;
import com.android.tools.fd.runtime.InstantReloadException;
public final class R {
public static final long serialVersionUID = 830508538663712626L;
public R() {
IncrementalChange var1 = $change;
if(var1 != null) {
Object[] var10001 = (Object[])var1.access$dispatch("init$args.([Landroid/support/v4/R;[Ljava/lang/Object;)Ljava/lang/Object;", new Object[]{null, new Object[0]});
Object[] var2 = (Object[])var10001[0];
this(var10001, (InstantReloadException)null);
var2[0] = this;
var1.access$dispatch("init$body.(Landroid/support/v4/R;[Ljava/lang/Object;)V", var2);
} else {
super();
}
}
R(Object[] var1, InstantReloadException var2) {
String var3 = (String)var1[1];
switch(var3.hashCode()) {
case -1968665286:
super();
return;
case -71951640:
this();
return;
default:
throw new InstantReloadException(String.format("String switch could not find \'%s\' with hashcode %s in %s", new Object[]{var3, Integer.valueOf(var3.hashCode()), "android/support/v4/R"}));
}
}
}
Is it false alarm?
I cant add exclusions in Symantec on my laptop as its company's laptop and excluding applications, files or folders feature is deactivated. So in order to get going i have disabled instant run to get going else i can't even install app on my emulator and get stuck with installation errors.
You can disable instant run by unchecking instant run in Settings in Android Studio.
NOTE: This is just workaround and not permanent solution.
You can report this false positive to Symantec and have them fix it.
https://submit.symantec.com/false_positive/
Related
One user reported that my app fails to request directory access when selecting a folder via the ACTION_OPEN_DOCUMENT_TREE intent.
For some reason it does not show my application, instead "Anonymous":
Translated: "Allow Anonymous to access files in Camera. This will let Anonymous access current and future content stored in Camera".
The user has a MIUI 12 with Android 11 on a Mi Note 10 lite.
I have the same just with a Mi Note 10, no issues ofc.
Checked the Android source code:
https://android.googlesource.com/platform/packages/apps/DocumentsUI/+/refs/heads/master/src/com/android/documentsui/picker/ConfirmFragment.java#82
case TYPE_OEPN_TREE:
final Uri treeUri = mTarget.getTreeDocumentUri();
final BaseActivity activity = (BaseActivity) getActivity();
final String target = activity.getCurrentTitle();
final String text = getString(R.string.open_tree_dialog_title,
**getCallingAppName**(getActivity()), target);
message = getString(R.string.open_tree_dialog_message,
**getCallingAppName**(getActivity()), target);
builder.setTitle(text);
builder.setMessage(message);
builder.setPositiveButton(
R.string.allow,
(DialogInterface dialog, int id) -> {
pickResult.increaseActionCount();
mActions.finishPicking(treeUri);
});
break;
#NonNull
public static String getCallingAppName(Activity activity) {
final String anonymous = activity.getString(R.string.anonymous_application);
final String packageName = getCallingPackageName(activity);
if (TextUtils.isEmpty(packageName)) {
return anonymous;
}
final PackageManager pm = activity.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo(packageName, 0);
} catch (final PackageManager.NameNotFoundException e) {
return anonymous;
}
CharSequence result = pm.getApplicationLabel(ai);
return TextUtils.isEmpty(result) ? anonymous : result.toString();
}
public static String getCallingPackageName(Activity activity) {
String callingPackage = activity.getCallingPackage();
// System apps can set the calling package name using an extra.
try {
ApplicationInfo info =
activity.getPackageManager().getApplicationInfo(callingPackage, 0);
if (isSystemApp(info) || isUpdatedSystemApp(info)) {
final String extra = activity.getIntent().getStringExtra(
Intent.EXTRA_PACKAGE_NAME);
if (extra != null && !TextUtils.isEmpty(extra)) {
callingPackage = extra;
}
}
} catch (NameNotFoundException e) {
// Couldn't lookup calling package info. This isn't really
// gonna happen, given that we're getting the name of the
// calling package from trusty old Activity.getCallingPackage.
// For that reason, we ignore this exception.
}
return callingPackage;
}
...and it seems that for whatever reason my packagename isn't found. How can can happen?
Asked him to install one of my other apps, and it happens there as well.
Asked him then to install another app from the playstore (FX File Explorer) and there it does not happen.
So it is specific to his device and my app.
So it turned out that this user having that issue turned off the MIUI Optimizations in the developer settings.
Bug report: συσκευη, εκδοση miui, Play store install (alpha 1021). It was impossible to specify a b i o s file or specify a game image directory in when MIUI optimizations are off. Turning them back on fixed the issue and directories are scanned normally. Also on the popup to allow folder access the app displays as "Anonymous" instead of AetherSX2 on my system. Some developer was talking about having the same issue here.
Created an app that used the device's uniqueID which is fetched by the following code snippet
String deviceId = Settings.Secure.getString(getContentResolver(),
Settings.Secure.ANDROID_ID);
When the user tries to clone the app by app cloner, then it creates a different deviceID and the app is not allowed to work
Is there any way to make our app non clonable
or
Any possible way to have the same deviceId even if the app instance is cloned?
Is there any way to find out whether the app is running in a cloned instance?
Applications like Cloner usually change your application's package name so you can retrieve package name and check if it is changed or not.
if (!context.getPackageName().equals("your.package.name")){
// close the app or do whatever
}
Also they usually sign cloned apk so the signature might be different from yours, you can check if signature is changed or not. I usually use this function:
#SuppressLint("PackageManagerGetSignatures")
public static int getCertificateValue(Context ctx){
try {
Signature[] signatures = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
signatures = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES).signingInfo.getApkContentsSigners();
}catch (Throwable ignored){}
}
if (signatures == null){
signatures = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES).signatures;
}
int value = 1;
for (Signature signature : signatures) {
value *= signature.hashCode();
}
return value;
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
public static boolean checkCertificate(Context ctx, int trustedValue){
return getCertificateValue(ctx) == trustedValue;
}
Before releasing your app call getCertificateValue(context) and write down the value and alongside with package name, check if that value matches the value that you get in runtime.
PS: as #vladyslav-matviienko said hackers will always find a way so try to make cloning harder by running some obfuscations on hardcoded package name and that value. Also try to tangle and spread these kind of logics all around the source code.
I found a story in proandroiddev by Siddhant Panhalkar and with some minor changes it's work perfectly in Mi device I did checked in Mi phones default Dual apps and some third party apps from playstore and it prevents from cloning (means not working properly after clone).
private const val APP_PACKAGE_DOT_COUNT = 3 // number of dots present in package name
private const val DUAL_APP_ID_999 = "999"
private const val DOT = '.'
fun CheckAppCloning(activity: Activity) {
val path: String = activity.filesDir.getPath()
if (path.contains(DUAL_APP_ID_999)) {
killProcess(activity)
} else {
val count: Int = getDotCount(path)
if (count > APP_PACKAGE_DOT_COUNT) {
killProcess(activity)
}
}
}
private fun getDotCount(path: String): Int {
var count = 0
for (element in path) {
if (count > APP_PACKAGE_DOT_COUNT) {
break
}
if (element == DOT) {
count++
}
}
return count
}
private fun killProcess(context: Activity) {
context.finish()
android.os.Process.killProcess( android.os.Process.myPid())
}
First of all I'd like to say that it is a project for a course in my university and at the same time my first app for Android which is more complicated that a calculator, so I understand that I could have done some unforgivable mistakes, but my priority is that the code should work. It can be insecure and not considering some cases, but as long as those cases won't appear, it will do.
My app is intended to be running on Android and first of all there should appear login screen which takes login and password, makes the hash of the password and contacts a database on a web server to compare hashes. I was told to use a free database db4free.net.
I created a class Serwer, which would be responsible exclusively for contacting the database. As far as I understood from tutorials and stackoverflow questions and answers, the connection should consist of:
Loading the driver,
Registering it in the DriverManager class,
Using getConnection method to open the connection, passing the credentials,
Preparing and executing SQL query,
Fetching a result set.
I also learned that I should download a mysql-connector-java-5.1.38-bin.jar file. As some threads on stackoverflow suggested, I copied it into main directory of the project (I have to copy the workspace and take to professor's computer when I finish), added it to Libraries tab of properties as an external library. Now when I run the project on my smartphone, I get a java.lang.ClassNotFoundException: Didn't find class "com.mysql.jdbc.Driver" error. I also tried to check the library in Order and Export tab - then it even doesn't compile, returning Conversion to Dalvik format failed with error 1.
I've tried many scenarios in other stackoverflow threads, such as cleaning the project in many configurations, changing the order of build path, etc. I suspect that I've made a simple, stupid mistake that I do not see and I hope you will recognize it.
Here is my Serwer class:
package com.planer.serwer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Driver;
import com.planer.MainActivity;
import com.example.planer.R;
import com.planer.pracownik.Pracownik;
public class Serwer {
private Connection conn = null;
private static Driver driver;
private static int status;
private MainActivity parentActivity;
private final String user = parentActivity.getResources().getString(R.string.db_login);
private final String pass = parentActivity.getResources().getString(R.string.db_pass);
private final String url= "jdbc:mysql://db4free.net:3306/kalendarzplaner";
public static final int STATUS_GOOD = 0;
public static final int STATUS_NO_CONNECTION = 1;
public static final int STATUS_NOT_AUTHENTICATED = 2;
public static final int STATUS_SQL_EXCEPTION = 4;
public static final int STATUS_NO_DRIVER = 8;
public Serwer(MainActivity parentActivity){
status = STATUS_NO_CONNECTION;
try {
driver = new com.mysql.jdbc.Driver();
} catch (Exception ex) {
status |= STATUS_NO_DRIVER;
} catch (NoClassDefFoundError e){
status |= STATUS_NO_DRIVER;
}
this.parentActivity = parentActivity;
}
public Pracownik authorize(String login, String passhash){
Pracownik pracownik = new Pracownik("","",false,status);
status |= this.polacz();
if(status != Serwer.STATUS_GOOD) {
pracownik.status |= status;
return pracownik;
}
Statement statement = null;
ResultSet resultSet = null;
String query = "select passhash, imie_nazwisko, czy_kierownik from auth where login='" + login + "';";
try {
statement = conn.prepareStatement(query);
resultSet = statement.executeQuery(query);
resultSet.first();
if(resultSet.getString("passhash").toString().compareTo(passhash)!= 0){
status |= Serwer.STATUS_NOT_AUTHENTICATED;
pracownik.status |= status;
return pracownik;
}
pracownik.login = login;
pracownik.imie_nazwisko = resultSet.getString("imie_nazwisko");
pracownik.czy_kierownik = resultSet.getBoolean("czy_kierownik");
} catch (SQLException ex) {
pracownik.status |= Pracownik.STATUS_SQL_EXCEPTION;
}
return pracownik;
}
public int polacz() {
int done = STATUS_NO_CONNECTION;
if((status & STATUS_NO_DRIVER) != 0)
return done;
// Connection
try {
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, user, pass);
done = Serwer.STATUS_GOOD;
} catch (java.sql.SQLException ex) {
done |= Serwer.STATUS_SQL_EXCEPTION;
System.out.println("SQLException: " + ex.getMessage());
}
return done;
}
}
As I said, the status of the result of authorise method is 9, which is expected when the driver is not loaded. I also append my workspace contents.
First, I want to start by suggesting that you tried out Android Studio. It's the new more modern IDE developed specifically for the purpose of Android Development.
Secondly, contacting a database on Android is a lot different than for example contacting a DB from Java/C# in an Desktop application.
To contact an online MySQL Database you need a RESTful service (written in PHP for example) that gets the data from the database and sends it over to the application. The service is like a communication point between the App and the Database. The service usually sends data to the application in a human-unfriendly format like JSON, so your app needs to parse that and then display it.
I have android native application & web service. Our application is University application. Generate long live token for session issue.So we planned to go for MDM, i searched on Google, , I got some solution
Open Mobster (Open Source Mobile Enterprise Backend)
Apache USerGrid_ (Mobile Backend as a service)
OpenMeap - not support native
Problem is I could not find out , whether this MDM are provide device identification facility.If any one knows about it please tell me. Device identification may be any unique id or mac address
or If i am going to developed our own middle layer , how we can get mac address from request header. without passing to service method , from the request should take.
is there any way to take sort-out this issue?
Please help me
Here is how OpenMEAP grabs the Mac address and passes it in the header.
package com.openmeap.thinclient;
import java.io.ByteArrayInputStream;
import com.openmeap.http.HttpRequestExecuter;
import com.openmeap.http.HttpResponse;
import com.openmeap.util.Utils;
public class FirstRunCheck implements Runnable {
private SLICConfig config;
private String macAddress;
private HttpRequestExecuter executer;
public FirstRunCheck(SLICConfig config, String macAddress, HttpRequestExecuter executer) {
this.config = config;
this.macAddress = macAddress;
this.executer = executer;
}
public void run() {
if( config.isDevelopmentMode().equals(Boolean.TRUE) ) {
return;
}
if( config.getNotFirstRun()==null ) {
config.setNotFirstRun(Boolean.TRUE);
try {
String macWithSalt = macAddress+".OPENMEAP#$!#3__234";
String hashValue = Utils.hashInputStream("sha1", new ByteArrayInputStream(macWithSalt.getBytes("UTF-8")));
HttpResponse response = executer.get("http://usage.openmeap.com/tracker.gif?hash="+hashValue);
Utils.consumeInputStream(response.getResponseBody());
} catch( Exception ioe ) {
return;
}
}
}
}
I had gotten reports from a few users that they couldn't login to our app (which makes HTTP calls to our site) or visit our website in their browser, so I added some code to our latest build to check what IP our host name is resolving to. I've gotten reports from several different users now that they get 127.0.0.1 for our hostname when the app starts, which obviously isn't going to work.
They claim they aren't running any proxy software, and this happens on both 2.1 and 2.2. This also happens on both wifi & 3g, which makes me suspect it is some piece of software on their phone that is interfering with DNS resolution somehow. Does anyone know of any popular software that might do that? Or does anyone have any ideas about how to identify which software might be doing it?
Thanks,
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.TXTRecord;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
public class DNSLookUpActivity extends Activity {
private String url = "https://spectracore.americanlogistics.com/rdac/AdmissionController/CheckMddAdmission";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
funDNS(url);
}
private static void funDNS(String url) {
try {
Lookup lookup = new Lookup(url, Type.ANY);
Record[] records = lookup.run();
if (lookup.getResult() == Lookup.SUCCESSFUL) {
String responseMessage = null;
String listingType = null;
for (int i = 0; i < records.length; i++) {
if (records[i] instanceof TXTRecord) {
TXTRecord txt = (TXTRecord) records[i];
for (Iterator j = txt.getStrings().iterator(); j
.hasNext();) {
responseMessage += (String) j.next();
}
Log.e("TXRecord ", "" + responseMessage);
} else if (records[i] instanceof ARecord) {
listingType = ((ARecord) records[i]).getAddress()
.getHostAddress();
Log.e("ARecord address : ", "" + listingType);
}
}
}
} catch (TextParseException e) {
e.printStackTrace();
}
}
}
Need android ask version 2.3.3 or above
Get their DNS config, and try their DNS servers directly with dig or nslookup. This is not perfect, but it has a good chance of showing you the problem.
dnsjava/org.xbill.DNS is too big for android app, Scott Means's DNSQuery is promiseful:
http://smeans.com/programming/dns-queries-in-java/