Related
Since I tend to modify roms before flashing them to my phone, and sometimes want to do so away from a computer, I ended up writing this. It's an ash script that uses the openssl binary found on most custom roms, and infozip. The sdk test/platform/media/etc keys are included. Usage:
Usage: signapk (options) [command] (files)
commands:
sign FILE sign a .zip or .apk
sign FILE1 FILE2 create a signed copy of FILE1 as FILE2
cert FILE(s) print cert info on FILE's signer
certinfo FILE print detailed cert info on FILE's signer
cmp FILE compare signer of FILE with default/selected cert
cmp FILE1 FILE2 compare signer of FILE1 to signer of FILE2
options:
-k, --key FILE key to sign with
-c, --cert FILE cert to sign with
if -c or -k are not files then they are considered
aliases to builtins (ie -k testkey or -c platform)
-f, --force sign even if cert differs from original
-t, --tmp DIR use DIR for tempdir instead of '/cache'
-d, --debug output debugging
-V, --version print 'signapk v0.3.1'
exit codes:
1: read error (file 1) 2: read error (file 2)
3: write error 4: ssl error
5: zip write error 9: key error
8: sign: cert mismatch 10: cmp: cert mismatch
128: script error 255: user error
Installation:
unpack somewhere. If needed, edit the variables at the top of the script. By default it uses /cache/ for 4 small temporary files.
Faq:
* Why did you include a busybox and openssl? * Some roms don't include the openssl utility. Busybox's unzip refuses to deal with zipaligned apks on alot of roms, because it wasn't compiled with ENABLE_DESKTOP. Busybox's ash is missing things that the script needs, on some roms. The script will use whatever the rom provides, if these binaries are not present. Good luck.
* How do I change the cert? * see signapk --help for cert/key selection flags
* Can I use this in my MarketAppThingy? * Sure, and please let me know. If it's a paid MarketAppThingy, consider sending me a free copy.
Changelog:
release 3: cmp function, key selection, documented exit codes that make sense, and paranoia. Includes trimmed down busybox and openssl binaries. If these are present, script will reload itself to run in it's busybox ash interpreter to avoid broken busybox compiles, and can run without using anything provided by the rom. In theory this means no compatibility issues, but is limited to ARM devices.
release 2: Apparently it's valid to have ANYNAME.SF/ANYNAME.RSA or ANYNAME.DSA. signapk cert and certinfo now handles this. The sign function will blindly write to CERT.SF and CERT.RSA as this is the behavior of the standard SignApk.java. This may be fixed later.
If you don't wanna signup to download attachment, snag this from http://code.google.com/p/signapk/downloads/list
very, very useful. I'm testing this now Signing stuff was always way too complicated.
Cool. Can't wait for someone to make a market app that creates a simple ui to edit update.zips before flashing. Hint hint
I put the files in /system/signapk (new folder)
When i run the script I get the error below. The test file is an unsigned apk exported from eclipse.
Code:
# ./signapk sign /sdcard/unsigned.apk
./signapk sign /sdcard/unsigned.apk
Checksumming /mnt/sdcard/unsigned.apk:
res/layout/main.xml AndroidManifest.xml
resources.arsc res/drawable-hdpi/icon.png res/drawable-ldpi/icon.png res/drawable-mdpi/icon.png classes.dex
[COLOR="Red"]unable to write 'random state'
./signapk: line 132: ./signapk.zip: not found[/COLOR]
#
Any idea what needs changing to fix this?
update: When I used the full path it worked.
Code:
# /system/signapk/signapk sign /sdcard/unsigned.apk
/system/signapk/signapk sign /sdcard/unsigned.apk
Checksumming /mnt/sdcard/unsigned.apk:
res/layout/main.xml AndroidManifest.xml
resources.arsc res/drawable-hdpi/icon.png res/drawable-ldpi/icon.png res/drawable-mdpi/icon.png classes.dex
unable to write 'random state'
adding: META-INF/MANIFEST.MF (deflated 49%)
adding: META-INF/CERT.SF (deflated 48%)
adding: META-INF/CERT.RSA (deflated 33%)
# /system/signapk/signapk cert /sdcard/unsigned.apk
/system/signapk/signapk cert /sdcard/unsigned.apk
/sdcard/unsigned.apk 936EACBE07F201DF SDK Test Key
Was playing around with app inventor and came up with this:
edit: AppInventor does not generate java code and it cannot be worked on further in anything else (i.e eclipse)
I was really hoping I would atleast get the activity xml
Heya, the latest is at http://code.google.com/p/signapk/downloads/list and should fix the zip error. signapk-bb, signapk-zip, and signapk-openssl are static, trimmed down versions of utilities required by the script, and should be extracted to the same directory as the script. If they are not present it will try to use stuff in $PATH
Just throwing it (the obvious) out there that this could enable a new generation of morphs for /data apps
Copy apk,uninstall,morph, install
Hmmmm....
britoso said:
Just throwing it (the obvious) out there that this could enable a new generation of morphs for /data apps
Copy apk,uninstall,morph, install
Click to expand...
Click to collapse
How can i get this to work with a morph and to edit the updater-script?
Someone explain the commands with example...
Another noob question is .. it is for android or pc...
Edit:- Made my own mod here https://forum.xda-developers.com/t/...-apk-zip-within-android.3835975/post-81324327
below code works with latest(1.32.0) busybox
Bash:
#!/system/bin/sh
# depends unzip printf zip openssl
# put zip openssl busybox in PATH
# Usage:-
# Sign.sh key.pk8 key.x509.pem in.zip out.zip
ordie() {
if [ $? -ne 0 ]; then
IFS=" "
$BB printf "$1\n"
exit $2
fi
}
PKEY="$1"
CERT="$2"
ORIG="$3"
TARGET="$4"
BB=busybox
cat "$ORIG" > "$TARGET"; ordie "Cannot write to $TARGET" 3
$BB printf "Checksumming $ORIG:\n"
TMP=$HOME
TMPDIR="$TMP/sign-$$"
TMPPKEY="$TMPDIR/tmp.pkey"
mkdir -p "$TMPDIR/META-INF"; ordie "" 3
$BB printf "Manifest-Version: 1.0\r\nCreated-By: 1.0 (Android SignApk)\r\n\r\n" > "$TMPDIR/META-INF/MANIFEST.MF"
ZIPls=$($BB unzip -qql "$ORIG"); ordie "$ORIG: unzip error" 1
OLDIFS=$IFS
IFS=${IFS:2:2}
for i in $ZIPls; do
IFS=$OLDIFS
set -- $i
if [ "$#" -ge 3 ] && [ "$1" != "0" ]; then
file="${i:30}"
case "$file" in META-INF/MANIFEST.MF|META-INF/CERT.SF|META-INF/CERT.RSA) continue;; esac
$BB printf "$file "
hash=$($BB unzip -p "$ORIG" "$file" | openssl sha1 -binary | openssl base64); ordie "$ORIG: unzip error" 1
ret="Name: $file\r\nSHA1-Digest: $hash\r\n\r\n"
$BB printf "$ret" >> "$TMPDIR/META-INF/MANIFEST.MF"
hash=$($BB printf "$ret" | openssl sha1 -binary | openssl base64)
$BB printf "Name: $file\r\nSHA1-Digest: $hash\r\n\r\n" >> "$TMPDIR/META-INF/CERT.SF.temp"
fi
done
$BB printf "\n"
mfhash=$(cat "$TMPDIR/META-INF/MANIFEST.MF" | openssl sha1 -binary | openssl base64)
$BB printf "Signature-Version: 1.0\r\nCreated-By: 1.0 (Android SignApk)\r\nSHA1-Digest-Manifest: $mfhash\r\n\r\n" > "$TMPDIR/META-INF/CERT.SF"
cat "$TMPDIR/META-INF/CERT.SF.temp" >> "$TMPDIR/META-INF/CERT.SF"
openssl pkcs8 -inform DER -nocrypt -in "$PKEY" > "$TMPPKEY"; ordie "" 4
cat "$TMPDIR/META-INF/CERT.SF" | openssl smime -sign -inkey "$TMPPKEY" -signer "$CERT" -binary -outform DER -noattr > "$TMPDIR/META-INF/CERT.RSA"; ordie "" 4
cd "$TMPDIR"
zip "$TARGET" META-INF/MANIFEST.MF META-INF/CERT.SF META-INF/CERT.RSA; ordie "" 5
cd - > /dev/null
rm -r "$TMPDIR"
I'm trying to deconstruct the Android app development process by creating and installing a sample app entirely from the command line (without even using Ant). I've composed a script which seems to work until the very last command, at which point I get the message
134 KB/s (10496 bytes in 0.076s)
pkg: /data/local/tmp/MyActivity-debug.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
Please don't be put off by the fact that my script is a Windows .bat script. I'm just calling code from the SDK's tools and platform-tools directories. Anyway, here's the script. If find what I'm missing that's giving me the NO_CERTIFICATES error, please reply...
call "c:\program files (x86)\Android\android-sdk\tools\android" create project --target 10 --name MyAndroidProject --path c:\MyProjects\MyAndroidProject --activity MyActivity --package com.allmycode.samples
cd \MyProjects\MyAndroidProject
mkdir C:\MyProjects\MyAndroidProject\res
mkdir C:\MyProjects\MyAndroidProject\libs
mkdir C:\MyProjects\MyAndroidProject\bin
mkdir C:\MyProjects\MyAndroidProject\gen
mkdir C:\MyProjects\MyAndroidProject\bin\classes
"C:\Program Files (x86)\Android\android-sdk\platform-tools\aapt.exe" package -f -m -M C:\MyProjects\MyAndroidProject\AndroidManifest.xml -S C:\MyProjects\MyAndroidProject\res -I "C:\Program Files (x86)\Android\android-sdk\platforms\android-9\android.jar" -J C:\MyProjects\MyAndroidProject\gen
"c:\program files\java\jdk1.7.0\bin\javac" -d C:\MyProjects\MyAndroidProject\bin\classes -classpath C:\MyProjects\MyAndroidProject\bin\classes;C:\MyProjects\MyAndroidProject;c:\ant\lib\ant-launcher.jar;"C:\Program Files (x86)\Java\jre6\lib\ext\QTJava.zip";C:\ant\lib\ant-antlr.jar;C:\ant\lib\ant-apache-bcel.jar;C:\ant\lib\ant-apache-bsf.jar;C:\ant\lib\ant-apache-log4j.jar;C:\ant\lib\ant-apache-oro.jar;C:\ant\lib\ant-apache-regexp.jar;C:\ant\lib\ant-apache-resolver.jar;C:\ant\lib\ant-apache-xalan2.jar;C:\ant\lib\ant-commons-logging.jar;C:\ant\lib\ant-commons-net.jar;C:\ant\lib\ant-jai.jar;C:\ant\lib\ant-javamail.jar;C:\ant\lib\ant-jdepend.jar;C:\ant\lib\ant-jmf.jar;C:\ant\lib\ant-jsch.jar;C:\ant\lib\ant-junit.jar;C:\ant\lib\ant-junit4.jar;C:\ant\lib\ant-netrexx.jar;C:\ant\lib\ant-swing.jar;C:\ant\lib\ant-testutil.jar;C:\ant\lib\ant.jar;"C:\Program Files\Java\jdk1.7.0\lib\tools.jar" -sourcepath C:\MyProjects\MyAndroidProject\src;C:\MyProjects\MyAndroidProject\gen -target 1.5 -bootclasspath "C:\Program Files (x86)\Android\android-sdk\platforms\android-9\android.jar" -encoding UTF-8 -g -source 1.5 c:\MyProjects\MyAndroidProject\src\com\allmycode\samples\*.java
call "C:\Program Files (x86)\Android\android-sdk\platform-tools\dx.bat" --dex --output=C:\MyProjects\MyAndroidProject\bin\classes.dex C:\MyProjects\MyAndroidProject\bin\classes
"C:\Program Files (x86)\Android\android-sdk\platform-tools\aapt.exe" package -f --debug-mode -M C:\MyProjects\MyAndroidProject\AndroidManifest.xml -S C:\MyProjects\MyAndroidProject\res -I "C:\Program Files (x86)\Android\android-sdk\platforms\android-9\android.jar" -F C:\MyProjects\MyAndroidProject\bin\MyActivity-debug-unaligned.apk
"C:\Program Files (x86)\Android\android-sdk\tools\zipalign.exe" -f 4 C:\MyProjects\MyAndroidProject\bin\MyActivity-debug-unaligned.apk C:\MyProjects\MyAndroidProject\bin\MyActivity-debug.apk
start "Launch an emulator" "C:\Program Files (x86)\Android\android-sdk/tools/emulator.exe" -avd Gingerbread
timeout /T 60
"C:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe" install -r C:\MyProjects\MyAndroidProject\bin\MyActivity-debug.apk
You need to sign your apk
Hey, I believe all you need to do is sign your .apk with a certificate.
Here is a link about creating a certificate if you dont already have one. I tried to include a link but it wont let me. (sorry im a new user)
Once you have acquired a certificate, you can then use the JDK utitility called jarsigner. The terminal command should be something like this...
jarsigner -verbose -keystore my-release-key.keystore final.apk alias_name
Click to expand...
Click to collapse
Hope this helps ya out.
Hey people,
today i wanted to share a post from chenxiaolong, who did some awesome work back at the Galaxy Tab S2 forum. The main problem, was that Netflix didn't want to play HD content on the Galay Tab S2, which was why I researched the requirements of Netflix. They need Widevine L1 implemented on the SoC to allow HD playback. While this is the necessary requirement, Netflix also needs to enable this device in their device list and tell the app it supports Widevine DRM L1. In many cases they don't do that although the device itself would be very capable of displaying HD content. Tried it out on my Galaxy Tab S2 and on the Nexus 5, which both support Widevine DRM L1 and aren't/weren't marked as WV L1 capable. To check DRM capability of your device you can use for example this app https://play.google.com/store/apps/details?id=com.androidfung.drminfo&hl=en
This will not make a non WV L1 capable device run Netflix HD, it will only make the device use the most secure DRM technology!
The whole process doesn't need root, just some tools like apktool, apk-signer and such. Feel free to link the post into your device forum you achieved to get Netflix HD on.
Big Thanks goes out to @chenxiaolong
Link to thread post: http://forum.xda-developers.com/showpost.php?p=65001865&postcount=12
Based on this, I made a script on Ubuntu to patch last version of netflix APK.
It currently works on version up to 5.12.xxx, it doesn't seem to work on more recent versions, we will have probably to wait for a new version of apktool (2.4.0 ?).
First, you need to install some packages
Code:
sudo apt-get install apktool zipalign default-jdk
Then, you have to build you own signature (to do only once)
Code:
keytool -genkeypair -alias androiddebugkey -keypass android -keystore "${HOME}/.netflix.keystore" -storepass android -keyalg RSA -sigalg SHA1withRSA -dname "CN=Android Debug,O=Android,C=US" -validity 9999
Then, download last netflix APK, for instance from apkmirror, and execute this script on downloaded file (for instance "netflixpatch com.netflix.mediaclient_4.16.1.apk" if your script is named "netflixpatch")
Code:
#!/bin/bash
NAME=$(basename "${1}" .apk)
KEYSTORE="${HOME}/.netflix.keystore"
TMPOUT=$(mktemp -d /tmp/tmpdir.netflixpatch.XXXXXXXXXX) || { echo "Failed to create temp file"; exit 1; }
FILEOLD="${TMPOUT}/smali/com/netflix/mediaclient/service/webclient/model/leafs/DeviceConfigData.smali"
FILENEW="${TMPOUT}/smali/com/netflix/mediaclient/service/configuration/DeviceConfiguration.smali"
apktool d -r -f "${1}" -o "${TMPOUT}"
if [ -f "${FILEOLD}" ];then
echo "Patching method 1"
sed -i 's/iget-boolean v0, p0, Lcom\/netflix\/mediaclient\/service\/webclient\/model\/leafs\/DeviceConfigData;->enableWidevineL1:Z/const\/4 v0, 0x1/g' "${FILEOLD}"
elif [ -f "${FILENEW}" ];then
echo "Patching method 2"
sed -i '/isWidevineL1Enabled/c\ const\/4 v0, 0x1\n return v0' "${FILENEW}"
else
echo "File to patch not found !"
rm -rf "${TMPOUT}"
exit 1
fi
# /usr/local/bin/apktool b "${TMPOUT}"
apktool b "${TMPOUT}"
jarsigner -keystore "${KEYSTORE}" -storepass android -keypass android -sigalg MD5withRSA -digestalg SHA1 -sigfile CERT -signedjar "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${TMPOUT}/dist/${NAME}.apk" androiddebugkey
zipalign -f 4 "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${NAME}-patched-signed-zipaligned.apk"
rm -rf "${TMPOUT}"
You'll get a "com.netflix.mediaclient_4.16.1-patched-signed-zipaligned.apk" file, which will play HD content if your device has Widevine DRM L1 libraries, even if not whitelisted by Netflix.
Perfect! It works for me on Medion Tablet. It also enables download offline mode. Tanks.
It doesn´t work for me...I get an error when tryng to reproduce movies
Hi!
Is it possible that this trick doesn't work anymore or doesn't work on all devices? I patched the current Netflix APK (and verified that the changes were made using apktool) but I only get 720p at best. There was also an error message along the lines of "content not allowed in prolog"?
I'm using one of those generic AmLogic S912 boxes ("X92 Smart Box" with the white clock display thing in the front) which supports L3 but neither Netflix nor Prime Video stream 1080p.
GuillaumeBarberousse said:
Based on this, I made a script on Ubuntu to patch last version of netflix APK.
First, you need to install some packages
Code:
sudo apt-get install apktool zipalign default-jdk
Then, you have to build you own signature (to do only once)
Code:
keytool -genkeypair -alias androiddebugkey -keypass android -keystore "${HOME}/.netflix.keystore" -storepass android -keyalg RSA -sigalg SHA1withRSA -dname "CN=Android Debug,O=Android,C=US" -validity 9999
Then, download last netflix APK, for instance from apkmirror, and execute this script on downloaded file (for instance "netflixpatch com.netflix.mediaclient_4.16.1.apk" if your script is named "netflixpatch")
Code:
#!/bin/bash
NAME=$(basename "${1}" .apk)
KEYSTORE="${HOME}/.netflix.keystore"
TMPOUT=$(mktemp -d /tmp/tmpdir.netflixpatch.XXXXXXXXXX) || { echo "Failed to create temp file"; exit 1; }
apktool d -r -f "${1}" -o "${TMPOUT}"
sed -i 's/iget-boolean v0, p0, Lcom\/netflix\/mediaclient\/service\/webclient\/model\/leafs\/DeviceConfigData;->enableWidevineL1:Z/const\/4 v0, 0x1/g' ${TMPOUT}/smali/com/netflix/mediaclient/service/webclient/model/leafs/DeviceConfigData.smali
apktool b ${TMPOUT}
jarsigner -keystore "${KEYSTORE}" -storepass android -keypass android -sigalg MD5withRSA -digestalg SHA1 -sigfile CERT -signedjar "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${TMPOUT}/dist/${NAME}.apk" androiddebugkey
zipalign -f 4 "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${NAME}-patched-signed-zipaligned.apk"
rm -rf $TMPOUT
You'll get a "com.netflix.mediaclient_4.16.1-patched-signed-zipaligned.apk" file, which will play HD content if your device has Widevine DRM L1 libraries, even if not whitelisted by Netflix.
Click to expand...
Click to collapse
Im sorry but with these informations I don't know exactly if and how it will work out for my galaxy s5. Can I use a app on my mobile to sign the backuped Netflix app? Or do I need to sign the apk on my PC?
T0mfield said:
Im sorry but with these informations I don't know exactly if and how it will work out for my galaxy s5. Can I use a app on my mobile to sign the backuped Netflix app? Or do I need to sign the apk on my PC?
Click to expand...
Click to collapse
These are instructions for Linux. What I have done:
1. download Ubuntu from Windows 10 Store
2. open powershell as admin and type:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
3. reboot when prompted
4. open command line and type:
ubuntu
5. create user/password as prompted
6. type:
sudo apt-get upgrade
Then follow the instructions from post #1. I've got my netflix apk from apkmirror: https://www.apkmirror.com/?post_type=app_release&searchtype=apk&s=netflix
You can access the windows filesystem by /mnt/c/
The script worked fine for me with Netflix 5.9.0 build 24858 and my Nexus 10.
The modification was not working anymore on my tablet (Samsung Galaxy Tab A6 SM-T580) giving me an error 0013 and it is now working again, I don't know why (I upgraded firmware to last version T580XXU2BQI9 / T580XEF2BQI9, or maybe Netflix changed something on their servers).
It is tested and working on Netflix apk 5.8.0_build_24642 and 5.9.0_build_24858 with apktool 2.2.1-dirty (Ubuntu 17.04 version), 2.2.3 and 2.3.0
I edited post https://forum.xda-developers.com/showpost.php?p=72178861&postcount=2, it should now work with old and new version of APK, (tested with version 5.11.1_build_25432)
GuillaumeBarberousse said:
I edited post https://forum.xda-developers.com/showpost.php?p=72178861&postcount=2, it should now work with old and new version of APK, (tested with version 5.11.1_build_25432)
Click to expand...
Click to collapse
I'm getting this error:
Code:
sed: can't read /tmp/tmpdir.netflixpatch.1QU3FdHrJ4/smali/com/netflix/mediaclient/service/webclient/model/leafs/DeviceConfigData.smali: No such file or directory
Also, you've changed the keystore value in the script code but not in the signature code.
Also, it didn't work with 5.11.2. Getting an error 5.2. Not sure if it's because it genuinely doesn't work anymore or because I didn't do it correctly on account of the error. Might I add that I'm using a virtual machine, if it makes a difference.
Also, why is there an L before com/?
vleesevlons said:
Also, you've changed the keystore value in the script code but not in the signature code.
Also, it didn't work with 5.11.2. Getting an error 5.2. Not sure if it's because it genuinely doesn't work anymore or because I didn't do it correctly on account of the error. Might I add that I'm using a virtual machine, if it makes a difference.
Also, why is there an L before com/?
Click to expand...
Click to collapse
Thank you, I edited the script to correct keystore path.
The error you were getting was normal, I was trying to patch file for old versions and new versions of netflix apk, I changed the script to prevent the file error message.
I don't know why you've got error 5.2, I had it for some times then it worked again, after uninstalling official apk and reinstalling patched one, maybe something in the cache of the tablet. I tried many version of apktool too, but it doesn't seem related.
For the virtual machine, it shouldn't affect the patching process.
And for the L before com, I don't know, it is smali language, probably to indicate a string value.
GuillaumeBarberousse said:
Thank you, I edited the script to correct keystore path.
The error you were getting was normal, I was trying to patch file for old versions and new versions of netflix apk, I changed the script to prevent the file error message.
I don't know why you've got error 5.2, I had it for some times then it worked again, after uninstalling official apk and reinstalling patched one, maybe something in the cache of the tablet. I tried many version of apktool too, but it doesn't seem related.
For the virtual machine, it shouldn't affect the patching process.
And for the L before com, I don't know, it is smali language, probably to indicate a string value.
Click to expand...
Click to collapse
I have a Nexus 5 (2013).
I've installed DRMinfo to confirm that I have WV L1 and it says it does.
I've been experimenting with liboemcrypto.so, i.e. deleting it or renaming it, and that does get rid of the error 5.2.
However, it appears that if the .so file differs from how a liboemcrypto.so should be, then Netflix will not do the DRM check and it will just give you SD quality.
So, I'm at a loss there...
What build worked for you? I've tried 5.11.2 build 25441 and 5.11.1 build 25432
vleesevlons said:
I have a Nexus 5 (2013).
I've installed DRMinfo to confirm that I have WV L1 and it says it does.
I've been experimenting with liboemcrypto.so, i.e. deleting it or renaming it, and that does get rid of the error 5.2.
However, it appears that if the .so file differs from how a liboemcrypto.so should be, then Netflix will not do the DRM check and it will just give you SD quality.
So, I'm at a loss there...
What build worked for you? I've tried 5.11.2 build 25441 and 5.11.1 build 25432
Click to expand...
Click to collapse
In my understanding, but I'm not sure, if you remove liboemcrypto.so, you lose Widevine level 1, so Netflix won't even try to play HD, so no error 5.2. I tried and got HD by patching 5.11.2_build_25441 and 5.11.1_build_25432.
Thanks for this guide. For me this missed a few instructions, like how to run a script on a file
So this are the steps nessesary to compleat this process:
1. Do everything from OP till it says to run a script on a file
2. For ease name your script netflixpatch and file com.netflix.mediaclient_4.16.1.apk
3. Open terminal in a place where you saved netflix app and this script
4. In terminal type: chmod u+x netflixpatch
5. Then run this script on apk by typing in terminal: ./netflixpatch com.netflix.mediaclient_4.16.1.apk (with ./ in front)
6. If all went you will see new file in your directory, thats the modified app
Now. For me, and I had apk v .12.2 build 25768 this trick seems to not work. I still have video looking like 720
Im on OnePlus 5T (capable of widevine lv.1) and stock rom.
Do I have nessesary libery I don't really know yet.
Need to investigate more but at least I have modified apk now so thanks for that
EDIT: Thers no liboemcrypto.so in /system/vendor/lib/ so that's probably the issue here ...
anybody knows that this code founds with Android TV netflix apk ?
GuillaumeBarberousse said:
Based on this, I made a script on Ubuntu to patch last version of netflix APK.
First, you need to install some packages
Code:
sudo apt-get install apktool zipalign default-jdk
Then, you have to build you own signature (to do only once)
Code:
keytool -genkeypair -alias androiddebugkey -keypass android -keystore "${HOME}/.netflix.keystore" -storepass android -keyalg RSA -sigalg SHA1withRSA -dname "CN=Android Debug,O=Android,C=US" -validity 9999
Then, download last netflix APK, for instance from apkmirror, and execute this script on downloaded file (for instance "netflixpatch com.netflix.mediaclient_4.16.1.apk" if your script is named "netflixpatch")
Code:
#!/bin/bash
NAME=$(basename "${1}" .apk)
KEYSTORE="${HOME}/.netflix.keystore"
TMPOUT=$(mktemp -d /tmp/tmpdir.netflixpatch.XXXXXXXXXX) || { echo "Failed to create temp file"; exit 1; }
FILEOLD="${TMPOUT}/smali/com/netflix/mediaclient/service/webclient/model/leafs/DeviceConfigData.smali"
FILENEW="${TMPOUT}/smali/com/netflix/mediaclient/service/configuration/DeviceConfiguration.smali"
apktool d -r -f "${1}" -o "${TMPOUT}"
if [ -f "${FILEOLD}" ];then
echo "Patching old version"
sed -i 's/iget-boolean v0, p0, Lcom\/netflix\/mediaclient\/service\/webclient\/model\/leafs\/DeviceConfigData;->enableWidevineL1:Z/const\/4 v0, 0x1/g' "${FILEOLD}"
elif [ -f "${FILENEW}" ];then
echo "Patching new version"
sed -i '/isWidevineL1Enabled/c\ const\/4 v0, 0x1\n return v0' "${FILENEW}"
else
echo "File to patch not found !"
rm -rf "${TMPOUT}"
exit 1
fi
# /usr/local/bin/apktool b "${TMPOUT}"
apktool b "${TMPOUT}"
jarsigner -keystore "${KEYSTORE}" -storepass android -keypass android -sigalg MD5withRSA -digestalg SHA1 -sigfile CERT -signedjar "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${TMPOUT}/dist/${NAME}.apk" androiddebugkey
zipalign -f 4 "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${NAME}-patched-signed-zipaligned.apk"
rm -rf "${TMPOUT}"
You'll get a "com.netflix.mediaclient_4.16.1-patched-signed-zipaligned.apk" file, which will play HD content if your device has Widevine DRM L1 libraries, even if not whitelisted by Netflix.
Click to expand...
Click to collapse
------------------------------------------
anyone try to apply this patch and upload to mega to try if this patch found in Mi box Tv
Problems with the script Helpme
[email protected]:/mnt/c/Users/crist/Downloads/netflix# ./net.sh com.netflix.ninja_5.0.4_build_1965.apk
./net.sh: line 2: $'\r': command not found
./net.sh: line 14: syntax error near unexpected token `elif'
'/net.sh: line 14: `elif [ -f "${FILENEW}" ];then
anybody could helme ... I copy this script :
-------------------------------------------------------------
#!/bin/bash
NAME=$(basename "${1}" .apk)
KEYSTORE="${HOME}/.netflix.keystore"
TMPOUT=$(mktemp -d /tmp/tmpdir.netflixpatch.XXXXXXXXXX) || { echo "Failed to create temp file"; exit 1; }
FILEOLD="${TMPOUT}/smali/com/netflix/mediaclient/service/webclient/model/leafs/DeviceConfigData.smali"
FILENEW="${TMPOUT}/smali/com/netflix/mediaclient/service/configuration/DeviceConfiguration.smali"
apktool d -r -f "${1}" -o "${TMPOUT}"
if [ -f "${FILEOLD}" ];then
echo "Patching old version"
sed -i 's/iget-boolean v0, p0, Lcom\/netflix\/mediaclient\/service\/webclient\/model\/leafs\/DeviceConfigData;->enableWidevineL1:Z/const\/4 v0, 0x1/g' "${FILEOLD}"
elif [ -f "${FILENEW}" ];then
echo "Patching new version"
sed -i '/isWidevineL1Enabled/c\ const\/4 v0, 0x1\n return v0' "${FILENEW}"
else
echo "File to patch not found !"
rm -rf "${TMPOUT}"
exit 1
fi
# /usr/local/bin/apktool b "${TMPOUT}"
apktool b "${TMPOUT}"
jarsigner -keystore "${KEYSTORE}" -storepass android -keypass android -sigalg MD5withRSA -digestalg SHA1 -sigfile CERT -signedjar "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${TMPOUT}/dist/${NAME}.apk" androiddebugkey
zipalign -f 4 "${TMPOUT}/dist/${NAME}-patched-signed.apk" "${NAME}-patched-signed-zipaligned.apk"
rm -rf "${TMPOUT}"
-----------------------------------
Don't copy and paste the script into terminal. Create a new file and past this to it then set permission on file and run the script
yes I did that
Friend I Did that. I was copy the script and paste in a white document and save has .sh when I try to execute make me that error . Please help me
Tried the script. First had to get Ubuntu. So I did:
enable Hyper-V, load Ubuntu 16.4.3-server-x64 (so no GUI) on Generation 1
ran the apt-get install commands provided by OP
Code:
[email protected]:~$ ./netflixpatch com.netflix.mediaclient_5.13.0_build_25824.apk
03:21:52 up 17 min, 2 users, load average: 0.05, 0.07, 0.07
USER TTY FROM [email protected] IDLE JCPU PCPU WHAT
sebas tty1 03:04 13:17 0.05s 0.05s -bash
sebas pts/0 192.168.178.72 03:09 0.00s 0.07s 0.00s w
I: Using Apktool 2.0.2-dirty on com.netflix.mediaclient_5.13.0_build_25824.apk
I: Copying raw resources...
I: Baksmaling classes.dex...
I: Baksmaling classes2.dex...
I: Baksmaling classes3.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
Patching old version
Script is running BUT I do not see the output created. Old file has an unmodified timestamp. Any thoughts on how to troubleshoot this?
Recent versions of the Netflix app (starting with 5.13.0) are permanently crashing after being processed. At least on my devices. So you can stop working on the current version or take a 5.12.x release.
See: https://forum.xda-developers.com/showpost.php?p=75479828&postcount=136
Introduction
This tutorial will teach you how to specifically extract the boot.img from your OTA/ROM's payload.bin on your Android device, rather than a computer.
In addition to this, you will also have the ability to access all other img files that are packaged with the payload.bin.
The boot partition contains a kernel image and a RAM disk combined via mkbootimg.
You would generally want to keep a copy of your current OTA/ROM's boot.img in the event that you want to recover your devices boot partition when you want to switch kernels, or repairing a corrupted device due to kernel/RAM disk issues.
Prerequisites
Termux Installed: Official Play Store Link | Official F-Droid Link
payload_dumper: Official GitHub Link
To get started
Code:
# Extract payload_dumper folder contents to: /storage/emulated/0/payload_dumper/
# Extract payload.bin from your OTA/ROM to: /storage/emulated/0/payload_dumper/
$ pkg install python -y
$ pip install --upgrade pip
$ apt update && apt upgrade -y
$ termux-setup-storage
# Allow Termux access photos, media and files on your device
$ cd storage/shared/payload_dumper
$ pip install -r requirements.txt
$ python payload_dumper.py payload.bin
# You will find the dumped payload in /storage/emulated/0/payload_dumper/output
Sources
https://explainshell.com/explain?cmd=sudo+apt-get+update+&&+sudo+apt-get+upgrade
https://github.com/python/cpython
https://packaging.python.org/tutorials/installing-packages/
https://github.com/vm03/payload_dumper
https://termux.com/
https://wiki.termux.com/wiki/Python
https://source.android.com/devices/bootloader/partitions-images
https://wiki.termux.com/wiki/Internal_and_external_storage
Nice!
I am getting the following error and I cannot figure out how to fix it:
Code:
Processing LOGO partitionTraceback (most recent call last):
File "payload_dumper.py", line 157, in <module>
dump_part(part)
File "payload_dumper.py", line 100, in dump_part
out_file = open('%s/%s.img' % (args.out, part.partition_name), 'wb')
FileNotFoundError: [Errno 2] No such file or directory: 'output/LOGO.img'
Thank you a lot Man!
This method working great with OnePlus 7 pro. Extracted system.img from Hydrogen, will try reflash it to Oxygen rom.
GuestK00376 said:
Introduction
This tutorial will teach you how to specifically extract the boot.img from your OTA/ROM's payload.bin on your Android device, rather than a computer.
In addition to this, you will also have the ability to access all other img files that are packaged with the payload.bin.
The boot partition contains a kernel image and a RAM disk combined via mkbootimg.
You would generally want to keep a copy of your current OTA/ROM's boot.img in the event that you want to recover your devices boot partition when you want to switch kernels, or repairing a corrupted device due to kernel/RAM disk issues.
Prerequisites
Termux Installed: Official Play Store Link | Official F-Droid Link
payload_dumper: Official GitHub Link
To get started
Code:
# Extract payload_dumper folder contents to: /storage/emulated/0/payload_dumper/
# Extract payload.bin from your OTA/ROM to: /storage/emulated/0/payload_dumper/
$ pkg install python -y
$ pip install --upgrade pip
$ apt update && apt upgrade -y
$ termux-setup-storage
# Allow Termux access photos, media a
[QUOTE="GuestK00376, post: 81933401"]
Introduction
This tutorial will teach you how to specifically extract the boot.img from your OTA/ROM's payload.bin on your Android device, rather than a computer.
In addition to this, you will also have the ability to access all other img files that are packaged with the payload.bin.
The boot partition contains a kernel image and a RAM disk combined via mkbootimg.
You would generally want to keep a copy of your current OTA/ROM's boot.img in the event that you want to recover your devices boot partition when you want to switch kernels, or repairing a corrupted device due to kernel/RAM disk issues.
Prerequisites
Termux Installed: Official Play Store Link | Official F-Droid Link
payload_dumper: Official GitHub Link
To get started
[CODE]# Extract payload_dumper folder contents to: /storage/emulated/0/payload_dumper/
# Extract payload.bin from your OTA/ROM to: /storage/emulated/0/payload_dumper/
$ pkg install python -y
$ pip install --upgrade pip
$ apt update && apt upgrade -y
$ termux-setup-storage
# Allow Termux access photos, media and files on your device
$ cd storage/shared/payload_dumper
$ pip install -r requirements.txt
$ python payload_dumper.py payload.bin
# You will find the dumped payload in /storage/emulated/0/payload_dumper/output
Sources
https://explainshell.com/explain?cmd=sudo+apt-get+update+&&+sudo+apt-get+upgrade
https://github.com/python/cpython
https://packaging.python.org/tutorials/installing-packages/
https://github.com/vm03/payload_dumper
https://termux.com/
https://wiki.termux.com/wiki/Python
https://source.android.com/devices/bootloader/partitions-images
https://wiki.termux.com/wiki/Internal_and_external_storage
Click to expand...
Click to collapse
nd files on your device
$ cd storage/shared/payload_dumper
$ pip install -r requirements.txt
$ python payload_dumper.py payload.bin
# You will find the dumped payload in /storage/emulated/0/payload_dumper/output[/CODE]
[/QUOTE]
Started with this "$ pkg install python -y" but installing process was ending with ... see my screen shot.
ltth said:
Started with this "$ pkg install python -y" but installing process was ending with ... see my screen shot.
Click to expand...
Click to collapse
Seems that the repo isn't hosted by bintray anymore: https://github.com/termux/science-packages/commit/6485c133c539ec20663cf5807a3d1e5db3c8e917
EDIT: I followed the instructions here to change the repo using the termux-change-repo command.
I'm getting the following
cd: storage/shared/payload_dumper: Permission denied
even when no permissions denied on both termux and ternux api.
What am I doing wrong?
Onrplus 9 pro
hello guys, how to downgrade python, what command?
psychoela said:
View attachment 5508737hello guys, how to downgrade python, what command?
Click to expand...
Click to collapse
Download python 3.7
Had the same error
trying to extract boot.img from a rom, getting the following error...
" MutableMapping = collections.MutableMapping
AttributeError: module 'collections' has no attribute 'MutableMapping' "
any way to fix?
Does this still work
SidneyD said:
Seems that the repo isn't hosted by bintray anymore: https://github.com/termux/science-packages/commit/6485c133c539ec20663cf5807a3d1e5db3c8e917
EDIT: I followed the instructions here to change the repo using the termux-change-repo command.
Click to expand...
Click to collapse
Can you share your steps please
This doesn't work!!
Edit:
This working fine. Just figured out the play Store version of termux is outdated.
This is still working as of Jan 2023. A couple of changes need to be made.
- download Termux from F-droid servers instead.
- install openssl-tool in termux (type openssl and follow instructions)
I was able to extract the payload easily.
Dear everyone,
I'd like to backup all apps and their data and settings from my old phone (Android 4.0.4, have a root shell if needed) and restore them to a new phone (Android 10) which I don't want to root. I've considered the following options, but would be glad about some guidance.
1. Backup with adb backup, restore with adb restore
This would be the obvious choice, I guess. However, my old phone is an Xperia Ray with stock ROM, which cannot run adb backup.
If I try to backup an app, I get the following in adb logcat:
Code:
V/BackupManagerService( 290): Requesting full backup: apks=false shared=false all=false pkgs=[Ljava.lang.String;@2c36b0b8
I/BackupManagerService( 290): Beginning full backup...
D/BackupManagerService( 290): Starting backup confirmation UI, token=940595255
I/ActivityManager( 290): START {act=fullback flg=0x10000000 cmp=com.android.backupconfirm/.BackupRestoreConfirmation (has extras)} from pid 290
E/BackupManagerService( 290): Unable to launch full backup confirmation
D/BackupManagerService( 290): Full backup processing complete.
The "Unable to launch full backup confirmation" is because BackupRestoreConfirmation.apk is missing.
I downloaded a system image from https://dl.google.com/android/repository/sys-img/android/sysimg_armv7a-14_r02.zip, extracted the files with unyaffs, and tried installing the BackupRestoreConfirmation.apk with adb install. This fails with INSTALL_FAILED_DEXOPT because it's an odexed app.
Using a root shell, I copied the extracted BackupRestoreConfirmation.apk and BackupRestoreConfirmation.odex to /system/app and rebooted the phone. I can see that the files are there:
Code:
$ adb shell ls -l /system/app | grep -i 'backup'
-rw-r--r-- root root 88093 2011-11-24 00:00 BackupRestoreConfirmation.apk
-rw-r--r-- root root 11816 2011-11-24 00:00 BackupRestoreConfirmation.odex
-rw-r--r-- root root 84730 2012-05-08 20:51 GoogleBackupTransport.apk
However, it still does not show up among the system apps:
Code:
$ adb shell pm list packages -f | grep -i 'backup'
package:/system/app/GoogleBackupTransport.apk=com.google.android.backup
I was expecting an entry for com.android.backupconfirm.
Q: Am I missing anything to install it as a system app? Is there any configuration file it needs to be added to?
2. Backup with a modified adb backup, restore with adb restore
Since I have root access, would it be possible to replace some code on my device such that adb backup does not require a confirmation?
adb backup calls /system/bin/bu, which runs /system/framework/bu.jar. From https://android.googlesource.com/pl...fs/tags/android-4.0.4_r2.1/cmds/bu?autodive=0, it seems that this calls somewhere into https://android.googlesource.com/pl...roid-4.0.4_r2.1/core/java/android/app/backup/, but is not directly responsible for the confirmation dialog.
Going backwards instead, "Unable to launch full backup confirmation" is printed from https://android.googlesource.com/pl...android/server/BackupManagerService.java#4911, which lives in /system/framework/services.jar.
Q: How complicated is it to compile and install a modified version of services.jar/services.odex? Is this even possible in a live system?
3. Create .ab file without adb backup, restore with adb restore
Since I have root access, I can copy out all the files I want. An .ab file is a compressed .tar archive with a special 24-byte header. If I knew which files go into the .ab file, and maybe in which order, with which permissions and user ids, and how to create the 24-byte header, I could manually create the .ab files to feed to adb restore.
Q: Is there a generic recipe for creating a .ab file for an app? Or does each app decide individually which files to backup and restore?
Thank you for any hints!
May be this helps you:
Backup android app, data included, no root needed, with adb
Backup android app, data included, no root needed, with adb - android-backup-apk-and-datas.md
gist.github.com
jwoegerbauer said:
May be this helps you:
Backup android app, data included, no root needed, with adb
Backup android app, data included, no root needed, with adb - android-backup-apk-and-datas.md
gist.github.com
Click to expand...
Click to collapse
Thank you! Unfortunately, this also uses adb backup to pull the data, for which I need to find a way to install com.android.backupconfirm on my device.
I use ApkExport* from Playstore on my non-rooted 10+ to backup all my loaded apps.
Have done a full restore using only the stored copies; worked perfectly. Cut down load time substantially... took Playwhore out of the loop.
*freeware, no ads, no internet connection
blackhawk said:
I use ApkExport* from Playstore on my non-rooted 10+ to backup all my loaded apps.
Click to expand...
Click to collapse
Thank you! But if I see correctly, this only copies the .apk files (basically, the /data/app directory), but does not export their settings and data to be imported to a new device.
f0k said:
Thank you! But if I see correctly, this only copies the .apk files (basically, the /data/app directory), but does not export their settings and data to be imported to a new device.
Click to expand...
Click to collapse
This is correct. Probably better this way especially if the phone was compromised by malware.
My important apps that are hard to reconfigure are backed up separately. I deliberately picked ones that allow for complete backup like Poweramp, PD MDM and ColorNote.
f0k said:
Thank you! Unfortunately, this also uses adb backup to pull the data, for which I need to find a way to install com.android.backupconfirm on my device.
Click to expand...
Click to collapse
The mentioned missing APKs you can fetch here:
Root - Stock APK's
Directory of \m830\rom\app 10/12/2012 05:21 PM 143,392 AccuweatherDaemon.apk 10/12/2012 05:21 PM 3,064,214 AccuweatherWidget.apk 10/12/2012 05:21 PM 5,808,937 AccuweatherWidget_Main.apk 10/12/2012 05:21 PM 124,220 Activation.apk 10/12/2012 05:21 PM...
androidforums.com
jwoegerbauer said:
The mentioned missing APKs you can fetch here:
Root - Stock APK's
Directory of \m830\rom\app 10/12/2012 05:21 PM 143,392 AccuweatherDaemon.apk 10/12/2012 05:21 PM 3,064,214 AccuweatherWidget.apk 10/12/2012 05:21 PM 5,808,937 AccuweatherWidget_Main.apk 10/12/2012 05:21 PM 124,220 Activation.apk 10/12/2012 05:21 PM...
androidforums.com
Click to expand...
Click to collapse
The download link does not work any more. However, as described above, I already extracted the missing .apk and .odex from an official sysimg from https://dl.google.com/android/repository/sys-img/android/sysimg_armv7a-14_r02.zip. That .apk is 88093 bytes and the .odex is 11816 bytes. The link you posted had a .apk of 15089 bytes and misses the .odex. Not sure if this is relevant.
In any case, user "animania260" in the thread you posted had the same problem as me: I copied the .apk and .odex into /system/app and rebooted, but adb backup still fails with the same error, and /system/app/BackupRestoreConfirmation.apk is not listed among the installed apps (adb shell pm list packages -f).
Is there anything else that needs to be done to get the phone to accept a new system app? Or are there any special requirements for system apps? Do they need to be signed differently than what's included in the official sysimg, for example?
Another route could be to compile https://android.googlesource.com/pl....0.4_r2.1/packages/BackupRestoreConfirmation/ into a deodexed .apk and install it as a user app, but I don't know how to do that yet, and I don't know if https://android.googlesource.com/pl...android/server/BackupManagerService.java#4988 will just happily start a user app if it happens to provide an intent of the correct name.
f0k said:
I copied the .apk and .odex into /system/app and rebooted, but adb backup still fails with the same error, and /system/app/BackupRestoreConfirmation.apk is not listed among the installed apps (adb shell pm list packages -f).
Is there anything else that needs to be done to get the phone to accept a new system app? Or are there any special requirements for system apps? Do they need to be signed differently than what's included in the official sysimg, for example?
Click to expand...
Click to collapse
IMO the APKs in question must NOT get simply 1:1 copied into /system/app but also renamed
Example:
Code:
/system/app/BackRestoreConfirmation-1.apk
and additionally given 0644 permission. Phone has to get re-booted afterwards, too, if that's not automatically done.
But I may err as always ...
jwoegerbauer said:
IMO the APKs in question must NOT get simply 1:1 copied into /system/app but also renamed
Click to expand...
Click to collapse
Renaming the package did not help, but this time I started adb logcat directly after adb reboot, and found something relevant that came up early in the boot process:
Code:
I/PackageManager( 291): /system/app/BackupRestoreConfirmation-1.apk changed; collecting certs
I/dalvikvm( 291): DexOpt: mismatch dep signature for '/system/framework/core.odex'
E/dalvikvm( 291): /system/app/BackupRestoreConfirmation-1.apk odex has stale dependencies
E/dalvikvm( 291): odex source not available -- failing
W/PackageManager( 291): StaleDexCacheError when reading apk: /system/app/BackupRestoreConfirmation-1.apk
W/PackageManager( 291): dalvik.system.StaleDexCacheError: /system/app/BackupRestoreConfirmation-1.apk
W/PackageManager( 291): at dalvik.system.DexFile.isDexOptNeeded(Native Method)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.performDexOptLI(PackageManagerService.java:3080)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.scanPackageLI(PackageManagerService.java:3634)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.scanPackageLI(PackageManagerService.java:2963)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.scanDirLI(PackageManagerService.java:2775)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:1066)
W/PackageManager( 291): at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:837)
W/PackageManager( 291): at com.android.server.ServerThread.run(SystemServer.java:167)
D/PackageManager( 291): No files in app dir /vendor/app
So if I interpret this correctly, there really is a problem with the signatures. Just out of curiosity, I tried whether apps in /vendor/app would be treated differently. I created /vendor/app, moved the .apk and .odex there and rebooted, but get the same error just with different paths.
Some googling informs me that this is probably because the /system/framework/core.odex on my device is not the same as the framework/core.odex in the sysimg I took the odexed BackupRestoreConfirmation.apk from.
From https://android.googlesource.com/pl...roid-4.2.2_r1/vm/analysis/DexPrepare.cpp#1142, it seems it would be trivial to just go ahead and replace the signatures of all dependencies in BackupRestoreConfirmation.odex (with a hexdump, I can see there are nine dependencies). Is the .odex signed to catch such a modification, or would it pass through? And how would I obtain the SHA-1 signatures from the source DEX files? My device apparently knows them.
/edit: They're part of the .odex header, the signature is at offset 0x34 and has 20 bytes, so I could copy out the SHA-1 signatures from the dependencies on my phone and implant them in BackupRestoreConfirmation.odex. But that signature check will be there for a reason, I assume the .odex will point at specific offsets in its dependencies and crash if the dependencies are not the original ones.
So I will either have to recompile BackupRestoreConfirmation.apk from source with WITH_DEXPREOPT=0 or to deodex the compiled one, so I don't need a .odex file at all.
I'm learning a lot more about the internals of Android than I ever intended to
Finally got around continuing this quest, and it worked! I deodexed the BackupRestoreConfirmation.apk, resigned it, installed it as a system app, and can now run adb backup on my Xperia Ray, Android 4.0.4 ICS.
For posterity, I am documenting all required steps (assuming a Linux machine).
1. Download and extract a stock system image
Download a system image for Android 4.0.4: https://dl.google.com/android/repository/sys-img/android/sysimg_armv7a-14_r02.zip
Unzip it.
Extract the image with unyaffs (can be installed with apt install unyaffs in Ubuntu):
Code:
mkdir /tmp/sysimg
unyaffs armeabi-v7a/system.img /tmp/sysimg
It will say Warning: Can't restore owner/group attribute, run unyaffs as root, that can be safely ignored, we do not need files to be owned by root.
2. Deodex BackupRestoreConfirmation.apk
Download smali and baksmali (https://github.com/JesusFreke/smali, find download link in the README), put the two .jar files somewhere (I assume /tmp)
Extract the .odex file. java -jar /tmp/baksmali*.jar x --help is pretty self-explanatory. I did:
Code:
mkdir /tmp/backuprestore
java -jar /tmp/baksmali*.jar x -a 14 -d /tmp/sysimg/framework -o /tmp/backuprestore/out /tmp/sysimg/app/BackupRestoreConfirmation.odex
Assemble the smali files into a .dex file. Again, java -jar /tmp/smali*.jar a --help is pretty self-explanatory. I did:
Code:
java -jar /tmp/smali*.jar a -a 14 -o /tmp/backuprestore/classes.dex /tmp/backuprestore/out
Add the .dex file to the .apk file. We will copy the .apk to be sure.
Code:
cp /tmp/sysimg/app/BackupRestoreConfirmation.apk /tmp/backuprestore
cd /tmp/backuprestore
zip BackupRestoreConfirmation.apk classes.dex
It is not needed to do a new zipalign. If you're curious, you can install it (in Ubuntu, sudo apt install zipalign) and run zipalign -c 4 BackupRestoreConfirmation.apk && echo aligned || echo not aligned to check it.
If you try to install the file with adb install BackupRestoreConfirmation.apk now, it will say: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES], because it is not correctly signed any longer. We need to resign it.
Install signapk (in Ubuntu, sudo apt install signapk. If you want, you can first verify that it is indeed not signed:
Code:
jarsigner -verify BackupRestoreConfirmation.apk
It should say jarsigner: java.lang.SecurityException: SHA1 digest error for classes.dex.
The original .apk is signed correctly; with
Code:
jarsigner -verify -verbose -certs /tmp/sysimg/app/BackupRestoreConfirmation.apk
you will see that it was signed by "[email protected], CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US" with a 2048-bit key.
Create a key for signing. This can be done with keytool, but this will set up a keystore that will be left behind. Instead, I followed a guide from https://sites.google.com/site/delocatedsystems/android/howto/create-cert-signapk, using 2048 instead of 1024 bits:
Code:
openssl genrsa -out key.pem 2048
openssl req -new -key key.pem -out request.pem # this will ask for some data, make up something
openssl x509 -req -days 9999 -in request.pem -signkey key.pem -out certificate.pem
openssl pkcs8 -topk8 -outform DER -in key.pem -inform PEM -out key.pk8 -nocrypt
Finally, we can sign the .apk:
Code:
signapk certificate.pem key.pk8 BackupRestoreConfirmation.apk BackupRestoreConfirmation_signed.apk
mv BackupRestoreConfirmation{,_unsigned}.apk
mv BackupRestoreConfirmation{_signed,}.apk
And optionally verify it with jarsigner -verify BackupRestoreConfirmation.apk -certs -verbose.
3. Install BackupRestoreConfirmation.apk
If you just install it with adb install BackupRestoreConfirmation.apk, it will be installed as user app. If you then run adb backup, the confirmation dialog will appear as intended. But if you confirm it, you will get:
Code:
D/BackupManagerService( 292): acknowledgeFullBackupOrRestore : token=1892071259 allow=true
D/AndroidRuntime( 8310): Shutting down VM
W/dalvikvm( 8310): threadid=1: thread exiting with uncaught exception (group=0x2b542210)
E/AndroidRuntime( 8310): FATAL EXCEPTION: main
E/AndroidRuntime( 8310): java.lang.SecurityException: acknowledgeFullBackupOrRestore: User 10104 does not have android.permission.BACKUP.
(Uninstall again with adb shell pm uninstall com.android.backupconfirm if needed.) So the .apk must be installed as a system app to have the android.permission.BACKUP permission.
To do so, copy the .apk file to your device:
Code:
adb push BackupRestoreConfirmation.apk /data/local/tmp
Now open a root shell on the device. This can be done via an exploit I explained in another post. Assuming you are in a root shell on the device, do:
Code:
remount -o rw,remount /system
cat /data/local/tmp/BackupRestoreConfirmation.apk > /system/app/BackupRestoreConfirmation.apk
chmod 644 /system/app/BackupRestoreConfirmation.apk
remount -o ro,remount /system
exit
In my case, the app was picked up directly, without having to reboot the phone. Verify with:
Code:
adb shell pm list packages -f | grep -F backup
If it worked, the list will contain:
Code:
package:/system/app/BackupRestoreConfirmation.apk=com.android.backupconfirm
Otherwise you may need to reboot your phone with adb reboot.
When you now try to backup an app with adb backup -f theappname.ab -apk com.theappname (where com.theappname is taken from the list of user apps produced with adb shell pm list packages -3), you may find that instead of a 0-byte file that you get with a missing BackupRestoreConfirmation.apk, you get a 41-byte file, which is only a moderate improvement. In adb logcat, you may find:
Code:
V/BackupManagerService( 811): Requesting full backup: apks=false shared=false all=false pkgs=[Ljava.lang.String;@4181ffc8
W/BackupManagerService( 811): Unknown package '-apk' 'com.theappname', skipping
It may not be apparent at first, but the quotes around -apk and com.theappname in the error message are not put there by BackupManagerService, they are introduced by recent versions of adb to safeguard against a shell injection. This is why -apk is not detected as a flag, and the package name is not recognized as a package. The solution is to downgrade to an earlier version of adb, as explained in more detail on https://android.stackexchange.com/a/132921.
To check the version of adb on your computer, run:
Code:
adb version
To check the version of adb on the phone, run:
Code:
adb shell adb version
In my case, the phone is running 1.0.29, but downgrading adb to 1.0.31 was enough. Precompiled versions are available for Linux, Mac, Windows.
Finally, you can backup apps with adb backup (at least those apps which support it). Phew!
(PS: If you want to run adb backup -shared, you will need to deodex and install SharedStorageBackup.apk. Didn't try.)