start taking in account feedbacks
All checks were successful
/ test_checkout (push) Successful in 1m50s

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2025-10-21 01:52:00 +02:00
parent 0d50644ede
commit de6359db3f
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 354 additions and 192 deletions

View file

@ -27,8 +27,7 @@
aspect-ratio : "16-9",
title : [From Large Scale Analysis to Dynamic Deobfuscation],
subtitle : [The Woes of Android Reverse Engineering],
event : [], //[PhD Defense],
short-title : [], //[PhD Defense],
footer-text : [Jean-Marie Mineau PhD Defense],
//short-event : [Rennes, 2025/12/9],
title-size : 32pt,
section-size : 18pt,
@ -113,36 +112,6 @@
)
]
#slide(
title: [Analysing Applications: Which Tools?],
foreground: eye-3(x: 3%, y: 5%)
)[
#set align(center+horizon)
#move(dx: -50pt, image("slides/imgs/apk-analysis.svg", width: 300pt))
]
// something is broken, so hack to keep the page number at the same
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Analysing Applications: Which Tools?],
)[
#set list(spacing: 3em)
#item-by-item[
- #cite(<Li2017>, form: "prose"): systematic literature review for Android static analysis, lists open-sourced tools
- #cite(<reaves_droid_2016>, form: "prose"): tests analysis tools, raises concerns about reusability and analysis of
real-world applications
]
]
// something is broken, so hack to keep the page number at the same
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Analysing Applications: Which Tools?],
)[
#highlight-block(pb1-text)
]
#slide(
title: [Obfuscation],
//foreground: eye-1(x: 95%, y: 85%, mirror: true)
@ -225,21 +194,100 @@
#slide(
title: [Obfuscation],
subtitle: [Deobfuscated],
foreground: {
place-fg(x: 44%, y: 55%, $ lr(}, size: #130pt) $ )
place-fg(x: 44%, y: 26%, $ lr(}, size: #110pt) $ )
arrow((385pt, 260pt), (450pt, 230pt))
arrow((385pt, 125pt), (450pt, 110pt))
},
)[
#show: yes-codly
#codly(
skips: ((3, 10), (5, 10), (6, 10)),
..default-codly
)
#scale(100%)[
```java
public class Foo {
public static String bar(String arg) {
}
}
#grid(
columns: (1fr, 4em, 1fr),
[
#scale(60%, reflow: true)[
```java
String DEX = "ZGV4CjA [...] EAAABEAwAA";
String className = "W5f3 [...] 3sls=";
String methodName = "n6WGYJzjDrUvR9cYljlNlw==";
ClassLoader cl = new InMemoryDexClassLoader(
ByteBuffer.wrap(Base64.decode(DEX, 2)),
Main.class.getClassLoader()
);
Class<?> loadedClass = this.cl.loadClass(decrypt(className));
Object obj = "FooBar";
Object ret = loadedClass.getMethod(
decrypt(methodName),
String.class
).invoke(null, obj);
```]
],
[],
[
#codly(
skips: ((3, 10),),
..default-codly
)
#scale(100%)[
```java
public class Foo {
public static String bar(String arg) {
}
}
```
```java
String ret = Foo.bar("FooBar");
```]
]
)
]
```]
#slide(
foreground: ghost-5(x: 10%, y: 7%)
)[
#set align(center+horizon)
#grid(
columns: (1fr, 1fr),
gutter: 2em,
[
== Dynamic Analysis
#item-by-item[
- Run the application
- _See_ dynamically loaded bytecode
- _See_ reflection calls
- Limited by code coverage
]
],
[
== Static Analysis
#item-by-item(start: 5)[
- Do *not* run the application
- *Not* limited by code coverage
- But only for the *code available*
//- Some values cannot be computed
]
],
//grid.cell(colspan: 2, uncover(8)[
// #text(size: 30pt)[Can we combine both?]
//]),
)
]
#slide(
title: [Analysing Applications: Which Tools?],
foreground: eye-3(x: 3%, y: 5%)
)[
#set align(center+horizon)
#move(dx: -50pt, image("slides/imgs/apk-analysis.svg", width: 300pt))
]
#slide(
title: [Problem Statement 1],
)[
#highlight-block(pb1-text)
]
#slide(
@ -299,13 +347,13 @@
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Class Loading],
title: [Problem Statement 3],
)[
#highlight-block(pb2-text)
]
#slide(
foreground: ghost-5(x: 10%, y: 7%)
title: [Deobuscation],
)[
#set align(center+horizon)
#grid(
@ -313,47 +361,55 @@
gutter: 2em,
[
== Dynamic Analysis
#item-by-item[
- Run the application
- _See_ dynamically loaded bytecode
- _See_ reflection calls
- Limited by code coverage
]
Easier to solve Dynamic Code Loading and Reflection Calls
],
[
== Static Analysis
#item-by-item(start: 5)[
- Do *not* run the application
- *Not* limited by code coverage
- But only for the *code available*
//- Some values cannot be computed
]
Better code coverage
],
grid.cell(colspan: 2, uncover(8)[
grid.cell(colspan: 2, uncover(2)[
#text(size: 30pt)[Can we combine both?]
]),
)
]
#slide[
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Problem Statement 3],
)[
#highlight-block(pb3-text)
]
#slide[
#highlight-block(pb1-text)
#highlight-block(pb2-text)
#highlight-block(pb3-text)
#slide(
foreground: rotate(30deg, smallcaps(text(fill: pirat-color.red, size: 50pt)[Faire un dessin]))
)[
// TODO Outline / problematics / drawing
]
#new-section-slide([Tool Reusability])
#slide(
title: [State of the Art],
)[
#set list(spacing: 0.5em)
Li #etal:
#v(0pt)
#item-by-item[
- Systematic literature review for Android static analysis
- Lists open-sourced tools
- Does not test the tools
]
#uncover("4-")[Reaves #etal:]
#v(0pt)
#item-by-item(start: 4)[
- Tests 7 Android analysis tools
- Tests analysing 16 real-world applications
- Raises concerns about reusability and analysis of real-world applications
]
]
#slide(
title: [Methodology]
)[
@ -398,8 +454,6 @@
#set align(center+horizon)
#show figure.caption: none
#scale(100%, get_figure(<fig:rasta-exit>))
//#text(size: 25pt)[We check if the results *exist* after running a tool]
]
#counter("logical-slide").update( n => n - 1 )
@ -445,6 +499,7 @@
#scale(100%, get_figure(<fig:rasta-exit>))
]
/*
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Results],
@ -505,34 +560,22 @@
#text(size: 22pt)[Finishing rate as a function of the bytecode size, for APKs discovered in 2022]
]
*/
#slide(
title: [Conclusion],
foreground: {
place(
bottom + left,
text(fill: pirat-color.blue)[International Conference on Software and Systems Reuse (ICSR 2024)]
)
}
)[
#set align(center)
#v(1fr)
//#set align(center)
#item-by-item[
- Over 22 tools, 10 are usable (*less than half*)
- Over 22 tools, 10 are usable
- Newer applications are harder to analyse
- Applications with more bytecode are harder to analyse
- Applications targetting more recent versions of Android are harder to analyse
]
]
#slide[
#set align(center)
// Sous titre dans la conclusion
#text(size: 22pt)[21st International Conference on Software and Systems Reuse (ICSR 2024)]
#v(2em)
#show regex("\[\d+\]"): none
#cite(<rasta>, form: "full")
#v(1fr)
#align(center, text(fill: pirat-color.blue.darken(30%))[International Conference on Software and Systems Reuse (ICSR 2024)])
#v(1em)
]
#new-section-slide([Class Shadowing])
@ -579,35 +622,107 @@
]
#slide(
title: [Android Ecosystem]
title: [State of the Art],
//foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[State of the Art])
)[
#set align(center+horizon)
#show figure.caption: none
#grid(
columns: (3fr, 1fr),
scale(reflow: true, get_figure(<fig:cl-archisdk>)),
[
#set align(left)
#set text(size: 20pt)
#set list(marker: [-])
=== Types of classes:
- APK Classes
- Platform Classes
- SDK Classes
- Hidden APIs
]
)
// TODO: hightlight
#set list(spacing: 3em)
#item-by-item[
- Previous contributions focus on Java runtime
- Android related contributions focus on Dynamic Code Loading
]
]
#for i in range(5) {
let strong-at(i, str-idxs, body) = {
if i in str-idxs {
strong(body)
} else {
body
}
}
slide(
title: [Android Ecosystem],
foreground: {
let c = white.transparentize(10%)
let place-rect(x, y, w, h) = place-fg(
x: x, y: y,
rect(
width: w,
height: h,
stroke: c,
fill: c,
)
)
// phone
if i in () {
place-rect(15%, 15%, 16.5%, 55%)
}
// Platform Classes
if i in (1,) {
place-rect(18%, 38%+4pt, 12%, 15%)
place-rect(21%, 54%, 8%, 5%)
}
// API access
if i in (1,4) {
place-rect(26%-4pt, 31%+2.3pt, 5%, 7%+2pt)
}
// APK file
if i in (2,3, 4) {
place-rect(19%+3pt, 22%, 9%, 9%+1pt)
place-rect(21%+5pt, 32%, 4%, 3%)
}
// doc
if i in (1,2,4) {
place-rect(31.5%, 45%, 30%, 25%)
}
// dev
if i in (2,4) {
place-rect(39.5%, 15%, 22%, 30%)
}
// Dev SDK
if i in (1,) {
place-rect(49.6%, 18%, 10%, 15%)
}
// Dev classes
if i in (3,) {
place-rect(41.5%-1pt, 18%, 8%+2pt, 10%)
}
// compil
if i in (2,3, 4) {
place-rect(31.5%, 22%, 8%, 5%)
}
}
)[
#set align(center+horizon)
#show figure.caption: none
#grid(
columns: (3fr, 1fr),
scale(reflow: true, get_figure(<fig:cl-archisdk>)),
[
#set align(left)
#set text(size: 20pt)
#set list(marker: [-])
=== Types of classes:
- #strong-at(i, (1,))[APK Classes]
- #strong-at(i, (2,))[Platform Classes]
- #strong-at(i, (3,))[SDK Classes]
- #strong-at(i, (4,))[Hidden APIs]
]
)
]
}
#slide(
title: [Android ClassLoaders]
title: [Android ClassLoaders], // TODO CHANGE DRAWING
foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[DESSIN RUNTIME CL \ \ WITH DELEGATION])
)[
/*
#set align(center+horizon)
#show figure.caption: none
#scale(60%, reflow: true, get_figure(<fig:cl-class_loading_classes>))
*/
]
#slide(
@ -704,6 +819,9 @@
=== `app.apk`
#line(length: 30%)
#show "classes.dex": set text(fill: pirat-color.red.darken(10%))
#show "classes2.dex": set text(fill: pirat-color.red.darken(10%))
#show "classes3.dex": set text(fill: pirat-color.red.darken(10%))
```
AndroidManifest.xml
resources.arsc
@ -755,9 +873,7 @@
else:
return f"classes{index+1}.dex"
```)
// Donner example
- `classes0.dex` ?
- `classes1.dex` ?
- `classes02.dex` ?
- `classes10.dex` ?
]
@ -808,7 +924,7 @@
columns: (1fr, 1fr),
column-gutter: 2em,
yes-codly[
#scale(60%, reflow: true,
#scale(55%, reflow: true,
```python
def get_dex_name(index: int):
if index == 0:
@ -829,7 +945,9 @@
return load_from_file(dex_file, class_name)
else:
raise ClassNotFoundError()
```) // TODO: nomer And Cl Alg
```)
#v(-1em)
#smallcaps(text(size: 15pt)[Android Class Loading Algorithm])
], [
#set align(left)
#set text(size: 18pt)
@ -852,6 +970,8 @@
#slide(
title: [Impact on Tools],
// TODO: IF PR: Add REF
foreground: move(dx: 300pt, rotate(30deg, text(fill: pirat-color.red, size: 30pt)[We want PR!])),
)[
#set align(center+horizon)
#show figure.caption: none
@ -861,11 +981,10 @@
show table: set align(center+horizon)
it
}
#show "not working": "attack not successfull"
#show "working": "attack successfull"
#show "works": "successfull"
#show "not working": "attack failed"
#show "working": "attack sucessful"
#show "works": "sucessful"
#scale(100%, reflow: true, get_figure(<tab:cl-results>))
// TODO: IF PR: Add REF
]
#slide(
@ -887,33 +1006,67 @@
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
slide(
title: [In the Wild: 49 975 APKs],
foreground: eye-2(x: 8%, y: 67%, height: 70pt)
)[
#set align(center+horizon)
#show figure.caption: none
#show link.where(dest: <acr-sdk>): it => it.body
#set table(
// TODO: Simplifier table, mettre nb apk dans titre
// enlever SDK et 1ere partie 100%
//#scale(90%, reflow: true, get_figure(<tab:cl-shadow>))
#import "4_class_loader/X_var.typ": scan_50k, scan_only_shadow
#import "lib.typ": num
#let nb_col = 7
#scale(90%, reflow: true, table(
columns: nb_col,
stroke: none,
align: center+horizon,
fill: (x, y) => {
if (
i == 1 and (x, y) in ((1, 13), (2, 13), (4, 13), (8, 13))
i == 1 and (x, y) in ((1, 4), (2, 4), (4, 4), (6, 4))
) or (
i == 2 and (x, y) in ((1, 14), (2, 14))
i == 2 and (x, y) in ((1, 5), (2, 5))
) {
highlight-color
} else {
none
}
}
)
// TODO: Simplifier table, mettre nb apk dans titre
// enlever SDK et 1ere partie 100%
#scale(90%, reflow: true, get_figure(<tab:cl-shadow>))
},
inset: (x: 0% + 7pt, y: 0% + 5pt),
table.hline(),
table.header(
table.cell(colspan: nb_col, inset: 3pt)[],
table.cell(rowspan: 2, eye-2(x: 35pt, y: 30pt, height: 70pt)),
table.vline(end: 3),
table.vline(start: 4),
table.cell(colspan: 3)[*Number of apps*],
table.vline(end: 3),
table.vline(start: 4),
table.cell(colspan: 2)[*Nb Shadow Classes*],
table.vline(end: 3),
table.vline(start: 4),
table.cell(rowspan: 2)[*Identical Code*],
[], [%], [% malware],
[Average], [Median],
),
table.hline(),
table.cell(colspan: nb_col, inset: 3pt)[],
..scan_only_shadow.map(e => (
[*#e.method*],
num(e.nbapp), [#e.ratioapp%], [#e.ratiomal%],
num(e.avgshadow), num(e.median),
[#e.id%]
)).flatten(),
table.cell(colspan: nb_col, inset: 3pt)[],
table.hline(),
))
]
}
#slide(
title: [Conclusion]
)[
#v(1fr)
#item-by-item[
- We modeled the class loading algorithm
- Static Analysis Tools did not
@ -921,28 +1074,18 @@
- Ambiguous cases exists in the wild
- We did not find deliberate shadow attacks
]
#v(1fr)
#align(center, text(fill: pirat-color.blue.darken(30%))[Digital Threats: Research and Practice])
#v(0.5em)
]
#slide[
#set align(center)
// Faire apparaitre a chaque étape
#text(size: 22pt)[Digital Threats: Research and Practice])
#v(2em)
#show regex("\[\d+\]"): none
#cite(<classloaderinthemiddle>, form: "full")
]
#new-section-slide([The Application of Theseus])
// TODO put everywhere Theseus Transformeur
#slide(
title: [Overview],
foreground: {
set align(center+horizon)
rotate(30deg, text(fill: pirat-color.red, size: 30pt)[Moche faire un dessin])
}
foreground: rotate(30deg, text(fill: pirat-color.red, size: 50pt)[Moche faire un dessin]),
)[
// TODO: bien tout rappeler l'objectif
// TODO: SOA
@ -986,7 +1129,7 @@
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
slide(
title: [Reflection],
title: [Transformation: Reflection],
//foreground: ghost-6(x: 80%, y: 15%, mirror: true)
)[
#show: yes-codly
@ -1189,10 +1332,9 @@
#set align(center+horizon)
#show figure.caption: none
#scale(90%, reflow: true, get_figure(<fig:th-status-npatched-vs-patched>))
// Fleche original
// Fleche theseus
// TODO: Fleche original
// TODO: Fleche theseus
//
// Theseus Transformeur
]
#slide(
@ -1235,10 +1377,10 @@
#counter("logical-slide").update( n => n - 1 )
#slide(
title: [Futur Work]
title: [Future Works]
)[
#item-by-item[
- Benchmark to evaluate finishing rate
- Benchmark of APKs to evaluate finishing rate
- Make tools reusing sources from Android Open Source Project
- Require developpers to provide high coverage tests inputs with the APKs
]
@ -1278,6 +1420,9 @@
/*
* RETOUR 1:
*
* Pas de retour en arriere
* Ne pas se retourner
*
* Bon premier jet.
*
* - slide text bof
@ -1295,15 +1440,8 @@
* Plus d'état de l'art, dans chapitres? redonner contexte au debut des chapitre, en profiter pour l'état de l'art. Pas plus d'un ou deux papiers, si important.
* Remplacer l'état de l'art dans l'intro par intuition et mettre soa dans chapitre
*
* Pb Statement: lisibilité!
*
* PQ: focu on dcl & refl
*
* Obfuscation: fleche vers deobfuscation
*
* Intro, dessin pas a pas dans l'intro en fonction de ce qui se passe dans l'intro
* RQ1: Static, RQ2: Check coherence static / dynamic, RQ3: transformation
*
* Mettre Theseus Tranformeur un peu partout!
*
*/

View file

@ -19,6 +19,8 @@ rgb("#E69426"),
pirat-color.red,
)
#let etal = [_et al._]
#let highlight-block(body) = {
set text(fill: white)
block(
@ -73,22 +75,8 @@ pirat-color.red,
}
*/
#let ghost(
img, x: 0pt,
y: 0pt,
mirror: false,
rot: 0deg,
height: 100pt
) = context {
let img = image(img, height: height)
if mirror {
img = scale(x: -100%, img)
}
if rot != 0deg {
img = rotate(rot, img)
}
let s = measure(img)
#let place-fg(x: 0pt, y: 0pt, body) = context {
let s = measure(body)
let hx = s.width / 2
let hy = s.height / 2
@ -96,10 +84,27 @@ pirat-color.red,
bottom + left,
dx: x - hx,
dy: -y + hy,
img
body
)
}
#let ghost(
img, x: 0pt,
y: 0pt,
mirror: false,
rot: 0deg,
height: 100pt
) = {
let img = image(img, height: height)
if mirror {
img = scale(x: -100%, img)
}
if rot != 0deg {
img = rotate(rot, img)
}
place-fg(x: x, y: y, img)
}
#let ghost-1 = ghost.with("imgs/ghosts/ghost-1.png")
#let ghost-2 = ghost.with("imgs/ghosts/ghost-2.png")
#let ghost-3 = ghost.with("imgs/ghosts/ghost-3.png")
@ -111,3 +116,30 @@ pirat-color.red,
#let eye-2 = ghost.with("imgs/ghosts/eye-2.png")
#let eye-3 = ghost.with("imgs/ghosts/eye-3.png")
#let eye-4 = ghost.with("imgs/ghosts/eye-4.png")
#let arrow(start, end, strk: 3pt + black) = {
let strk = stroke(strk)
start.at(1) = -start.at(1)
end.at(1) = -end.at(1)
let (xe, ye) = end
let (xs, ys) = start
let w = xe.pt() - xs.pt()
let h = ye.pt() - ys.pt()
let len = if w == 0pt and h == 0pt {
1pt
} else {
calc.sqrt(w*w + h*h)
}
let cos = w / len
let sin = h / len
place(bottom + left, line(start: start, end: end, stroke: strk))
place(bottom + left, polygon(
fill: strk.paint,
stroke: strk,
end,
(xe + strk.thickness * (sin - cos), ye - strk.thickness * (sin + cos )),
(xe - strk.thickness * (sin + cos), ye - strk.thickness * (sin - cos )),
))
}

View file

@ -43,9 +43,8 @@ cmyk(25%,7%,0%,0%),
// Data
#let sns-polylux-template_title = state("title", none)
#let sns-polylux-template_short-title = state("short-title", none)
#let sns-polylux-template_subtitle = state("subtitle", none)
#let sns-polylux-template_event = state("event", none)
#let sns-polylux-template_footer-text = state("footer-text", none)
#let sns-polylux-template_short-event = state("short-event", none)
#let sns-polylux-template_authors = state("authors", none)
@ -77,8 +76,7 @@ cmyk(25%,7%,0%,0%),
// Data
title : none,
subtitle : none,
short-title : none,
event : none,
footer-text : none,
short-event : none,
logo-2 : none,
logo-1 : none,
@ -115,11 +113,7 @@ cmyk(25%,7%,0%,0%),
)
sns-polylux-template_title.update(title)
sns-polylux-template_subtitle.update(subtitle)
if short-title != none { sns-polylux-template_short-title.update(short-title) }
else { sns-polylux-template_short-title.update(title) }
sns-polylux-template_event.update(event)
if short-event != none { sns-polylux-template_short-event.update(short-event) }
else { sns-polylux-template_short-event.update(event) }
if footer-text != none { sns-polylux-template_footer-text.update(footer-text) }
sns-polylux-template_logo-2.update(logo-2)
sns-polylux-template_logo-1.update(logo-1)
sns-polylux-template_authors.update(authors)
@ -171,7 +165,7 @@ cmyk(25%,7%,0%,0%),
let content = align(top + center, context( {
let title = sns-polylux-template_title.at(here())
let subtitle = sns-polylux-template_subtitle.at(here())
let event = sns-polylux-template_event.at(here())
let footer-text = sns-polylux-template_footer-text.at(here())
let authors = sns-polylux-template_authors.at(here())
let title-size = sns-polylux-template_title-size.at(here())
let logo = {
@ -224,7 +218,7 @@ cmyk(25%,7%,0%,0%),
place(
bottom + center,
dy: -1cm,
text(fill: sns-polylux-template_background-color.at(here()), size: 22pt, event)
text(fill: sns-polylux-template_background-color.at(here()), size: 22pt, footer-text)
)
if logo != none {
place(
@ -454,8 +448,7 @@ cmyk(25%,7%,0%,0%),
// FOOTER
let footer = align(top + center, context( {
let short-title = sns-polylux-template_short-title.at(here())
let short-event = sns-polylux-template_short-event.at(here())
let footer-text = sns-polylux-template_footer-text.at(here())
place(top + center, line(length: 100%-2cm, stroke: (paint: sns-polylux-template_colormap.at(here()).at(1), thickness: 2pt)))
@ -468,9 +461,8 @@ cmyk(25%,7%,0%,0%),
align(horizon,text(fill: sns-polylux-template_colormap.at(here()).at(2), size: 16pt,
grid(
gutter: 0.8cm,
columns: (0.7fr, 1fr, 0.7fr),
align(left, short-title),
align(center, smallcaps(short-event)),
columns: (1fr, 5em),
align(center, smallcaps(footer-text)),
align(right, if page-number [#toolbox.slide-number/#toolbox.last-slide-number]),
))
))