#import "@preview/polylux:0.4.0": * #import "slides/lib.typ": * #import "@preview/codly:1.3.0": * #import "@preview/codly-languages:0.1.1": * #show: codly-init.with() #let default-codly = ( display-name: false, display-icon: false, zebra-fill: none, fill: luma(240), radius: 1em, inset: (y: 0.15em), highlighted-default-color: highlight-color, highlight-fill: it => it.lighten(40%), //highlight-color, ) #codly-disable() #set text(lang: "en") #set list(marker: none) #show: sns-polylux-template.with( txt-font: "New Computer Modern", title-font: "TeX Gyre Heros", 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], //short-event : [Rennes, 2025/12/9], title-size : 32pt, section-size : 18pt, size : 22pt, //logo-1 : image("slides/imgs/logo_irisa.png"), //logo-2 : image("slides/imgs/logo_pirat.png"), // colormap : sns-polylux-template_sns-pirat, authors : ( { set text(weight: "bold") [MINEAU Jean-Marie] v(1em) }, [LALANDE Jean-François, PhD supervisor], [VIET TRIEM TONG Valérie, PhD co-supervisor] ), date : datetime(year: 2025, month: 12, day: 9), ) /* * Intro: * Dear jury, gentle people of the audience, here and online, thank you for your presence. * I am Jean-Marie Mineau, and today I will be defending my thesis about Android Application reverse engineering and the many difficulties a reverse engineer might encounter. * This thesis was suppervised by Jean-François Lalande and Valerie Viet Triem Tong, within the PIRAT research team at IRISA. */ #title-slide( logo: grid(columns: 2, image("slides/imgs/logo_pirat.png"), image(width: 500pt, "slides/imgs/logo_cs.png"), image("slides/imgs/logo_irisa.png"), image("slides/imgs/platypus.png"), ) ) #slide( new-sec: true, title: [Introduction], hide-title: true, /*foreground: { ghost-5(x: 10%, y: 30pt) ghost-4(x: 95%, y: 80%) //ghost-4(x: 45%, y: 43%) }*/ )[ #set align(center+horizon) #grid( columns: (1fr, 1fr), image("slides/imgs/google.png", width: 200pt), image("slides/imgs/phone.png", height: 350pt) ) #v(2em) ] #counter("logical-slide").update( n => n - 1 ) #slide( foreground: ghost-4(x: 60%, y: 25%, rot: 45deg) )[ #set align(center+horizon) #grid( columns: (3fr, 2fr), stack(dir: ltr, item-by-item[ - Personal Data and PII - Computing Power - Phone - Mic, Camera, \ Geolocalisation ], [ $ => $ ], item-by-item()[ - Ransomware/Spyware - Cryptojacker - Expander (phone billing) - Stalkerware ] ), { move(dx: 20pt, image("slides/imgs/phone.png", height: 350pt)) } ) ] #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(, form: "prose"): systematic literature review for Android static analysis, lists open-sourced tools - #cite(, 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) )[ #set list(marker: [-]) Applications might use *obfuscation* to either: - protect their IP - hide malicious behaviour #v(1em)#uncover(2)[ We will focus on two techniques: - *Dynamic Code Loading* - *Reflection* ] ] #for i in range(4) { if i != 0 { counter("logical-slide").update( n => n - 1 ) } show: yes-codly slide( title: [Obfuscation], subtitle: if i == 0 [Example] else if i == 1 [Dynamic Code Loading] else if i in (2, 3) [Reflection] else { none }, foreground: eye-1(x: 95%, y: 85%, mirror: true) )[ #if i == 0 { codly(..default-codly) } else if i == 1 { codly( highlighted-lines: (1, 5, 6, 7, 8), ..default-codly ) } else if i == 2 { codly( highlighted-lines: (2, 3), highlights: ( (line: 10, start: 42, end: 59, fill: pirat-color.blue), (line: 13, start: 3, end: 21, fill: pirat-color.blue), ), ..default-codly ) } else if i == 3 { codly( highlighted-lines: (10,), highlights: ( (line: 12, start: 14, end: 34, fill: pirat-color.blue), (line: 15, start: 2, end: 19, fill: pirat-color.blue), ), ..default-codly ) } #scale(70%, 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); ```] ] } #counter("logical-slide").update( n => n - 1 ) #slide( title: [Obfuscation], subtitle: [Deobfuscated], )[ #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) { } } String ret = Foo.bar("FooBar"); ```] ] #slide( title: [Class Loading], )[ #set align(center) #show: yes-codly #grid( columns: (2fr, 1em, 1fr), scale(70%, reflow: true)[ #codly( highlights: ( (line: 1, start: 0, end: 11, fill: pirat-color.blue), (line: 1, start: 22, end: 43, fill: pirat-color.blue), (line: 3, start: 14, end: 27, fill: pirat-color.blue), (line: 6, start: 32, end: 40, fill: pirat-color.blue), ), ..default-codly ) ```java ClassLoader cl = new InMemoryDexClassLoader( ByteBuffer.wrap(Base64.decode(DEX, 2)), Main.class.getClassLoader() ); Class loadedClass = this.cl.loadClass(decrypt(className)); ``` ], [], uncover(2, scale(70%, reflow: true)[ #codly( ..default-codly ) ```java class A { public static void foo() { B b = new B(); b.bar(); } } ``` Where is the class loader? ]) ) ] #counter("logical-slide").update( n => n - 1 ) #slide( title: [Class Loading], )[ #item-by-item[ - Used to select classes implementation - More complexe than it looks - Doubious documentation - Not studied in the context of Android Static Analysis ] ] #counter("logical-slide").update( n => n - 1 ) #slide( title: [Class Loading], )[ #highlight-block(pb2-text) ] #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 - Some values cannot be computed ] ], grid.cell(colspan: 2, uncover(7)[ #text(size: 30pt)[Can we combine both?] ]), ) ] #slide[ #highlight-block(pb3-text) ] #slide[ #highlight-block(pb1-text) #highlight-block(pb2-text) #highlight-block(pb3-text) ] #new-section-slide([Tool Reusability]) #slide[ Rasta 1 /* #stack(dir: ltr, scale(40%, reflow: true, get_figure()), scale(55%, reflow: true, get_figure()), )*/ ] #slide[ Rasta 2 ] #new-section-slide([Class Shadowing]) #slide[Shadow 1 ] #slide[Shadow 2 ] #slide[Shadow 3 ] #new-section-slide([The Application of Theseus]) #slide[Th 1 ] #slide[Th 2 ] #new-section-slide([Conclusion]) #slide[Conclusion 1 ] #slide[Conclusion 2 ] #empty-slide[ Questions ] /* #slide()[ #get_figure()) ] #slide()[ #pl.toolbox.slide-number #context({ pl.toolbox.all-sections((sections, current) => { for i in sections { repr(i.at("body").at("text")) } }) }) ] */ #pagebreak() #set page(height: auto, margin: 25mm) #bibliography("bibliography.bib")