How to change apk file and resign it onilne? - android

For some security reasons I need to change apk file before user can download apk file. But when I change .apk content, my app cant be installed. Its need to be resigned.
So I want to know how do I resign it using only zip-open/read/write operations or something else using php.
The only way I see is to install sdk tools on server and work with them with shell command in php. But I want to know if there are more easy ways to do this

The only way I see is to install sdk tools on server and work with them with shell command in php.
In all likelihood, that is your only option. Even if somehow PHP had a fully-functioning jarsigner embedded in it, it is unlikely to also have zipalign.
Note, though, that by "sdk tools", you only really need the Java SDK (for jarsigner) and the zipalign binary (which, AFAIK, has no other dependencies). You should not need the entire Android SDK.

Related

How can I sign Android application with AOSP certificate

The context of my issue is the following:
I build AOSP for our hardware device on Linux
Together with the system, I build an APK as a system application
Everything works fine in this setup when I flesh it together with system image
However, I would like to have this application build separated from the AOSP build and be able to build it standalone and install from Windows.
On windows, I am trying to build it with Gradle
And the problem arises when I try to push the build to the device the following way:
adb install -r my_app.apk
adb: failed to install my_app.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package <...> signatures do not match the previously installed version; ignoring!]
Obviously the error means that I am missing a platform signature in the application, but where to take it from the AOSP build and how to sign it with Gradle build is not so clear.
Also here I found an advice to uninstall the system app first before installing. Unfortunately, for my case it does not help, the error is still the same even I uninstall it first.
I already spend quite some time on this, searching in the Android make-files for the signing script, but it seems to be not that straight forward there.
Any help would be highly appreciated...
Create a keystore from platform.x509.pem and platform.pk8 files located in build/target/product/security. Then use that with gradle.
See this answer for how to do the conversion: https://stackoverflow.com/a/22214826/3801327
Note: Don't use the default keys included with AOSP, everyone has those, and would be able to make their app a system app in your platform. Generate your own keys.

Update native library without reinstalling the app

I have app which include two native library (for example libfirst.so, libsecond.so). Now a loading libraries standard method.
System.loadLibrary("first");
System.loadLibrary("second");
Now I need to be able to update the library without reinstalling the app (without update .apk).
I can loaded native libraries this method
System.load("/storage/emulated/0/armeabi/libfirst.so");
System.load("/storage/emulated/0/armeabi/libsecond.so");
I think this is a bad practice.
I tried to copy manual the libraries in folder getApplicationInfo().nativeLibraryDir , but system error:
open failed: EACCES (Permission denied)
What are the best practices update native libraries without update apk ?
What are the best practices update native libraries without update apk ?
I don't believe that contingency is covered.
Code signing does two things. First, it ensures the developer who publishes the app is the same one who updates the app. Second, it creates trust relationships between related apps (but that does not apply here). Nikolay Elenkov discusses the topic at Code signing in Android's security model.
If you want to update the dependent libraries, then you need to rebuild the APK to prove you are authorized to make the updates. That's part one of code signing discussed above.
If you want to update a personal copy of the app (and not publish it), then just strip the existing signatures, update the libraries, sign with the Debug signing key, and then push to the device.
Also, you are safe to perform adb install -r <the apk>. -r is "replace existing application", and its effectively a reinstall. It retains the previous application data, like a database.
There are some other things that need to be done when updating an app, like increasing version numbers so its handled properly in Google Play. But they are not really relevant to your question.
There is actually a way to do it
for install your apk:
adb install -r path_to_my_apk.apk
now you can change your code and recompile your .so and when you want to update it you can do:
adb push -p path_to_my_so.so /data/local/tmp/libmyso.so
adb shell cat /data/local/tmp/libmyso.so | run-as com.mycomp.myapp sh -c 'cat > /data/data/com.mycomp.myapp/lldb/libmyso.so; chmod 700 /data/data/com.mycomp.myapp/lldb/libmyso.so'
adb shell rm /data/local/tmp/libmyso.so
Android studio does exactly this in order to install the lldb server when you are debugging native code.
It assumes there is a folder called lldb in your app directory. if you are debugging using Android Studio, this folder will already be there.
Your Java code needs to make sure to load the correct .so using
System.load("/data/data/com.mycomp.myapp/lldb/libmyso.so");
Instead of System.loadLibrary() which doesn't take a full path in a static initialization block somewhere, similar to how you load any other .so
This method can be very useful if your apk is huge and you only want to update the binary for easy debugging.

Download IPA / APK from Crashlytics

I'm using Crashlytics to distribute an app for Beta testing.
While it is easy and convenient to install the app on devices from the Crashlytics app, I have not been able to figure out how I could download only the IPA from the Crashlytics server.
Background: I need to get the IPA / APK for automated testing. My test environment will re-sign the IPA to be able to install it to test devices, so going the Crashlytics app way doesn't work.
What I need would be a download link for the IPA / APK as it used to be available in TestFlight or Hockeyapp.
If you're using it with iOS, you can enable Settings > Safari > Advanced > Web Console, then look in the web inspector of the download link from the install page on iOS. It will look like this (I swapped in gobbledegook text for some parts):
<a class="primary-button js-install-button" href="itms-services://?action=download-manifest&url=https%3A%2F%2Fapps.crashlytics.com%2Fprojects%2F2F2F2F2F2FF2F2F2%2Freleases%2F2200806%2Fdownload.plist%3Fdevice_id%2F2F2F2F%26device_token%234JH23L4KH234LK2J34H2LK34H2LK3J4H2LK3JH42L3K4JH23LK4JH2L3K4JH2L3K4JH2LKJ3H4%253D--2KJ3H4LK2J3H4L2KJ3H4LK2J3H4LK23JH4LK2J3H4L%26payload_token%2KL34JH2LK3JH4L2K3J4HL23KJ4HL23JK4" id="most-recent-install">Install</a>
Then just copy out the URL-encoded URL:
https%3A%2F%2Fapps.crashlytics.com%2Fprojects%2F2F2F2F2F2FF2F2F2%2Freleases%2F2200806%2Fdownload.plist%3Fdevice_id%2F2F2F2F%26device_token%234JH23L4KH234LK2J34H2LK34H2LK3J4H2LK3JH42L3K4JH23LK4JH2L3K4JH2L3K4JH2LKJ3H4%253D--2KJ3H4LK2J3H4L2KJ3H4LK2J3H4LK23JH4LK2J3H4L%26payload_token%2KL34JH2LK3JH4L2K3J4HL23KJ4HL23JK4
Then urldecode that on your command line using PHP:
php -r "echo urldecode('{PASTE THE ABOVE URL HERE}');"
(Make sure that you use double quotes around the PHP line, and single quotes around the URL.)
Then paste the URL-decoded result into Safari on your Mac. You'll see an XML file; copy the download link and paste into your browser. This will download the IPA to your Mac :D
After poking around myself, it doesn't look like there is any way to pull an ipa or apk from Crashlytics Beta.
I would suggest using something like Jenkins or Fastlane to automate your build process and have it a) upload to Dropbox or somewhere you can easily refer to and b) upload automatically to Crashlytics for distribution.
The gradle crashlytics plugin provides a handy method to do this:
gradlew assembleDebug crashlyticsUploadDistributionDebug
As far as I can see there is no straight forward way to download an IPA from Crashlytics.
However, if you really need to get the file it can be done.
Copy the link target of the Install button in the Crashlytics mail (alternatively view source and copy from there, this is what I did)
Paste to Safari in the Simulator. This will install the Crashlytics app in the simulator
Open install page in the Crashlytics app in simulator
inspect simulator with your Macs Safari (Develop > Simulator)
Copy button link and open in Safari on Mac - there you go
Of course this is nothing you want to do as a standard procedure :)
And sorry this is iOS only, so no bounty for me :(
I found an easy way to get APK builds on Android. Follow these steps:
Install "Amaze File Manager" on your device. Free version is enough and it doesn't need your device to be rooted.
Open "App Manager" in the menu on the left
Find your installed build by its name
Press "three dots" and select "backup"
You will find your APK file in the storage/emulated/0/app_backup
This answer is probably too late, and is only specific to the APK file, but I did manage to identify where Crashlytics stores the APK before installation.
After installing Beta/Crashlytics on your device, go ahead and download your application, but don't install it - just leave it at the screen asking if you want to install (just in case Beta/Crashlytics deletes the APK after installation, not sure if they do though)
Then, using adb via another computer, identify the file name of your application by opening up a shell and finding all APK files.
Open command prompt or terminal, and run adb devices to ensure your device is recognized
Once recognized, run adb shell, and then type su to enter superuser mode
There are 2 ways - you can search for all APK files and look for a file name similar to what you would expect using "find / -iname *.apk" OR you can try listing the files sorted by modified date to look for a recently modified APK using the following command "ls -nl [directory] | sort -k 8,8n -k 6,6M" where [directory] is the directory you want to list
Note the location, and then exit adb, and grab the file using adb pull - in my case it was "adb pull /data/app/myapplication.apk"
TL;DR - Beta/Crashlytics downloads the APK file for your application to /data/app/ before installing. You may need root privileges to access this folder.
Hope this helps!
This may specifically help those who are trying to retrieve the APK file.
If you're using Android, you can use Android Monitor to extract the file downloaded from the Crashlytics Beta app.
In order for this to work, you must have already installed the Crashlytics Beta app and have downloaded your app from within the Beta app.
Then, follow these steps:
Open Android Device Monitor
Select your device in the "Devices" tab on the left
Click on the "File Explorer" View on the right
Navigate through the path: data/data/io.crash.air/files.
There you should find your .apk file
Click on the "Pull a file from the device" button in the top right.
Very complicated, but probably one of the few ways to extract it.
Another thought would be to use Wireshark to sniff the traffic when the device tries to download the APK/IPA file. This can be done while using an emulator.
I am using crashlytics for distributing app to testers, The steps are as
Install crashlytics(add fabric+crashlytics) to your code as described on their site.
Now, make archieve of your application.(Check that provisioning profile and signing identity, the udid of testers are added with provisioning profile).
Now, click on fabric symbol at right-top corner, click on distribute button on that.
Once you click on distribute, this will show textfield and add button to add email addresses of testers.
After adding testers email addresses click on next button and continue.
This will send email of ipa files to testers and show buttons to install it.
This is working fine will latest versions of iOS.

Building an Android APK with same certificate as the system

I'm trying to make a system app work. Here's what I have:
An OEM OMAP platform with full 4.4.2 source code. I've built the system and loaded on my platform using Ubuntu 14.04. That all works.
Now, there is an app from the OEM which directly accesses the hardware (DSP, I2C, UART) etc. The original APK that came from the OEM works on my platform.
I built the exact same app using make command (not using Eclipse); It builds and I can install on the platform. But when I try to launch the app, it gets stuck in an eternal wait state.
I am not sure, but I suspect my locally built app tries to initialize a hardware component on the board and then gets blocked there.
I've been reading articles all over, and seems like it has something to do with the app signing and certificate. I think the general idea is the app needs to be signed with the same certificate with the system itself. I thought, since I built both the app and the system on the same machine using same commands, they would have a same certificate.
If it helps, the manifest file has this line:
android:sharedUserId="android.uid.system"
And the project make file Android.mk has this line:
LOCAL_CERTIFICATE := platform
Can anyone show me how can I make the app work? I am not sure, seems like I have to rebuild the app with proper certificates so that it can access all the hardware resources.
Thanks.
Check signing system apk.
Optionally:
You need to create a keystore file by using keytool-importkeypair which you can find here.
Go into the: build/target/product/security/ directory in your platform source tree (source codes related to your Android version and vendor).
You will find platform.pk8 and platform.x509.pem files.
Create keystore file by using this example command:
keytool-importkeypair -k ~/.android/debug.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform
You can use this keystore file to sign your apk which will have system permissions afterwards.

Can an APK be repacked after a minor text edit?

I'm creating a software that will guide the user through a few steps, to publish an android application (APK file).
The way I am doing this, is that the APK file is already compiled, and all I need to do is replace an XML file in the package, and that will change the behaviour of the application. My big problem now, is that unpacking the apk file, and doing any tiny text edit, and then packing it again, breaks the signature and prevents the application from running on any device, giving a message that the signature is incorrect.
How can I solve this? I want to safely open the APK, write something in a text file, and close it again. Note that this operation will be done on the user's computer (after he purchases our application) so we're look for a command-line tool with no special requirements like JDK.
Any help?
Ok I reached the best "tested" solution - I'm posting it here to save other developers hours of googling. The only downside is that I will require the customer to install JDK on his machine, unfortunately. The reason is because I did not find any apk-signing tool that works purely on windows, without relying on JDK.
I have my android application created using Air, so this makes things easy for me - all of the air files are treated as resource assets. So have your APK archive file ready.
Once you have your modifications ready, put them inside a temporary folder named "assets". You will use the 7-zip command line tool (free: http://sourceforge.net/projects/sevenzip/) to update the contents of your apk. To have it working with your apk you will have to rename your apk's extension to zip - don't worry, you'll change it back later.
Now from a .bat file (or directly in the command prompt) from the location containing both your apk file (zip extensioned) and your assets folder, you'll call: 7za u APK-file.zip assets
Now your apk file is updated. Rename it back to .apk extension
Now you'll use the signAPK tool from here https://code.google.com/p/signapk/ and note that this is the only step requiring JDK installed. It also assumes that you have your key files ready (replace the dummy ones included in the package). Extract the file contents and call: java -jar signapk.jar key.x509.pem key.pk8 [android_app].apk [signed_android_app].apk
At the very end, you may find your signed apk file size drammatically increased. So you need to use the android's zipAlign tool: (darn, can't post the link since new users can only post a maximum of two hyperlinks)
you will be calling the command: zipAlign -c 4 [signed_android_app].apk
And voila! That's the route I'm taking.
If someone finds a way to do the signing process without relying on JDK (assuming the key files are ready) please share.
How can I solve this?
You don't. If you modify an APK file, by any means, it must be re-signed.
Android apk files must be signed. That signature proves that the contents of the apk have NOT BEEN MODIFIED from what was initially published. (Which is exactly what you are doing.) The signature at the same time, also proves who the author is.
So in a normal signed apk file:
You know who the author is. (Even if it's not something you as a human can understand.)
You know the contents were put there by the author, and not modified since.
This is a key security measure built into Android, is there for very good reason, and cannot be overcome. It prevents things like viruses from being embedded inside innocent apk files.

Categories

Resources