APKEditor icon indicating copy to clipboard operation
APKEditor copied to clipboard

baksmali

Open Veha0001 opened this issue 1 year ago • 1 comments

Describe the bug Well I don't change any file in smali folder. And Build with '-no-cache' so it didn't use copy of .cache/classes*.dex . And after rebuilt.......... (At log...)

To Reproduce Steps to reproduce the behavior:

  1. Used version '1.4.1'
  2. Operating system 'Androd(Termux'
  3. Command 'apkedit b -i . -o file.apk -no-cache'

Log/Stacktrace


➜  ~ cd Download*
➜  Downloads ls
kotatsu-7.6.1-release.apk
➜  Downloads which apkedit
apkedit: aliased to java -jar /data/data/com.termux/files/home/.l
ocal/bin/APKEditor.jar
➜  Downloads ls
kotatsu-7.6.1-release.apk
➜  Downloads apkedit -v
APKEditor version 1.4.1, ARSCLib version 1.3.5
➜  Downloads apkedit d -i kotatsu-7.6.1-release.apk -o mangaapp
00.000 I: [DECOMPILE] Using: APKEditor version 1.4.1, ARSCLib ver
sion 1.3.5
      -t = xml
      -i = kotatsu-7.6.1-release.apk
      -o = mangaapp
 __________________________________
00.072 I: [DECOMPILE] Loading ...
00.458 I: [DECOMPILE] Decompiling to xml ...
02.438 I: [DECOMPILE] Initializing android framework ...
02.438 I: [DECOMPILE] Loading android framework for version: 35
02.670 I: [DECOMPILE] Initialized framework: android-35 (15)
02.790 I: [DECOMPILE] [SANITIZE]: Sanitizing paths ...
02.813 I: [DECOMPILE] Validating resource names ...
02.988 I: [DECOMPILE] All resource names are valid
02.988 I: [DECOMPILE] Decode: archive-info.json
03.005 I: [DECOMPILE] Decode: uncompressed-files.json
03.042 I: [DECOMPILE] Decoding: AndroidManifest.xml
03.379 I: [DECOMPILE] public.xml: org.koitharu.kotatsu -> package
_1
03.463 I: [DECOMPILE] Res files: resources
08.759 I: [DECOMPILE] Baksmali: classes.dex
26.910 I: [DECOMPILE] Baksmali: classes2.dex
27.742 I: [DECOMPILE] Extracting root files ...
28.079 I: [DECOMPILE] Dumping signatures ...
28.081 I: [DECOMPILE] Saved to: mangaapp
➜  Downloads ls
kotatsu-7.6.1-release.apk  mangaapp
➜  Downloads mangaapp
➜  mangaapp ls
AndroidManifest.xml  resources   smali
archive-info.json    root        uncompressed-files.json
path-map.json        signatures
➜  mangaapp apkedit b -i . -o build.apk -no-cahe
Unknown option: '-no-cahe'
➜  mangaapp apkedit b -i . -o build.apk -no-cache
00.000 I: [BUILD] Using: APKEditor version 1.4.1, ARSCLib version
 1.3.5
             -t = xml
      -no-cache = true
             -i = .
             -o = build.apk
 _________________________
00.093 I: [BUILD] Scanning XML directory ...
00.194 I: [BUILD] Scanning: .
01.463 I: [BUILD] Initializing android framework ...
01.463 I: [BUILD] Loading android framework for version: 35
01.890 I: [BUILD] Initialized framework: android-35 (15)
01.890 I: [BUILD] Set main package id from manifest: @mipmap/ic_l
auncher
01.902 I: [BUILD] Main package id initialized: id = 0x7f, from: @
mipmap/ic_launcher
01.903 I: [BUILD] Encoding attrs ...
02.523 I: [BUILD] Encoding values ...
06.571 I: [BUILD] Scan: package_1/res
06.854 I: [BUILD] Scanned 1356 files: package_1/res
07.853 I: [BUILD] Add manifest: AndroidManifest.xml
07.854 I: [BUILD] Building dex ...
08.730 I: [BUILD] (1/2) Smali: classes.dex
01:16.561 I: [BUILD] (2/2) Smali: classes2.dex
01:19.749 I: [BUILD] Scanning root directory ...
01:19.806 I: [BUILD] Restoring original file paths ...
01:19.993 I: [BUILD] Loading signatures ...
01:20.040 I: [BUILD] Sorting files ...
01:20.089 I: [BUILD] Refreshing resource table ...
01:20.544 I: [BUILD] TableBlock: packages = 1, size = 2729364 byt
es
01:20.547 I: [BUILD] Writing apk...
01:20.595 I: [BUILD] Buffering compress changed files ...
01:30.463 I: [BUILD] Writing files: 1466
01:30.564 I: [BUILD] Writing signature block ...
01:30.600 I: [BUILD] Saved to: build.apk
➜  mangaapp apkedit d -i build.apk -o test
00.000 I: [DECOMPILE] Using: APKEditor version 1.4.1, ARSCLib ver
sion 1.3.5
      -t = xml
      -i = build.apk
      -o = test
 __________________
