This commit is contained in:
parent
a1a5794250
commit
ad66b1293d
4 changed files with 204 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
|||
#import "../lib.typ": todo, APK, DEX, JAR, OAT, eg, ART, paragraph
|
||||
#import "../lib.typ": todo, APK, DEX, JAR, OAT, eg, ART, paragraph, jm-note
|
||||
|
||||
/*
|
||||
* Parler de dex lego et du papier qui encode les resultats d'anger en jimple
|
||||
|
@ -166,7 +166,7 @@ When loaded dynamically, the classes are in a different classloader, and the cla
|
|||
We decided to restrain our scope to the use of class loader from the Android SDK.
|
||||
In the abscence of class collision, those class loader behave seamlessly and adding the classes to application maintains the behavior.
|
||||
|
||||
#todo[this is redundant an messy:]
|
||||
#jm-note[
|
||||
When we detect a collision, we rename one of the classes colliding in order to be able to differenciate both classes.
|
||||
To avoid breaking the application, we then need to rename all references to this specific class, an be carefull not to modify references to the other class.
|
||||
To do so, we regroup each classes by the classloaders defining them, then, for each colliding class name and each classloader, we check the actual class used by the classloader.
|
||||
|
@ -177,6 +177,7 @@ The pseudo-code in @lst:renaming-algo show the three steps of this algorithm:
|
|||
- first we detect collision and rename classes definitions to remove the collisions
|
||||
- then we rename the reference to the colliding classes to make sure the right classes are called
|
||||
- ultimately, we merge the modified dexfiles of each class loaders into one android application
|
||||
][this is redundant an messy]
|
||||
|
||||
#figure(
|
||||
```python
|
||||
|
|
|
@ -1,8 +1,103 @@
|
|||
#import "../lib.typ": todo
|
||||
#import "../lib.typ": todo, SDK, num, mypercent, ART, ie
|
||||
#import "X_var.typ": *
|
||||
|
||||
== Result <sec:th-res>
|
||||
|
||||
#todo[better section name for @sec:th-res]
|
||||
|
||||
=== Bytecode Loaded by Application <sec:th-code-collected>
|
||||
To studdy the impact of our transformation on analysis tools, we took reused application from the dataset we sampled in @sec:rasta-dataset.
|
||||
Because we are running the application on a rescent version of Android (#SDK 34), we only took the most recent applications: the one collected in 2023.
|
||||
This represent #num(5000) applications.
|
||||
Among them, we could not retrieve 43 from Androzoo, leaving us with #num(dyn_res.all.nb) applications to test.
|
||||
|
||||
#todo[Bytecode collected: facebook, google, appsflyer]
|
||||
=== The Limits of Our Dynamic Analysis <sec:th-dyn-failure>
|
||||
|
||||
After running the dynamic analysis on our dataset the first time we realised our dynamic setup was quite fragile.
|
||||
We found that #mypercent(dyn_res.all.nb_failed_first_run, dyn_res.all.nb) of the execution failed with various errors.
|
||||
The majority of those errors were related to faillures to connect to the Frida agent or start the activity from Frida.
|
||||
Some of those errors seamed to come from Frida, while other seamed related to the emulator failing to start the application.
|
||||
We found the simply relauching the analysis for the applications that failled was the most simple way to fix those issues, and after 6 passes we went from #num(dyn_res.all.nb_failed_first_run) to #num(dyn_res.all.nb_failed) application that could not be analyzed.
|
||||
The remaining errors look more related to the application itself or Android, with #num(96) errors being a failure to install the application, and #num(110) other beeing a null pointer exception from Frida.
|
||||
|
||||
Infortunatly, although we managed to start the applications, we can see from the list of activity visited by GroddDroid that a majority (#mypercent(dyn_res.all.z_act_visited, dyn_res.all.nb - dyn_res.all.nb_failed)) of the application stopped before even starting one activity.
|
||||
Some applications do not have an activity, and are not intended to interact with a user, but those are clearly a minority and do not explain such a high number.
|
||||
We expected some issue related to the use of an emulator, like the lack of x86_64 library in the applications, or contermesures aborting the application if the emulator is detected.
|
||||
We manually looked at some applications, but did not found a notable pattern.
|
||||
In some cases, the application was just broken, for instance the application might be trying to load a native library that simply do not exists in the application.
|
||||
In other case, Frida is to blame: we found some cases where calling a method from Frida can confuse the #ART.
|
||||
`protected` methods needs to be called from the class that defined the method or one of its children calsses, but Frida might be considered by the #ART as an other class, leading to the #ART aborting the application.
|
||||
#todo[jfl was suppose to test a few other app #emoji.eyes]
|
||||
@tab:th-dyn-visited shows the number of applications that we analysed, if we managed to start at least one activity and if we intercepted code loading or reflection.
|
||||
As shown in the table, even if the application fails to start an activity, some times it will still load external code or use reflection.
|
||||
|
||||
#figure(
|
||||
table(
|
||||
columns: 6,
|
||||
stroke: none,
|
||||
inset: 7pt,
|
||||
align: center+horizon,
|
||||
table.header(
|
||||
table.hline(),
|
||||
table.cell(colspan: 6, inset: 2pt)[],
|
||||
table.cell(rowspan: 2)[],
|
||||
table.cell(rowspan: 2)[nb apk],
|
||||
table.vline(end: 3),
|
||||
table.vline(start: 4),
|
||||
table.cell(colspan: 2, inset: (bottom: 0pt))[nb failled],
|
||||
table.vline(end: 3),
|
||||
table.vline(start: 4),
|
||||
table.cell(colspan: 2, inset: (bottom: 0pt))[activities visited],
|
||||
|
||||
[1#super[st] pass], [6#super[th] pass],
|
||||
[0], [$>= 1$],
|
||||
),
|
||||
table.cell(colspan: 6, inset: 2pt)[],
|
||||
table.hline(),
|
||||
table.cell(colspan: 6, inset: 2pt)[],
|
||||
[All], num(dyn_res.all.nb), num(dyn_res.all.nb_failed_first_run), num(dyn_res.all.nb_failed), num(dyn_res.all.z_act_visited), num(dyn_res.all.nz_act_visited),
|
||||
[With Reflection], num(dyn_res.reflection.nb), [], [], num(dyn_res.reflection.z_act_visited), num(dyn_res.reflection.nz_act_visited),
|
||||
[With Code Loading], num(dyn_res.code_loading.nb), [], [], num(dyn_res.code_loading.z_act_visited), num(dyn_res.code_loading.nz_act_visited),
|
||||
table.cell(colspan: 3, inset: 2pt)[],
|
||||
table.hline(),
|
||||
),
|
||||
caption: [Summary of the dynamic exploration of the applications from the RASTA dataset collected by Androzoo in 2023]
|
||||
) <tab:th-dyn-visited>
|
||||
|
||||
The high number of application that did not start an activity means that our result will be highly biaised.
|
||||
The code that might be loaded or method that might be called by reflection from inside activities is filtered out by the limit of or dynamic execution.
|
||||
This biaised must be kept in mind when reading the next subsection that studdy the bytecode that we intercepted.
|
||||
|
||||
=== The Bytecode Loaded by Application <sec:th-code-collected>
|
||||
|
||||
We collected a total of #nb_bytecode_collected files for #dyn_res.code_loading.nb application that we detected loading bytecode dynamicatlly.
|
||||
#num(92) of them were loaded by a `DexClassLoader`, #num(547) were loaded by a `InMemoryDexClassLoader` and #num(1) was loaded by a `PathClassLoader`.
|
||||
|
||||
Interressingly, once we compared the files, we found that we only collected #num(bytecode_hashes.len()) distinct files, and that #num(bytecode_hashes.at(0).at(0)) where identicals.
|
||||
Once we looked more in details, we found that most of those files are advertisement libraries.
|
||||
In total, we collected #num(nb_google) files containing Google ads librairies and #num(nb_facebook) files containing Facebook ads librairies.
|
||||
In addition, we found #num(nb_appsflyer) files containing code that we believe to be AppsFlyer, and company that provides "measurement, analytics, engagement, and fraud protection technologies".
|
||||
The remaining #num(nb_bytecode_collected - nb_google - nb_appsflyer - nb_facebook) files were custom code from high security applications (#ie banking, social security)
|
||||
@tab:th-bytecode-hashes sumarize the information we collected about the most common bytecode files.
|
||||
|
||||
#figure(
|
||||
table(
|
||||
columns: 4,
|
||||
stroke: none,
|
||||
align: center+horizon,
|
||||
table.header(
|
||||
[Nb Occurences], [SHA 256], [Content], [Format]
|
||||
),
|
||||
table.hline(),
|
||||
..bytecode_hashes.slice(0, 10)
|
||||
.map(
|
||||
(e) => (num(e.at(0)), [#e.at(1).slice(0, 10)...], ..e.slice(2))
|
||||
).flatten(),
|
||||
table.cell(colspan: 4)[...],
|
||||
table.hline(),
|
||||
),
|
||||
caption: [Most common dynamically loaded files]
|
||||
) <tab:th-bytecode-hashes>
|
||||
|
||||
=== Impact on Analysis Tools
|
||||
|
||||
#todo[Check if flowdroid improve, compare sucess rate of RASTA, show result for demo app]
|
||||
|
|
101
5_theseus/X_var.typ
Normal file
101
5_theseus/X_var.typ
Normal file
|
@ -0,0 +1,101 @@
|
|||
#import "../lib.typ": DEX, APK
|
||||
|
||||
#let dyn_res = (
|
||||
all: (
|
||||
nb: 4957,
|
||||
nb_failed_first_run: 2136,
|
||||
nb_failed: 209,
|
||||
z_act_visited: 3860,
|
||||
nz_act_visited: 888,
|
||||
),
|
||||
reflection: (
|
||||
nb: 3948,
|
||||
z_act_visited: 3152,
|
||||
nz_act_visited: 796,
|
||||
),
|
||||
code_loading: (
|
||||
nb: 598,
|
||||
z_act_visited: 434,
|
||||
nz_act_visited: 164,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
#let bytecode_hashes = (
|
||||
(273, "bee390afa2267bc48829ee7a0f4286895bf32ba2443ff447451f515818f7203b", "Lcom/facebook/ads/*", DEX),
|
||||
(98, "7aae06433cff5967ac254484d784c2c348380891d0914c56de64e7e006668cd4", "Lcom/facebook/ads/*", DEX),
|
||||
(70, "920e465a87a2409fc8d7186ea4e319c613c04d156bec75e8b91cb4d07b1deb75", "Lcom/facebook/ads/*", DEX),
|
||||
(31, "51dd5ff34a950c026bd39ba3b923c4c47126c097e844951ab1b71ea7c0ed824f", "Lcom/google/android/ads/*", APK),
|
||||
(12, "d44cfb6b41231f150cf310c7c4d399be9587294e3727197e046db4a1c2c3ca3b", "Lcom/google/android/ads/*", APK),
|
||||
(9, "be87bb0a50395917f973b4b2691d62037c7c7c6bc8aef060b49240680f82ec06", "Lcom/facebook/ads/*", DEX),
|
||||
(9, "26fb1a790377e11135bf8bfa7552cc2797d351df60154ea032ceeb4463776fdf", "Lcom/facebook/ads/*", DEX),
|
||||
(7, "8395a0121e5c4fc47f9547f58b8b335c4f499a8c302023878184db88336456ff", "Lcom/facebook/ads/*", DEX),
|
||||
(7, "1eea5584eb2332554753b4beec7fe8e972bfb3eeadbe0c05dba33de267f25a00", "Lcom/google/android/ads/*", APK),
|
||||
(6, "94f66aa1ae29067590791b57c44943326ff7d0793e5c3b4943c88837d98bf5f2", "Lcom/appsflyer/internal/*", DEX),
|
||||
(6, "76b0a168957403694b4067be8d5e0733c8b06b4165a0aaa85363517e8e972b41", "Lcom/appsflyer/internal/*", DEX),
|
||||
(6, "0aaf38c4dbaebb1f97357d71fcd266a04d941edf7d6a90ce4d5457f9276e9bb2", "Lcom/google/android/ads/*", APK),
|
||||
(5, "f14f45afd0a5d08b046dc89b394709bd6391245f64955cbfc8c0d5ed32fd13fd", "Lcom/appsflyer/internal/*", DEX),
|
||||
(5, "77731deb52bfdbc177380141ce84f9a44558564438c069ad7582490b1071cabc", "Lcom/google/android/ads/*", APK),
|
||||
(5, "2ef4bbdaeb41f79500d38885b7711ff5ea9464f565f32b060116670806b7b173", "Lcom/appsflyer/internal/*", DEX),
|
||||
(5, "1431e7d7fd88b604a9c3e7025992617af92714e42c5b6ea4aaa230dbee54e32e", "Lcom/appsflyer/internal/*", DEX),
|
||||
(5, "08db2ca6e3f51676dc1c9b114d522ac5ed211ae2e359bf6270066aca651e6932", "Lcom/facebook/ads/*", DEX),
|
||||
(4, "a66a9b1d2d136dc5df624d3cf577e54952218157ab15d39254ab64963be5cc72", "Lcom/facebook/ads/*", DEX),
|
||||
(4, "688d9c42adca2cacb59ccff544456da5b0faf33c47539753f4b6158d11681177", "Lcom/facebook/ads/*", DEX),
|
||||
(4, "5c4e43425c7220af03957c560092dbcc613ac7e0894e2740e87a0a9441fef9fb", "Lcom/google/android/ads/*", APK),
|
||||
(4, "38c5c0584805386dfce413656c636c4e73a968ade86cabd7a4ecac4f034a842b", "Lcom/facebook/ads/*", DEX),
|
||||
(3, "f235eaf46d704697e94379372a77a2a2b35e0727d09db08e9dd1d7a55c13a38d", "Lcom/appsflyer/internal/*", DEX),
|
||||
(3, "e5c7e239c5ff1e86317bfb009068311c0f0f89f76d7b7c7177aced74f718922d", "Lcom/google/android/ads/*", " Java archive data (JAR)"),
|
||||
(3, "e4270ee2c7c624bde9dacf923066032fd734e12cd70c8c70c949aee553896ef2", "Lcom/google/android/ads/*", APK),
|
||||
(3, "7cd311f806352c2a69f8c22a48f732a1c27fd00ad07690a8ae2b1fdb0aa7b1e8", "Lcom/facebook/ads/*", DEX),
|
||||
(3, "430c38bdf4ff62180781e77d4c7282bcd87143ec5d0aaf4534272ed6c7654b50", "Lcom/google/android/ads/*", APK),
|
||||
(3, "22ba7ab35067bf1343dcb20e1fa12a0277af5bafa4d8cbf62eda91c15983d180", "Lcom/google/android/ads/*", APK),
|
||||
(2, "f809447486f89fcaa74f87e06d126d103d37eb2b3157e88f2c06d989b2c284ce", "Lcom/google/android/ads/*", APK),
|
||||
(2, "b2d5fa3f1fa8128c2f086e933ebdc310ed9ae498161bd4f31b11d2a327e49a2d", "Lcom/google/android/ads/*", APK),
|
||||
(2, "8ae01d69caedba5faec1bf99fd86b412e54ae01d6c1b1876cb4fd1b744329dad", "Lcom/google/android/ads/*", APK),
|
||||
(2, "0bfad0c78e6e439d2c70d43568d1dc541bff8d4b4c5bfda9e81e03ae790dd864", "Lcom/facebook/ads/*", DEX),
|
||||
(1, "f8bc60491994834867a77096af5282190d9b742acf46a0d5a8fc527b627f20e8", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "edd47be06bf71794d0402a70a909e8f288de394129f9ab3cd4b873690f034719", "Lcom/facebook/ads/*", DEX),
|
||||
(1, "e8cc3f0bfc7988db9e0183c120b929c9b27c95a3d7245d1fadc3df3b60c7ef55", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "b97436f2e515c5846f0d23fae671271dc60795dae9f309ac2e6d85219a86f342", "", DEX),
|
||||
(1, "b5ddd91296430681f34b34154b553adce8f896a9ae330af761eaff62c16e67c5", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "b550710e818a228ac6a40a6964f67dc3647b463239b9aa58554038960fce6321", "Lcom/facebook/ads/*", DEX),
|
||||
(1, "ab8baa542a35f0cf5a02a6976be08d90b5c1982898844a5fdb7336a30db99f87", "", DEX),
|
||||
(1, "aa5468adfa49b5bb6b77ea01f08f69b824c1db1942d73cb80a38f30b1350688b", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "a5cd22950a182ed86832b94018c75cb80d2225c75f3dace2c25fb186580cfb04", "", DEX),
|
||||
(1, "a307f009ed3545218b58aa312a8ad906997e7333a8ad8fd483720f5b43d50808", "", DEX),
|
||||
(1, "94aecdeaf153c6993abaf289e2be41b7ed9e513ba4c12c219225b4ada5928543", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "82ba14f2b885c2471fe2b8ff1059ce72763d6a9195e8e442e8fa47a0388e187c", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "7b65a03fea918ff93b53cdc1973a6c65dafb1e15b07b9cdd653da7808d8eaf71", "", DEX),
|
||||
(1, "79f6c8048f803a069118db0ed11362c9c3a6db2f9e54e5d219830da20b98cec4", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "6febc4b01385c784fbf7c03af15e95c9e357f503f2aa1c002048a199fe1b3df4", "", DEX),
|
||||
(1, "6d562af7cbdb7fde5a79fb2f319b4e553f61428fd31b1ceae4d4bee860845a99", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "6cd8d19dc74ba69f6c6d93c6f14e2f5872ba102fd66f8f3a0f47bd7c8bbb3e31", "Lcom/google/android/ads/*", APK),
|
||||
(1, "6655124716f0da78a182d1fd647e59424cea8bcd91a74c7d570d112abd2b0773", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "607e10860109c11381a99f56036ca127c1c8352113d3eb612d704982694599f5", "Lcom/facebook/ads/*", DEX),
|
||||
(1, "5f18e3b50fe739e6ada6cd47db5fcb19fffca7fbe20ca8d2176a230904027a2a", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "5ec35489b467484e6f28a054fd371ebbc058ef686919330bada7bb91bd8a7664", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "5dd0a0925f78c828ccafe52239bfc41fab98861839e85c4dbb597ef88042f783", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "58e6c3467d0ac66647166bbe111ea4e6aa8dff1639d85c10dc016bd3f768af04", "Lcom/google/android/ads/*", APK),
|
||||
(1, "58a38bf508d3be01bef2f98de98892f8f2d015047b8808c0e471c13435436411", "Lcom/google/android/ads/*", APK),
|
||||
(1, "55ceea5940c98162c39ff009eb36b23ba37650ff0b761da4d91aefba2ce144f9", "", APK),
|
||||
(1, "4c07d1b3a5177cfee01aee86595c5a95bf818830f0a8d737df5e475c483a069f", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "3aedaba6f25a7fd04b16f68bb7ca12f71c5a464346556cbce78ebdb490df0362", "Lcom/facebook/ads/*", DEX),
|
||||
(1, "39b387a92c8de51316ac103dd7998ad5561c6bbeb29bf7baa71f6f30eaabd7e9", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "36e9d49509eafde99a852053b20b0ba5f9978cdf6b2e3d981aba9ff7dcfe06c5", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "355d3417e140868277dd4b52f75e2e844ee1ec26d43e2d5f192218c3b6c261ca", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "297d6430b89f66c7dae4df9f7ba60e6fdf8f823afda7786521187ce61486dc22", "", DEX),
|
||||
(1, "1fb49fb80e5dabd0f2897a64c9cf76f6aa2ad2504a89135e286339d77862d043", "", DEX),
|
||||
(1, "1d42b43a4f2ca277b3dcc147c5f3d4f4f84b6b170b8912287b486fb7343fc1fb", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "1aaa4f587a73d18dbcadf23ddc92841ae807a31d4f729ba430495456b0422ae0", "", DEX),
|
||||
(1, "1658b49396266d5811bed57bfaeb99504abb799c37356d720e45119153ab5702", "Lcom/appsflyer/internal/*", DEX),
|
||||
(1, "1409d97cc8b3c23244507fa4f62fd4e5835b80209e1b1bd9589579c3166d4aeb", "", DEX),
|
||||
(1, "11caa0ac837a8af9d3e45ad509e59c31d3d344bb8858cf40d1b0e1a1c29156ea", "Lcom/google/android/ads/*", APK),
|
||||
(1, "0d2f47edb7a5f4a075deb9f1e5ee24786daf28492553f6a6f8918c6ea19da92f", "", APK),
|
||||
(1, "0a446677e3eb0e015827f3d2d67df23ed9042e436bb5bab5cc9fae961e20600f", "", DEX),
|
||||
)
|
||||
|
||||
// #let nb_bytecode_collected = 640
|
||||
#let nb_bytecode_collected = bytecode_hashes.map((e) => e.at(0)).sum()
|
||||
#let nb_google = bytecode_hashes.filter((e) => "google" in e.at(2)).map((e) => e.at(0)).sum()
|
||||
#let nb_facebook = bytecode_hashes.filter((e) => "facebook" in e.at(2)).map((e) => e.at(0)).sum()
|
||||
#let nb_appsflyer = bytecode_hashes.filter((e) => "appsflyer" in e.at(2)).map((e) => e.at(0)).sum()
|
2
lib.typ
2
lib.typ
|
@ -36,3 +36,5 @@
|
|||
|
||||
#let mypercent(numerator, denominator, digits: 2) = [#num(calc.round((100 * numerator) / denominator, digits: digits))%]
|
||||
|
||||
#let jm-note = note.with(stroke: purple + 1pt)
|
||||
#let jfl-note = note.with(stroke: green + 1pt)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue