feedback
All checks were successful
/ test_checkout (push) Successful in 1m48s

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2025-10-28 23:18:23 +01:00
parent 1b461338b7
commit 6f7afe73a7
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
6 changed files with 3814 additions and 81 deletions

View file

@ -125,7 +125,7 @@ The contributions of this thesis are the following:
+ We propose an approach to allow static analysis tools to analyse applications that perform dynamic code loading:
We collect at runtime the bytecode dynamically loaded and the reflection calls information, and patch the #APK file to perform those operations statically.
Finally, we evaluate the impact this transformation has on the tools we containerised previously.
+ We released under the AGPL licence #todo[Still waiting for CS to validate] the software we used in the experiments presented in this thesis.
+ We released under the GPL licence the software we used in the experiments presented in this thesis.
For @sec:rasta, this includes the code used to test the output of each tool and the code to analyse the results of the experiment, in addition to the containers to run the tested tools.
We also released Androscalpel, a Rust crate to manipulate Dalvik bytecode, that we used to create Theseus, a set of scripts that implement the approach presented in @sec:th.
The complete list and location of the software we release are available in @sec:soft.

View file

@ -453,6 +453,7 @@
"static-vs-dyn",
"theseus",
).at(i)
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
slide(
//foreground: rotate(30deg, smallcaps(text(fill: pirat-color.red, size: 50pt)[#stage]))
)[
@ -921,12 +922,6 @@
title: [MultiDex]
)[
#set align(center + horizon)
#let apk-block = block.with(
//fill: green.lighten(50%),
stroke: black,
inset: 10pt,
radius: 12pt,
)
#only(1)[
#apk-block[
@ -1036,25 +1031,22 @@
]
)
]
]
#only(5)[
#for i in range(3) {
counter("logical-slide").update( n => n - 1 )
show table.cell: c => {
if c.y >= 1 and ((i < 2 and c.x == 2) or (i < 1 and c.x == 1)) {
[]
} else {
c
}
}
slide(
title: [Self-Shadowing],
)[
#grid(
columns: (1fr, 1fr),
apk-block[
#set align(left+top)
=== `app.apk`
#line(length: 30%)
```
AndroidManifest.xml
resources.arsc
META-INF/
res/
classes.dex
classes2.dex
classes3.dex
```
],
columns: (2fr, 0.5em, 3fr),
yes-codly[
#set list(spacing: 0.5em)
#scale(100%, reflow: true,
@ -1065,15 +1057,40 @@
else:
return f"classes{index+1}.dex"
```)
- `classes0.dex` ?
- `classes02.dex` ?
- `classes10.dex` ?
]
)
#ghost-4(x: 2%, y: 2%, mirror: true)
]
]
#align(bottom, text(size: 0.75em)[#sym.star estimation, non-deterministic])
], [], {
set text(size: 24pt)
show table.cell: set align(center+horizon)
let r = text.with(fill: pirat-color.red.darken(10%))
table(
columns: (1fr, 1fr, 1fr),
//inset: (x,y) => if y == 0 { 10pt } else { 3pt },
stroke: none,
table.header(
[Android],
table.vline(),
[Soot],
table.vline(),
[Androguard#super[#sym.star]]
),
table.hline(),
[`classes.dex`], [`classes.dex`], [`classes10.dex`],
..if (i != 0) {(
[], r[`classes1.dex`], [],
[], r[`classes10.dex`], [],
)},
[`classes2.dex`], [`classes2.dex`], [`classes9.dex`],
[`classes3.dex`], [`classes3.dex`], [`classes8.dex`],
table.cell(colspan: 3, inset: -3pt)[...],
[`classes9.dex`], [`classes9.dex`], [`classes2.dex`],
[`classes10.dex`], [], [`classes1.dex`],
strike[`classes1.dex`], [], [`classes.dex`],
)}
)
]
}
#for i in range(4) {
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
slide(
@ -1084,12 +1101,12 @@
codly(
..default-codly
)
} else if i == 1 {
} else if i == 2 {
codly(
highlighted-lines: (7, 8),
..default-codly
)
} else if i == 2 {
} else if i == 1 {
codly(
highlighted-lines: (1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15),
..default-codly
@ -1144,17 +1161,17 @@
#set align(left)
#set text(size: 18pt)
#partial-hide(i, hidden: (0,), partial: (2,))[
=== Self Shadowing
Trick the tool into using an APK class instead of another APK class
]
#partial-hide(i, hidden: (0, 1))[
=== SDK shadowing
Trick the tool into using an APK class instead of an SDK class
]
#partial-hide(i, hidden: (0,), partial: (2,))[
#partial-hide(i, hidden: (0, 1))[
=== Hidden API shadowing
Trick the tool into using an APK class instead of an hidden API class
]
#partial-hide(i, hidden: (0,1))[
=== Self Shadowing
Trick the tool into using an APK class instead of another APK class
]
]
)
]
@ -1180,17 +1197,27 @@
]
#slide(
title: [Example: Androguard],
title: [Androguard on Toy Malware],
foreground: eye-4(x: 97%, y: 85%, mirror: true)
)[
#set align(center+horizon)
#show image: scale.with(250%)
#set figure(gap: 4em)
//#show image: scale.with(250%)
//#set figure(gap: 4em)
#v(3em)
#grid(
columns: (1fr, 1fr),
get_figure(<fig:cl-andro_non_obf_cg>),
get_figure(<fig:cl-andro_obf_cg>)
//get_figure(<fig:cl-andro_non_obf_cg>),
figure(
image("slides/imgs/call_graph_expected.svg", width: 100%),
caption: [Expected],
supplement: none,
),
//get_figure(<fig:cl-andro_obf_cg>)
figure(
image("slides/imgs/call_graph_obf.svg", width: 100%),
caption: [Computed],
supplement: none,
)
)
]
@ -1267,7 +1294,7 @@
- We did not find deliberate shadow attacks
]
#v(1fr)
#align(center, text(fill: pirat-color.blue.darken(30%))[Digital Threats: Research and Practice])
#align(center, text(fill: pirat-color.blue.darken(30%))[Digital Threats: Research and Practice, vol. 6 (3), 2025])
#v(0.5em)
]
@ -1276,18 +1303,29 @@
// TODO put everywhere Theseus Transformeur
#slide(
title: [State of the Art],
title: [Dexhunter: Zang #etal (2015)],
)[
#align(center+horizon, text(fill: pirat-color.red, size: 30pt)[INSERT SoA])
#align(center+horizon, dexhunter-outline(
small_icon_size: 75pt,
big_icon_size: 200pt,
))
]
#slide(
title: [Overview],
foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[FINIR DESSIN]),
title: [DroidRA: Li #etal (2016)],
)[
#align(center+horizon, droidra-outline(
small_icon_size: 75pt,
big_icon_size: 200pt,
))
]
#slide(
title: [Theseus: Overview],
)[
// TODO: bien tout rappeler l'objectif
#set align(center+horizon)
#theseus-outline()
#only(1, theseus-outline(stage: "theseus-no-static"))
#only(2, theseus-outline(stage: "theseus"))
]
#slide(
@ -1387,32 +1425,62 @@
)[
#show: yes-codly
#set align(center+horizon)
#if i == 1 {
codly(
offset: 5,
highlighted-lines: (6,),
..default-codly
)
} else if i == 4 {
codly(
offset: 5,
highlights: (
(line: 6, start: 0, end: 25, fill: pirat-color.blue),
),
..default-codly
)
} else {
codly(
offset: 5,
..default-codly
)
}
```java
String retData = (String) mth.invoke(obj, args);
```
#v(-0.5em)
#align(center+horizon, sym.arrow.b.stroked)
#v(-0.5em)
#if i == 1 {
codly(
offset: 5,
highlighted-lines: (10,),
..default-codly
)
} else if i == 2 {
} else if i == 3 {
codly(
offset: 5,
highlights: (
(line: 6, start: 0, end: 13, fill: pirat-color.blue),
(line: 8, start: 3, end: 8, fill: pirat-color.blue),
(line: 10, start: 3, end: 8, fill: pirat-color.blue),
(line: 12, start: 18, end: 32, fill: pirat-color.blue),
),
..default-codly
)
} else if i == 3 {
codly(
offset: 5,
highlights: (
(line: 8, start: 12, end: 19, fill: pirat-color.blue),
(line: 12, start: 18+9, end: 32, fill: pirat-color.blue),
),
..default-codly
)
} else if i == 4 {
codly(
offset: 5,
highlights: (
(line: 8, start: 12, end: 19, fill: pirat-color.blue),
(line: 12, start: 0, end: 25, fill: pirat-color.blue),
),
..default-codly
)
} else if i == 2 {
codly(
offset: 5,
highlights: (
@ -1442,7 +1510,41 @@
}
#slide(
foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[MOCHE]),
foreground: {
arrow(
stroke: 10pt + pirat-color.red,
(
250pt,
-400pt,
),
(
250pt,
-350pt,
)
)
arrow(
stroke: 10pt + pirat-color.red,
(
130pt,
-400pt,
),
(
180pt,
-320pt,
)
)
arrow(
stroke: 10pt + pirat-color.red,
(
370pt,
-400pt,
),
(
320pt,
-320pt,
)
)
}
)[
#set align(center+horizon)
#theseus-outline()
@ -1475,6 +1577,11 @@
title: [Collected Bytecode],
foreground: eye-1(x: 5%, y: 70%, height: 70pt)
)[
/*
* Explications, give example of Google Services:
* whithout service: does not work
* with service: service recognize the app as malware and block it
*/
#set align(center+horizon)
#show link.where(dest: <acr-apk>): it => it.body
#show link.where(dest: <acr-dex>): it => it.body
@ -1494,10 +1601,33 @@
]
#slide(
foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[MOCHE]),
foreground: {
arrow(
stroke: 10pt + pirat-color.red,
(
770pt,
-250pt,
),
(
620pt,
-350pt,
)
)
arrow(
stroke: 10pt + pirat-color.red,
(
620pt,
-350pt,
),
(
770pt,
-250pt,
)
)
}
)[
#set align(center+horizon)
#theseus-outline()
#theseus-outline(stage: "theseus-vs-static")
]
#for i in range(3) {
@ -1506,25 +1636,45 @@
slide(
title: [Added Method Calls],
)[
// TODO: remove Before After
#set align(center+horizon)
#show link.where(dest: <acr-apk>): it => it.body
#show link.where(dest: <acr-dex>): it => it.body
#show figure.caption: none
#set table(
fill: (x, y) => {
if (
i == 1 and (x == 3 and y > 1)
//#show link.where(dest: <acr-apk>): it => it.body
//#show link.where(dest: <acr-dex>): it => it.body
//#show figure.caption: none
//#scale(90%, reflow: true, get_figure(<tab:th-compare-cg>))
#import "5_theseus/X_var.typ": compared_callgraph
#import "lib.typ": num
#let nb_col = 3
#table(
columns: (1fr, 1.1fr, 1fr),
align: center+horizon,
stroke: none,
fill: (x, y) => if (
i == 1 and (x == 1 and y > 1 and y != 9)
) or (
i == 2 and (x == 4 and y > 1)
i == 2 and (x == 2 and y > 1)
){
highlight-color
} else {
none
}
}
},
table.hline(),
table.header(
//[SHA 256], [Original CG edges], [New CG edges], [Edges added], [Reflection edges added],
table.cell(rowspan: 2)[APK SHA 256],
table.cell(colspan: nb_col - 1)[Number of Call Graph edges], [Diff (Total After - Before)], [Added Reflection],
),
table.hline(),
..compared_callgraph.map(
(e) => (
[#lower(e.sha256).slice(0, 10)...],
num(e.added),
num(e.added_ref_only)
)).flatten(),
[#lower("5D2CD1D10ABE9B1E8D93C4C339A6B4E3D75895DE1FC49E248248B5F0B05EF1CE").slice(0, 10)...], table.cell(colspan: nb_col - 1)[_Transformation Crashed_],
table.hline(),
)
#scale(90%, reflow: true, get_figure(<tab:th-compare-cg>))
]
}
@ -1549,14 +1699,18 @@
foreground: {
let strk = 3pt + pirat-color.blue
import "slides/icons.typ": arrow
arrow((360pt, 330pt), (380pt, 310pt), strk: strk)
arrow((420pt, 330pt), (400pt, 310pt), strk: strk)
arrow((290pt, -335pt), (320pt, -310pt), strk: strk)
arrow((400pt, -335pt), (340pt, -310pt), strk: strk)
}
)[
#set align(center+horizon)
#show figure.caption: none
Original #h(2em) Transformed
#move(dx: -70pt)[Original #h(2em) Transformed]
/*
* JFL bet on a question about SAAF
*/
#box(width: 80%, get_figure(<fig:th-status-npatched-vs-patched>))
]
@ -1578,7 +1732,7 @@
We showed that:
#item-by-item[
- After five years, more than half the static analysis tools are no longer usable.
- Most Static analysis tools are no longer usable after a few years.
The size of the application seems to be the most significant factor.
- Android behaviour is complex and not well known.
In the specific case of class loading, we showed that state-of-the-art tools do not match Android, leading to invalid analyses.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 70 KiB

View file

@ -3,7 +3,7 @@
#import "../lib.typ": pb1-text, pb2-text, pb3-text
#import "icons.typ": arrow
#import "outlines.typ": theseus-outline
#import "outlines.typ": theseus-outline, dexhunter-outline, droidra-outline
#let pirat-color = (
black: rgb("#000000"),
@ -35,6 +35,14 @@ pirat-color.red,
)
}
#let apk-block = block.with(
//fill: green.lighten(50%),
stroke: black,
inset: 10pt,
radius: 12pt,
)
#let colortest = [
#for th in (
sns-polylux-template_sns-pirat,

View file

@ -152,7 +152,7 @@
box(
width: width,
height: height,
stroke: black,
//stroke: black,
{
place(
left+bottom,
@ -221,6 +221,13 @@
)
}
#let droidra-outline(
small_icon_size: 100pt,
big_icon_size: 200pt,
) = context {
text(fill: red, size: 40pt)[TODO]
}
#let theseus-outline(
small_icon_size: 60pt,
big_icon_size: 90pt,