00.100 I: [DECOMPILE] Loading ...
00.505 I: [DECOMPILE] Decompiling to xml ...
01.758 I: [DECOMPILE] Initializing android framework ...
01.759 I: [DECOMPILE] Loading android framework for version: 35
02.015 I: [DECOMPILE] Initialized framework: android-35 (15)
02.136 I: [DECOMPILE] [SANITIZE]: Sanitizing paths ...
02.159 I: [DECOMPILE] Validating resource names ...
02.286 I: [DECOMPILE] All resource names are valid
02.287 I: [DECOMPILE] Decode: archive-info.json
02.308 I: [DECOMPILE] Decode: uncompressed-files.json
02.353 I: [DECOMPILE] Decoding: AndroidManifest.xml
02.796 I: [DECOMPILE] public.xml: org.koitharu.kotatsu -> package
_1
02.876 I: [DECOMPILE] Res files: resources
09.207 I: [DECOMPILE] Baksmali: classes.dex
26.132 I: [DECOMPILE] Baksmali: classes2.dex
26.986 I: [DECOMPILE] Extracting root files ...
27.241 I: [DECOMPILE] Dumping signatures ...
27.242 I: [DECOMPILE] Saved to: test
➜  mangaapp ls
AndroidManifest.xml  resources   test
archive-info.json    root        uncompressed-files.json
build.apk            signatures
path-map.json        smali
➜  mangaapp ls test/*
test/AndroidManifest.xml  test/path-map.json
test/archive-info.json    test/uncompressed-files.json

test/resources:
package_1

test/root:
DebugProbesKt.bin  assets  kotlin-tooling-metadata.json  okhttp3
META-INF           kotlin  lib                           org

test/signatures:
0_V2.signature.info.bin          2_PADDING.signature.info.bin
1_0x504b4453.signature.info.bin

test/smali:
classes  classes2
➜  mangaapp ls
AndroidManifest.xml  resources   test
archive-info.json    root        uncompressed-files.json
build.apk            signatures
path-map.json        smali
➜  mangaapp pwd
/data/data/com.termux/files/home/Downloads/mangaapp
➜  mangaapp diff -r smali test/smali
diff --color -r smali/classes/androidx/constraintlayout/core/Line
arSystem.smali test/smali/classes/androidx/constraintlayout/core/
LinearSystem.smali
9c9
< .field public static USE_DEPENDENCY_ORDERING:Z = false
---
> .field public static USE_DEPENDENCY_ORDERING:Z
diff --color -r smali/classes/androidx/core/graphics/TypefaceComp
atApi21Impl.smali test/smali/classes/androidx/core/graphics/Typef
aceCompatApi21Impl.smali
7c7
< .field public static sAddFontWeightStyle:Ljava/lang/reflect/Met
hod; = null
---
> .field public static sAddFontWeightStyle:Ljava/lang/reflect/Met
hod;
9c9
< .field public static sCreateFromFamiliesWithDefault:Ljava/lang/
reflect/Method; = null
---
> .field public static sCreateFromFamiliesWithDefault:Ljava/lang/
reflect/Method;
11c11
< .field public static sFontFamily:Ljava/lang/Class; = null
---
> .field public static sFontFamily:Ljava/lang/Class;
13c13
< .field public static sFontFamilyCtor:Ljava/lang/reflect/Constru
ctor; = null
---
> .field public static sFontFamilyCtor:Ljava/lang/reflect/Constru
ctor;
15c15
< .field public static sHasInitBeenCalled:Z = false
---
> .field public static sHasInitBeenCalled:Z
diff --color -r smali/classes/androidx/core/view/ViewCompat.smali
 test/smali/classes/androidx/core/view/ViewCompat.smali
11c11
< .field public static sAccessibilityDelegateCheckFailed:Z = fals
e
---
> .field public static sAccessibilityDelegateCheckFailed:Z
diff --color -r smali/classes/androidx/core/view/WindowInsetsComp
at$BuilderImpl20.smali test/smali/classes/androidx/core/view/Wind
owInsetsCompat$BuilderImpl20.smali
7c7
< .field public static sConstructor:Ljava/lang/reflect/Constructo
r; = null
---
> .field public static sConstructor:Ljava/lang/reflect/Constructo
r;
9c9
< .field public static sConstructorFetched:Z = false
---
> .field public static sConstructorFetched:Z
11c11
< .field public static sConsumedField:Ljava/lang/reflect/Field; =
 null
---
> .field public static sConsumedField:Ljava/lang/reflect/Field;
13c13
< .field public static sConsumedFieldFetched:Z = false
---
> .field public static sConsumedFieldFetched:Z
diff --color -r smali/classes/androidx/core/view/WindowInsetsComp
at$Impl20.smali test/smali/classes/androidx/core/view/WindowInset
sCompat$Impl20.smali
7c7
< .field public static sAttachInfoClass:Ljava/lang/Class; = null
---
> .field public static sAttachInfoClass:Ljava/lang/Class;
9c9
< .field public static sAttachInfoField:Ljava/lang/reflect/Field;
 = null
---
> .field public static sAttachInfoField:Ljava/lang/reflect/Field;
11c11
< .field public static sGetViewRootImplMethod:Ljava/lang/reflect/
Method; = null
---
> .field public static sGetViewRootImplMethod:Ljava/lang/reflect/
Method;
13c13
< .field public static sVisibleInsetsField:Ljava/lang/reflect/Fie
ld; = null
---
> .field public static sVisibleInsetsField:Ljava/lang/reflect/Fie
ld;
15c15
< .field public static sVisibleRectReflectionFetched:Z = false
---
> .field public static sVisibleRectReflectionFetched:Z
diff --color -r smali/classes/androidx/recyclerview/widget/Recycl
erView.smali test/smali/classes/androidx/recyclerview/widget/Recy
clerView.smali
22c22
< .field public static sDebugAssertionsEnabled:Z = false
---
> .field public static sDebugAssertionsEnabled:Z
28c28
< .field public static sVerboseLoggingEnabled:Z = false
---
> .field public static sVerboseLoggingEnabled:Z
diff --color -r smali/classes/coil/util/-SvgUtils.smali test/smal
i/classes/coil/util/-SvgUtils.smali
10c10
< .field public static sActionBarFieldsFetched:Z = false
---
> .field public static sActionBarFieldsFetched:Z
12c12
< .field public static sActionBarOnMenuKeyMethod:Ljava/lang/refle
ct/Method; = null
---
> .field public static sActionBarOnMenuKeyMethod:Ljava/lang/refle
ct/Method;
14c14
< .field public static sDialogFieldsFetched:Z = false
---
> .field public static sDialogFieldsFetched:Z
diff --color -r smali/classes/org/conscrypt/ConscryptFileDescript
orSocket.smali test/smali/classes/org/conscrypt/ConscryptFileDesc
riptorSocket.smali
21c21
< .field private static final DBG_STATE:Z = false
---
> .field private static final DBG_STATE:Z
➜  mangaapp cat smali/classes/org/conscrypt/ConscryptFileDescript
orSocket.smali | grep "static final DBG_STATE:Z"
.field private static final DBG_STATE:Z = false
➜  mangaapp cat test/smali/classes/org/conscrypt/ConscryptFileDes
criptorSocket.smali | grep "static final DBG_STATE:Z"
.field private static final DBG_STATE:Z
➜  mangaapp

Used apk file Any Apk File

Additional context

Veha0001 avatar Oct 05 '24 15:10 Veha0001

This and other differences are common on smali encoding/decoding. But should not break any logic of dex.

For example:

.field public static USE_DEPENDENCY_ORDERING:Z = false .field public static USE_DEPENDENCY_ORDERING:Z

This happens when the field is already initialized on static constructor <clinit> or the field is NOT final and it is redundant to initialize it with false , thus the smali compiler drops value assigning on such field declaration.

REAndroid avatar Oct 05 '24 17:10 REAndroid

diff.log

XML Files:

Original: android:minWidth="280.0dp" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

Rebuilt: android:minWidth="280.0dp" xmlns:android="http://schemas.android.com/apk/res/android">

Why was xmlns:app removed? The xmlns:app attribute is only necessary when custom attributes from the res-auto namespace are used (e.g., attributes for custom views or library components). If the rebuilt XML file doesn’t have any custom attributes that require xmlns:app, the build tools automatically remove it as it's no longer needed.


Smali Files:

Why were = false and = null removed? In smali files, assigning default values like = false for booleans or = null for objects is redundant because the Dalvik/ART virtual machine automatically assigns these values. For example:

Original: .field public static USE_DEPENDENCY_ORDERING:Z = false

Rebuilt: .field public static USE_DEPENDENCY_ORDERING:Z

The build tools remove the = false because it’s unnecessary—booleans default to false in Java/Android. Similarly, = null is removed for objects because the system automatically initializes them to null.


Can the APK build without removing these?

Yes, the APK can still build successfully even if these initializations are not removed. However, they are removed by smali tools during optimization to avoid redundancy.


Why is the rebuilt APK file size larger than the base APK, despite many lines being removed?

The size difference could be caused by several factors:

  1. Recompression Differences: The rebuild process might use different compression settings or methods, leading to a larger APK even if some lines were removed.

  2. Extra Metadata: The build tools may add additional metadata or resources that weren’t present in the original APK, such as debug symbols, extra logs, or optimization-related files.

  3. Resource Alignment: The alignment or packaging of resources might differ between the base APK and the rebuilt APK, impacting the final file size.

These factors can lead to a larger APK, even if some code is removed during the rebuild process.

Veha0001 avatar Oct 06 '24 02:10 Veha0001

Why was xmlns:app removed?

"res-auto" is aapt/aapt2 thing we prioritize to satisfy android os. Processing xml namespace is a bit complex for android world, each namespace represents resource package name (not application id). Most apps out there uses single-resource-package thus we use the name "app" as traditionally used by developers. The challenge comes when dealing with multi-package resource. Check this issue :https://github.com/REAndroid/ARSCLib/issues/40

Why is the rebuilt APK file size larger than the base APK, despite many lines being removed?

  • We don't use different compression method, but we always keep libs and dex uncompressed
  • Resources are built with flat entries, we don't use sparse or packed entries.
  • On xml, we don't strip away namesapces & attribute names (android os only needs resource id)
  • Removing entries doesn't always results size difference check :https://github.com/REAndroid/APKEditor/issues/105#issuecomment-2102611285

In general the priorities of APKEditor are (in order):

  • Build working apk
  • Optimization
  • Resemble output/formats to other build tools

Your points are asked commonly, i appreciate if you can contribute somewhere in our repo as FAQ

REAndroid avatar Oct 06 '24 17:10 REAndroid