diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5e8e39..97a719a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: - name: Build run: | - ./gradlew assembleDebug --no-daemon --stacktrace + ./gradlew assembleDebug --no-daemon --stacktrace --warning-mode=all cp -f app/build/outputs/apk/debug/app-debug.apk ${{ env.repo }}-${{ env.version }}.apk - name: Attest diff --git a/app/build.gradle b/app/build.gradle index 8fc27b8..c8bad97 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,13 +4,13 @@ plugins { android { namespace = 'com.saradabar.easyblu' - compileSdk = 34 + compileSdk = 35 defaultConfig { minSdk = 24 //noinspection ExpiredTargetSdkVersion targetSdk = 22 - versionCode = 7 + versionCode = 6 versionName = "3.0" proguardFiles += 'proguard-rules.pro' multiDexEnabled = false @@ -42,7 +42,7 @@ android { lintOptions { abortOnError = false - ignore 'SdCardPath', 'ProtectedPermissions', 'ReassignedVariable', 'HardcodedText', 'ResultOfMethodCallIgnored', 'SetTextI18n' + ignore 'SdCardPath', 'ProtectedPermissions', 'ReassignedVariable', 'HardcodedText', 'SetTextI18n', 'DiscouragedApi' } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 889fa9d..7ccdf8d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,9 +13,10 @@ + android:screenOrientation="landscape" + android:windowSoftInputMode="stateAlwaysHidden"> diff --git a/app/src/main/java/com/saradabar/easyblu/MainActivity.java b/app/src/main/java/com/saradabar/easyblu/MainActivity.java index a09a8d0..aa1582f 100644 --- a/app/src/main/java/com/saradabar/easyblu/MainActivity.java +++ b/app/src/main/java/com/saradabar/easyblu/MainActivity.java @@ -7,6 +7,7 @@ import android.content.ServiceConnection; import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; @@ -29,15 +30,16 @@ import jp.co.benesse.dcha.dchaservice.IDchaService; +/** @noinspection ResultOfMethodCallIgnored*/ public class MainActivity extends Activity { private static final String BLOCK_DEVICE = "/dev/block/platform/bootdevice/"; - private static final String BOOTDEVICE = BLOCK_DEVICE + "mmcblk0"; // 内部ストレージ + private static final String BOOTDEVICE = BLOCK_DEVICE + "mmcblk0"; // eMMC private static final String PART24 = BOOTDEVICE + "p24"; // CT3 で新規パーティションを作成した際の割振番号 private static final String FRP = "frp"; private static final String EXPDB = "expdb"; private static final String FRP_BLOCK = BLOCK_DEVICE + "by-name/" + FRP; // ro.frp.pst と同様 - private static final String FRP_CLONE = "/cache/" + FRP; // FRP のバックアップ + private static final String FRP_COPY = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/" + FRP; // /sdcard/Download/frp に抽出 private static final String APP_PATH = "/data/data/com.saradabar.easyblu/cache/"; // getCacheDir() + "/" と同様 private static final boolean CT3 = Build.PRODUCT.equals("TAB-A04-BR3"); // CT3 かどうかの真偽値 @@ -51,14 +53,13 @@ public class MainActivity extends Activity { private static final String SETTINGS_PACKAGE = "com.android.settings"; private static final String SETTINGS_ACTIVITY = SETTINGS_PACKAGE + ".Settings"; // 設定アプリのメインアクティビティ - private static final String GETENFORCE = "getenforce"; + private static final String GETENFORCE = "getenforce"; // SELinux ポリシー強制状態の確認 private static final String PERMISSIVE = "Permissive"; // デバイスを書き換えられるかどうかの確認 private static final String SHRINKER = "shrinker"; // 純正 boot の CTX/CTZ 専用。`getenforce` を実行 private static final String MTK_SU = "mtk-su"; // CT3 専用。root シェルを実行 private static final String PARTED = "parted"; // CT3 でデバイスブロックの書き換えに必須 private static final String PARTED_CMD = APP_PATH + PARTED + " -s " + BOOTDEVICE + " "; // parted のコマンド短縮 - /** * @param savedInstanceState If the activity is being re-initialized after * previously being shut down then this Bundle contains the data it most @@ -79,11 +80,33 @@ protected void onCreate(Bundle savedInstanceState) { init(); } + /** + * APK の assets 内のファイルを cache にコピー。実行権限も付与。 + * ただし、{@code frp} のみ、コピー先が {@code /sdcard/Download} である + * @param file assets のファイル名 + * @author Kobold + * @since v1.0 + */ + private void copyAssets(String file) { + File bin = new File(file.equals(FRP) ? Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) : getCacheDir(), file); + try { + InputStream inputStream = getAssets().open(file); + FileOutputStream fileOutputStream = new FileOutputStream(bin, false); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) >= 0) fileOutputStream.write(buffer, 0, length); + if (!file.equals(FRP)) bin.setExecutable(true); // chmod +x bin を省略 + fileOutputStream.close(); + inputStream.close(); + } catch (IOException ignored) { + } + } + /** * 関数の呼出しに使用 * @param func Runnable 形式 * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void callFunc(Runnable func) { new Handler(getMainLooper()).post(func); @@ -92,22 +115,22 @@ private void callFunc(Runnable func) { /** * コマンドの実行に使用。 * CT3 の場合は、常に {@code mtk-su} を実行 - * @param str 実行コマンド + * @param cmd 実行コマンド * @return 必要な場合は文字列を取得 * @throws RuntimeException ランタイムスロー * @see #parted(String) * @author Kobold - * @since v2.1 + * @since v3.0 */ @NonNull - private StringBuilder exec(String str) throws RuntimeException { + private StringBuilder exec(String cmd) throws RuntimeException { Process process; BufferedWriter bufferedWriter; BufferedReader bufferedReader; StringBuilder stringBuilder = new StringBuilder(); try { - process = Runtime.getRuntime().exec(CT3 ? APP_PATH + MTK_SU + " -c " + str : str + System.lineSeparator()); + process = Runtime.getRuntime().exec(CT3 ? APP_PATH + MTK_SU + " -c " + cmd : cmd + System.lineSeparator()); bufferedWriter = new BufferedWriter(new OutputStreamWriter(process.getOutputStream())); bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); bufferedWriter.write("exit" + System.lineSeparator()); @@ -126,28 +149,6 @@ private StringBuilder exec(String str) throws RuntimeException { return stringBuilder; } - /** - * APK の assets 内のファイルを cache にコピー - * @param file assets のファイル名 - * @author Kobold - * @since v1.0 - * @noinspection ResultOfMethodCallIgnored - */ - private void copyAssets(String file) { - File bin = new File(getCacheDir(), file); - try { - InputStream inputStream = getAssets().open(file); - FileOutputStream fileOutputStream = new FileOutputStream(bin, false); - byte[] buffer = new byte[1024]; - int length; - while ((length = inputStream.read(buffer)) >= 0) fileOutputStream.write(buffer, 0, length); - if (!file.equals(FRP)) bin.setExecutable(true); // chmod +x bin を省略 - fileOutputStream.close(); - inputStream.close(); - } catch (IOException ignored) { - } - } - /** * 文字列をコンソール上に出力 * @param str 出力する文字列 @@ -155,7 +156,7 @@ private void copyAssets(String file) { * @see #warning(String) * @see #error(Exception) * @author Kobold - * @since v2.1 + * @since v3.0 */ private void echo(String str) { TextView textView = findViewById(R.id.text_console); @@ -170,7 +171,7 @@ private void echo(String str) { * @param str 出力したい文字列 * @see #echo(String) * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void notify(String str) { echo("- 通知:" + str); @@ -181,7 +182,7 @@ private void notify(String str) { * @param str 出力したい文字列 * @see #echo(String) * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void warning(String str) { echo("- 警告:" + str); @@ -195,7 +196,7 @@ private void warning(String str) { * @see #echo(String) * @see #init() * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void error(Exception e) { echo("- エラー:" + System.lineSeparator() + e); @@ -263,7 +264,7 @@ private void init() { * @see #getBlockDeviceSize() * @see #overwriteFrp() * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void setup() { // retry() と同様 exec(APP_PATH + (CT3 ? MTK_SU : SHRINKER)); @@ -278,38 +279,6 @@ private void setup() { // retry() と同様 } } - /** - * parted のコマンドを実行 - * @param cmd parted のコマンド - * @see #exec(String) - * @see #getBlockDeviceSize() - * @see #fixExpdb() - * @see #createFrp() - * @author Syuugo - * @since v2.1 - */ - private void parted(String cmd) { - exec(PARTED_CMD + cmd); - } - - /** - * CTX/CTZ にて、FRP を上書き - * @see #copyAssets(String) - * @see #copyFile(String, String) - * @author Kobold - * @since v1.0 - */ - private void overwriteFrp() { - copyAssets(FRP); - try { - copyFile(FRP_BLOCK, FRP_CLONE); // オリジナルの FRP を cache パテにコピー - copyFile(APP_PATH + FRP, FRP_BLOCK); // 修正済み FRP を適用 - } catch (Exception e) { - error(e); - } - callFunc(this::openSettings); - } - /** * DchaService{@code copyUpdateImage} を実行。 * システム権限でファイルの操作が可能 @@ -318,7 +287,7 @@ private void overwriteFrp() { * @throws RemoteException サービススロー * @see #overwriteFrp() * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void copyFile(String src, String dst) throws RemoteException { if (!bindService(new Intent(DCHA_SERVICE).setPackage(DCHA_PACKAGE), new ServiceConnection() { @@ -344,29 +313,45 @@ public void onServiceDisconnected(ComponentName componentName) { } /** - * CT3 において、expdb が修正されているかを確認する関数 + * CTX/CTZ にて、FRP を上書き + * @see #copyAssets(String) + * @see #copyFile(String, String) + * @author Kobold + * @since v1.0 + */ + private void overwriteFrp() { + copyAssets(FRP); + try { + copyFile(FRP_COPY, FRP_BLOCK); // 修正済み FRP を適用 + notify(FRP_COPY + " を削除しています。"); + new File(FRP_COPY).delete(); + } catch (Exception e) { + error(e); + } + callFunc(this::openSettings); + } + + /** + * parted のコマンドを実行 + * @param cmd parted のコマンド + * @see #exec(String) * @see #getBlockDeviceSize() * @see #fixExpdb() * @see #createFrp() * @author Syuugo - * @since v2.0 + * @since v3.0 */ - private void checkFixed() { - if (getBlockDeviceSize().contains("124MB 134MB")) { // 純正 expdb のセクタ範囲 - notify(EXPDB + " は修正されていません。"); - } else { - notify(EXPDB + " は既に修正済みです。"); - notify("既存の " + FRP + " を削除します。"); - parted("rm 24"); - } - callFunc(this::fixExpdb); + private void parted(String cmd) { + exec(PARTED_CMD + cmd); } /** - * mmcblk0 のパーティションの詳細を確認する関数。parted のコピーも行う + * mmcblk0 のパーティションの詳細を確認する関数。 + * {@code parted} のコピーも行う * @return パーティションの詳細 + * @see #checkFixed() * @author Syuugo - * @since v2.1 + * @since v3.0 */ @NonNull private String getBlockDeviceSize() { @@ -375,6 +360,25 @@ private String getBlockDeviceSize() { return exec(PARTED_CMD + "print").toString(); } + /** + * CT3 において、expdb が修正されているかを確認する関数 + * @see #getBlockDeviceSize() + * @see #fixExpdb() + * @see #createFrp() + * @author Syuugo + * @since v2.0 + */ + private void checkFixed() { + if (getBlockDeviceSize().contains("124MB 134MB")) { // 純正 expdb のセクタ範囲 + notify(EXPDB + " は修正されていません。"); + } else { + notify(EXPDB + " は既に修正済みです。"); + notify("既存の " + FRP + " を削除します。"); + parted("rm 24"); + } + callFunc(this::fixExpdb); + } + /** * expdb の修正を行う関数 * @see #checkFixed() @@ -410,15 +414,16 @@ private void createFrp() { parted("toggle 24 msftdata"); notify(PART24 + " を上書き修正します。"); copyAssets(FRP); - exec("dd if=" + APP_PATH + FRP + " of=" + PART24); // 必ずフルパス - callFunc(this::doBootloader); + exec("dd if=" + Environment.getExternalStorageDirectory() + "/" + FRP + " of=" + PART24); // 必ずフルパス + callFunc(this::openSettings); } + //TODO: 要修正 /** * bootloader へ直接再起動する関数 * @see #openSettings() * @author Syuugo - * @since v2.1 + * @since v3.0 */ private void doBootloader() { notify("すべての修正が完了しました!"); diff --git a/docs/README.md b/docs/README.md index 6d248da..b8c4851 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,7 +36,7 @@ fastboot flashing unlock - `count_dcha_completed` を削除 - `ignore_dcha_completed` を作成 - `dcha_hash` を作成 - 中身:`echo -n | sha256sum | cut -c-64` + 中身:`echo -n | sha256sum | cut -c-64`:`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` これはパスワードが空の状態 ### lk @@ -65,7 +65,7 @@ fastboot flashing unlock このアプリは以下のライブラリーを使用しています。 -- **shrinker** +- **mali_shrinker_mmap32** (`shrinker`) [SmileTabLabo/CVE-2022-38181: CVE-2022-38181 PoC for CTX(TAB-A05-BD) and CTZ(TAB-A05-BA1)](https://github.com/SmileTabLabo/CVE-2022-38181) - **mtk-su** [Amazing Temp Root for MediaTek ARMv8 \[2020-08-24\] | XDA Forums](https://xdaforums.com/t/3922213/) diff --git a/gradle.properties b/gradle.properties index 738bc5c..2ce230c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,2 @@ org.gradle.configuration-cache=true org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 -org.gradle.parallel=true