normalization and move french to the end
All checks were successful
/ test_checkout (push) Successful in 1m51s
All checks were successful
/ test_checkout (push) Successful in 1m51s
This commit is contained in:
parent
4e38131df5
commit
c3a27f8711
7 changed files with 57 additions and 53 deletions
|
@ -8,11 +8,11 @@ In this section, we will present those issues and potential avenues of improveme
|
|||
|
||||
=== Bytecode Transformation
|
||||
|
||||
#paragraph[Custom Classloaders][
|
||||
The first obvious limitation of our bytecode transformation is that we do not know what custom classloaders do, so we cannot accurately reproduce statically their behaviour.
|
||||
We elected to fallback to the behaviour of the `BaseDexClassLoader`, which is the highest Android-specific classloader in the inheritance hierarchy, and whose behaviour is shared by all classloaders except `DelegateLastClassLoader`.
|
||||
#paragraph[Custom Class Loaders][
|
||||
The first obvious limitation of our bytecode transformation is that we do not know what custom class loaders do, so we cannot accurately reproduce statically their behaviour.
|
||||
We elected to fallback to the behaviour of the `BaseDexClassLoader`, which is the highest Android-specific class loader in the inheritance hierarchy, and whose behaviour is shared by all class loaders except `DelegateLastClassLoader`.
|
||||
The current implementation of the #ART enforces some restrictions on the class loader's behaviour to optimise the runtime performance by caching classes.
|
||||
This gives us some guarantees that custom class loaders will keep some coherence with the classic classloaders.
|
||||
This gives us some guarantees that custom class loaders will keep some coherence with the classic class loaders.
|
||||
For instance, a class loaded dynamically must have the same name as the name used in `ClassLoader.loadClass()`.
|
||||
This makes `BaseDexClassLoader` a good approximation for legitimate class loaders.
|
||||
However, an obfuscated application could use the techniques discussed in @sec:cl-cross-obf, in which case our model would be entirely wrong.
|
||||
|
@ -22,21 +22,21 @@ A more reasonable approach would be to improve the static analysis to intercept
|
|||
This would allow us to collect a mapping $("class loader", "class name") -> "class"$ that can then be used when renaming colliding classes.
|
||||
]
|
||||
|
||||
#paragraph[Multiple Classloaders for one `Method.invoke()`][
|
||||
Although we managed to handle calls to different methods from one `Method.invoke()` site, we do not handle calling methods from different classloaders with colliding class definitions.
|
||||
The first reason is that it is quite challenging to compare classloaders statically.
|
||||
#paragraph[Multiple Class Loaders for one `Method.invoke()`][
|
||||
Although we managed to handle calls to different methods from one `Method.invoke()` site, we do not handle calling methods from different class loaders with colliding class definitions.
|
||||
The first reason is that it is quite challenging to compare class loaders statically.
|
||||
At runtime, each object has a unique identifier that can be used to compare them over the course of the same execution, but this identifier is reset each time the application starts.
|
||||
This means we cannot use this identifier in an `if` condition to differentiate the classloaders.
|
||||
Ideally, we would combine the hash of the loaded #DEX files, the classloader class and parent to make a unique, static identifier, but the #DEX files loaded by a classloader cannot be accessed at runtime without accessing the process memory at arbitrary locations.
|
||||
For some classloaders, the string representation returned by `Object.toString()` lists the location of the loaded #DEX file on the file system.
|
||||
This means we cannot use this identifier in an `if` condition to differentiate the class loaders.
|
||||
Ideally, we would combine the hash of the loaded #DEX files, the class loader class and parent to make a unique, static identifier, but the #DEX files loaded by a class loader cannot be accessed at runtime without accessing the process memory at arbitrary locations.
|
||||
For some class loaders, the string representation returned by `Object.toString()` lists the location of the loaded #DEX file on the file system.
|
||||
This is not the case for the commonly used `InMemoryClassLoader`.
|
||||
In addition, the #DEX files are often located in the application's private folder, whose name is derived from the hash of the #APK itself.
|
||||
Because we modify the application, the path of the private folder also changes, and so will the string representation of the classloaders.
|
||||
Checking the classloader of a class can also have side effects on classloaders that delegate to the main application classloader:
|
||||
because we inject the classes in the #APK, the classes of the classloader are now already in the main application classloader, which in most cases will have priority over the other classloaders, and lead to the class being loaded by the application classloader instead of the original classloader.
|
||||
If we check for the classloader, we would need to consider such cases and rename each class of each classloader before reinjecting them in the application.
|
||||
Because we modify the application, the path of the private folder also changes, and so will the string representation of the class loaders.
|
||||
Checking the class loader of a class can also have side effects on class loaders that delegate to the main application class loader:
|
||||
because we inject the classes in the #APK, the classes of the class loader are now already in the main application class loader, which in most cases will have priority over the other class loaders, and lead to the class being loaded by the application class loader instead of the original class loader.
|
||||
If we check for the class loader, we would need to consider such cases and rename each class of each class loader before reinjecting them in the application.
|
||||
This would greatly increase the risk of breaking the application during its transformation.
|
||||
Instead, we elected to ignore the classloaders when selecting the method to invoke.
|
||||
Instead, we elected to ignore the class loaders when selecting the method to invoke.
|
||||
This leads to potential invalid runtime behaviour, as the first method that matches the class name will be called, but the alternative methods from other class loaders still appear in the new application, albeit in a block that might be flagged as dead code by a sufficiently advanced static analyser.
|
||||
]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue