This commit is contained in:
parent
071a82ea56
commit
37f8298cb7
2 changed files with 508 additions and 20 deletions
527
slides.typ
527
slides.typ
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#set text(lang: "en")
|
||||
#set list(marker: none)
|
||||
#set par(leading: 0.2em)
|
||||
#set list(spacing: 1em)
|
||||
|
||||
#show: sns-polylux-template.with(
|
||||
txt-font: "New Computer Modern",
|
||||
|
|
@ -598,13 +600,15 @@
|
|||
title: [MultiDex]
|
||||
)[
|
||||
#set align(center + horizon)
|
||||
#let apk-block = block.with(
|
||||
//fill: green.lighten(50%),
|
||||
stroke: black,
|
||||
inset: 10pt,
|
||||
radius: 12pt,
|
||||
)
|
||||
|
||||
#only(1)[
|
||||
#block(
|
||||
fill: green.lighten(50%),
|
||||
inset: 10pt,
|
||||
radius: 12pt,
|
||||
)[
|
||||
#apk-block[
|
||||
#set align(left+top)
|
||||
|
||||
=== `app.apk`
|
||||
|
|
@ -619,11 +623,7 @@
|
|||
]
|
||||
]
|
||||
#only(2)[
|
||||
#block(
|
||||
fill: green.lighten(50%),
|
||||
inset: 8pt,
|
||||
radius: 8pt,
|
||||
)[
|
||||
#apk-block[
|
||||
#set align(left+top)
|
||||
=== `app.apk`
|
||||
#line(length: 50%)
|
||||
|
|
@ -645,11 +645,7 @@
|
|||
]
|
||||
]
|
||||
#only(3)[
|
||||
#block(
|
||||
fill: green.lighten(50%),
|
||||
inset: 8pt,
|
||||
radius: 8pt,
|
||||
)[
|
||||
#apk-block[
|
||||
#set align(left+top)
|
||||
=== `app.apk`
|
||||
#line(length: 75%)
|
||||
|
|
@ -685,7 +681,225 @@
|
|||
]
|
||||
#ghost-4(x: 2%, y: 2%, mirror: true)
|
||||
]
|
||||
|
||||
#only(4)[
|
||||
#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
|
||||
```
|
||||
],
|
||||
yes-codly[
|
||||
#scale(100%, reflow: true,
|
||||
```python
|
||||
def get_dex_name(index: int):
|
||||
if index == 0:
|
||||
return "classes.dex"
|
||||
else:
|
||||
return f"classes{index+1}.dex"
|
||||
```)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
#only(5)[
|
||||
#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
|
||||
```
|
||||
],
|
||||
yes-codly[
|
||||
#set list(spacing: 0.5em)
|
||||
#scale(100%, reflow: true,
|
||||
```python
|
||||
def get_dex_name(index: int):
|
||||
if index == 0:
|
||||
return "classes.dex"
|
||||
else:
|
||||
return f"classes{index+1}.dex"
|
||||
```)
|
||||
- `classes0.dex` ?
|
||||
- `classes1.dex` ?
|
||||
- `classes02.dex` ?
|
||||
- `classes10.dex` ?
|
||||
]
|
||||
)
|
||||
#ghost-4(x: 2%, y: 2%, mirror: true)
|
||||
]
|
||||
]
|
||||
|
||||
#for i in range(4) {
|
||||
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
|
||||
slide(
|
||||
title: [Shadow Attacks]
|
||||
)[
|
||||
|
||||
#if i in (0, 4) {
|
||||
codly(
|
||||
..default-codly
|
||||
)
|
||||
} else if i == 1 {
|
||||
codly(
|
||||
highlighted-lines: (7, 8),
|
||||
..default-codly
|
||||
)
|
||||
} else if i == 2 {
|
||||
codly(
|
||||
highlighted-lines: (1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15),
|
||||
..default-codly
|
||||
)
|
||||
}
|
||||
#let partial-hide(
|
||||
i,
|
||||
hidden: (),
|
||||
partial: (),
|
||||
body
|
||||
) = {
|
||||
if i in hidden {
|
||||
hide(body)
|
||||
} else if i in partial {
|
||||
set text(fill: luma(200))
|
||||
body
|
||||
} else {
|
||||
body
|
||||
}
|
||||
}
|
||||
#set align(center+horizon)
|
||||
|
||||
#grid(
|
||||
columns: (1fr, 1fr),
|
||||
column-gutter: 2em,
|
||||
yes-codly[
|
||||
#scale(60%, reflow: true,
|
||||
```python
|
||||
def get_dex_name(index: int):
|
||||
if index == 0:
|
||||
return "classes.dex"
|
||||
else:
|
||||
return f"classes{index+1}.dex"
|
||||
def load_class(class_name: str):
|
||||
if is_platform_class(class_name):
|
||||
return boot_cl.load(class_name)
|
||||
else:
|
||||
index = 0
|
||||
dex_file = get_dex_name(index)
|
||||
while exists_in_apk(dex_file) and \
|
||||
class_name not in classes_of(dex_file):
|
||||
index += 1
|
||||
dex_file = get_dex_name(index)
|
||||
if file_exists_in_apk(dex_file):
|
||||
return load_from_file(dex_file, class_name)
|
||||
else:
|
||||
raise ClassNotFoundError()
|
||||
```)
|
||||
], [
|
||||
#set align(left)
|
||||
#set text(size: 18pt)
|
||||
#partial-hide(i, hidden: (0,), partial: (2,))[
|
||||
=== SDK shadowing
|
||||
Trick the tool into using an APK class instead of an SDK class
|
||||
]
|
||||
#partial-hide(i, hidden: (0,), partial: (2,))[
|
||||
=== 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
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
#slide(
|
||||
title: [Impact on Tools],
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#show figure.caption: none
|
||||
#show link.where(dest: <acr-sdk>): it => it.body
|
||||
#show figure: it => {
|
||||
set align(left)
|
||||
show table: set align(center+horizon)
|
||||
it
|
||||
}
|
||||
#scale(100%, reflow: true, get_figure(<tab:cl-results>))
|
||||
]
|
||||
|
||||
#slide(
|
||||
title: [Example: Androguard],
|
||||
foreground: eye-4(x: 97%, y: 85%, mirror: true)
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#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>)
|
||||
)
|
||||
]
|
||||
|
||||
#for i in range(3) {
|
||||
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
|
||||
slide(
|
||||
title: [In the Wild],
|
||||
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(
|
||||
fill: (x, y) => {
|
||||
if (
|
||||
i == 1 and (x, y) in ((1, 13), (2, 13), (4, 13), (8, 13))
|
||||
) or (
|
||||
i == 2 and (x, y) in ((1, 14), (2, 14))
|
||||
) {
|
||||
highlight-color
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
)
|
||||
#scale(90%, reflow: true, get_figure(<tab:cl-shadow>))
|
||||
]
|
||||
}
|
||||
|
||||
#slide(
|
||||
title: [Conclusion]
|
||||
)[
|
||||
#item-by-item[
|
||||
- We modeled the class loading algorithm
|
||||
- Static Analysis Tools did not
|
||||
- We introduced obfuscation techniques based on this model
|
||||
- Ambiguous cases exists in the wild
|
||||
- We did not find deliberate shadow attacks
|
||||
]
|
||||
]
|
||||
|
||||
#slide[
|
||||
|
|
@ -701,20 +915,293 @@
|
|||
|
||||
#new-section-slide([The Application of Theseus])
|
||||
|
||||
#slide[Th 1
|
||||
|
||||
#slide(
|
||||
title: [Overview],
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#show figure.caption: none
|
||||
#scale(100%, reflow: true, get_figure(<fig:th-process>))
|
||||
]
|
||||
#slide[Th 2
|
||||
|
||||
#slide(
|
||||
title: [Dynamic Analysis],
|
||||
)[
|
||||
- Frida: intercepts method calls
|
||||
|
||||
#v(2em)
|
||||
|
||||
#uncover("2-")[
|
||||
- Android Emulator: runs on computer/server
|
||||
- Grodd Runner: clicks buttons
|
||||
]
|
||||
|
||||
#v(2em)
|
||||
#uncover(3)[
|
||||
- Phone with adb enable: actuall hardware
|
||||
- Human: intelligent button clicker
|
||||
]
|
||||
]
|
||||
|
||||
#slide(
|
||||
title: [Dynamic Code Loading],
|
||||
foreground: ghost-6(x: 80%, y: 15%, mirror: true)
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#show figure.caption: none
|
||||
#show image: box.with(width: 58%)
|
||||
#get_figure(<fig:th-inserting-dex>)
|
||||
]
|
||||
|
||||
#for i in range(4) {
|
||||
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
|
||||
|
||||
slide(
|
||||
title: [Reflection],
|
||||
//foreground: ghost-6(x: 80%, y: 15%, mirror: true)
|
||||
)[
|
||||
#show: yes-codly
|
||||
#set align(center+horizon)
|
||||
|
||||
#if i == 1 {
|
||||
codly(
|
||||
highlighted-lines: (6,),
|
||||
..default-codly
|
||||
)
|
||||
} else if i == 3 {
|
||||
codly(
|
||||
offset: 5,
|
||||
..default-codly
|
||||
)
|
||||
} else {
|
||||
codly(..default-codly)
|
||||
}
|
||||
|
||||
#if i in (0, 1) {
|
||||
```java
|
||||
ClassLoader cl = MainActivity.class.getClassLoader();
|
||||
Class clz = cl.loadClass("Reflectee");
|
||||
Object obj = clz.newInstance();
|
||||
Method mth = clz.getMethod("myMethod", String.class);
|
||||
Object[] args = {(Object)"an argument"};
|
||||
String retData = (String) mth.invoke(obj, args);
|
||||
```
|
||||
} else if i == 2{
|
||||
```java
|
||||
ClassLoader cl = MainActivity.class.getClassLoader();
|
||||
Class clz = cl.loadClass(getFromInternet());
|
||||
Object obj = clz.newInstance();
|
||||
Method mth = clz.getMethod(getFromInternet(), String.class);
|
||||
Object[] args = {(Object)getFromInternet()};
|
||||
String retData = (String) mth.invoke(obj, args);
|
||||
```
|
||||
} else {
|
||||
```java
|
||||
String retData = (String) mth.invoke(obj, args);
|
||||
```
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
#for i in range(5) {
|
||||
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
|
||||
|
||||
slide(
|
||||
title: [Reflection Transformation]
|
||||
)[
|
||||
#show: yes-codly
|
||||
#set align(center+horizon)
|
||||
#if i == 1 {
|
||||
codly(
|
||||
offset: 5,
|
||||
highlighted-lines: (10,),
|
||||
..default-codly
|
||||
)
|
||||
} else if i == 2 {
|
||||
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),
|
||||
),
|
||||
..default-codly
|
||||
)
|
||||
} else if i == 4 {
|
||||
codly(
|
||||
offset: 5,
|
||||
highlights: (
|
||||
(line: 7, start: 5, end: 43, fill: pirat-color.blue),
|
||||
(line: 8, start: 21, end: 31, fill: pirat-color.blue),
|
||||
(line: 8, start: 38, end: 45, fill: pirat-color.blue),
|
||||
(line: 8, start: 47, end: 54, fill: pirat-color.blue),
|
||||
),
|
||||
..default-codly
|
||||
)
|
||||
} else {
|
||||
codly(
|
||||
offset: 5,
|
||||
..default-codly
|
||||
)
|
||||
}
|
||||
```java
|
||||
Object objRet;
|
||||
if (T.check_is_reflectee_mymethod_XXXX(mth)) {
|
||||
objRet = (Object)((Reflectee) obj).myMethod((String)args[0]);
|
||||
} else {
|
||||
objRet = mth.invoke(obj, args);
|
||||
}
|
||||
String retData = (String) objRet;
|
||||
```
|
||||
]
|
||||
}
|
||||
|
||||
#slide(
|
||||
title: [Dynamic Analysis],
|
||||
foreground: ghost-1(x: 97%, y: 10%, height: 70pt)
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#show figure.caption: none
|
||||
#set table(
|
||||
fill: (x, y) => {
|
||||
if (
|
||||
x == 4 and y > 2
|
||||
) {
|
||||
highlight-color
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
)
|
||||
#scale(100%, reflow: true, get_figure(<tab:th-dyn-visited>))
|
||||
]
|
||||
|
||||
#slide(
|
||||
title: [Collected Bytecode],
|
||||
foreground: eye-1(x: 5%, y: 70%, height: 70pt)
|
||||
)[
|
||||
#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 (
|
||||
x == 4 and y > 2
|
||||
) {
|
||||
highlight-color
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
)
|
||||
#scale(90%, reflow: true, get_figure(<tab:th-bytecode-hashes>))
|
||||
]
|
||||
|
||||
#for i in range(3) {
|
||||
if i != 0 { counter("logical-slide").update( n => n - 1 ) }
|
||||
|
||||
slide(
|
||||
title: [Added Calls],
|
||||
)[
|
||||
#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)
|
||||
) or (
|
||||
i == 2 and (x == 4 and y > 1)
|
||||
){
|
||||
highlight-color
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
)
|
||||
#scale(90%, reflow: true, get_figure(<tab:th-compare-cg>))
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
#slide(
|
||||
title: [Added Calls],
|
||||
foreground: ghost-3(x: 93%, y: 10%)
|
||||
)[
|
||||
#import "@preview/diagraph:0.3.5": render
|
||||
#set align(center+horizon)
|
||||
#scale(47%, box(render(
|
||||
read("5_theseus/figs/patched_main_main.dot"),
|
||||
//width: 100%,
|
||||
labels: (name) => { move(dy: -7pt, scale(140%, text(size: 10pt, weight: "bold", name))) }
|
||||
)))
|
||||
]
|
||||
|
||||
#slide(
|
||||
title: [Impact on Finishing Rate],
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
#show figure.caption: none
|
||||
#scale(90%, reflow: true, get_figure(<fig:th-status-npatched-vs-patched>))
|
||||
]
|
||||
|
||||
#slide(
|
||||
title: [Conclusion],
|
||||
)[
|
||||
#item-by-item[
|
||||
- We can statically analyse APKs with reflection and dynamic code loading with our method
|
||||
- Our dynamic analysis is questionable
|
||||
- The dynamically loaded bytecode we intercepted is mainly telemetry and advertisement related
|
||||
- We released a tool to instrument APKs
|
||||
]
|
||||
]
|
||||
|
||||
#new-section-slide([Conclusion])
|
||||
|
||||
#slide[Conclusion 1
|
||||
#slide[
|
||||
We showed that:
|
||||
|
||||
#item-by-item[
|
||||
- After five years, more than half the static analysis tools are no longer usable.
|
||||
The size of the application seems to be the most significant factor.
|
||||
- Android behaviour is complex and 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.
|
||||
- APKs can be augmented with instrumentation to improve further analyses with any other tools.
|
||||
- Also, dynamic analysis is still very much not trivial.
|
||||
]
|
||||
]
|
||||
#slide[Conclusion 2
|
||||
|
||||
#slide(
|
||||
title: [Futur Work],
|
||||
foreground: {
|
||||
ghost-3(x: 80%, y: 70%)
|
||||
ghost-6(x: 20%, y: 30%)
|
||||
ghost-7(x: 70%, y: 20%)
|
||||
}
|
||||
)[
|
||||
#set align(center+horizon)
|
||||
A lot of engineering, preferably spearheaded by Google.
|
||||
]
|
||||
|
||||
#counter("logical-slide").update( n => n - 1 )
|
||||
#slide(
|
||||
title: [Futur Work]
|
||||
)[
|
||||
#item-by-item[
|
||||
- Benchmark to evaluate finishing rate
|
||||
- Make tools reusing sources from Android Open Source Project
|
||||
- Require developpers to provide high coverage tests inputs with the APKs
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue