deobfuscation of obfuscated software kurucsai istván · final binary morpher is tightly coupled...
TRANSCRIPT
Deobfuscation of obfuscated software
Kurucsai István
Tartalom
● Bevezetés● Obfuszkáció típusai● Mit és hol?● Deobfuszkáció
– Szintaxis alapú módszerek
– Szemantikus módszerek
● Összefoglalás
Bevezetés
● Anti-reversing: programok visszafejtésének megnehezítése
– Az előadás keretében: natív Windows alkalmazások
● Motivációk:– Illegális szoftvermásolás akadályozása
– Kritikus/értékes algoritmusok védelme
– Kártékony kódok elrejtése
● Csak nehezítés, a visszafejtés időigényét és költségét növelhetjük
– Tökéletes védelem nem megvalósítható
Anti-reversing
● ~ ára– Kódméret növekedése
– Teljesítmény csökkenése
● Kompatibilitási kérdések– SecuROM
● Hatékonyság nehezen mérhető: mennyivel nehezebb visszafejteni a kódot?
– Embernek
– Automatikus eszközöknek
Anti-reversing módszerek
● Szimbólumok/debug információk eltávolítása– Natív alkalmazások esetén szinte mindig
megtörténik
– Bytecode alapú nyelveknél fontos
● Packerek/wrapperek (csomagolás)● Virtualizáció● Anti-debugging/disassembly/VM/dumping
trükkök ● Obfuszkáció● Gyakran együtt jelennek meg
Refused és Stubborn
● Önálló laboratórium keretében készített programok
● Refused: source-to-source transformer– Különböző obfuszkációs módszerek
● Stubborn: Windows PE packer
Kártékony kódok elrejtése (packerek)
Obfuszkáció
● A funkcionalitás megőrzése mellett a kód „összezavarása”, az olvashatóság csökkentése
– Layout obfuscations: szimbólumok és kommentek eltávolítása, formázás megváltoztatása
● Natív bináris készítésekor a fordító elvégzi
– Preventív transzformációk: a deobfuszkálásnál felhasznált eszközök esetleges gyengeségeinek kihasználása
Adat obfuszkáció
● A program által használt adatok struktúrája és a konstansok nagyban segítik a visszafejtést
Adat obfuszkáció
● Számos módszer– Tárolás és kódolás transzformációja
– Tömbök átszervezése (tömbök összevonása és szétválasztása, dimenziók számának növelése/csökkentése, elemek permutációja)
– A hatékonyság és általánosság hiánya illetve költségeik gyakran kérdésessé teszi az alkalmazhatóságukat
Konstansok védelme
● A konstansok védelme azonban egyszerű és hatásos lehet
● Hashelés– Amennyiben a konstanst csak egyenlőség
jellegű vizsgálatoknál használja a program és nincs szükség a konkrét értékére (==, !=, !strcmp, stb...)
– if (a == 24) helyett if (hash(a) == 356725135)
– A megfelelő hash kiválasztása● Ütközésmentesség: a program helyes műküdése● Egyirányúság: visszafejtés nehézsége
Konstansok védelme II
● Ha a konstans eredeti értékére is szükség van– Titkosítás majd futásidőben a használat előtt
ideiglenes dekódolás
– Stringek egyszerű (XOR, SUB) rejtjelezése
– Bonyolultabb algoritmusok, például blokkrejtjelezők alkalmazása nem jelent különösebb nehézséget, mert futásidőben úgyis megjelenik a konstans eredeti értéke és a kulcs is
Adat obfuszkáció
● Összességében– A konstansok védelme alapfunkciónak számít
– Az általánosabb adat obfuszkációs megoldások viszont kevésbé elterjedtek
● Nehéz az általános megvalósítás● Nagy overhead● Gyenge védelem
Control-flow obfuscation
● A program vezérlési struktúrájának összezavarása
● Sokat kutatott terület● A legtöbb obfuszkátor alapja
Opaque predicates (átlátszatlan feltételek)
● Olyan elágazás-feltételek, melyek mindig igazra vagy hamisra értékelődnek ki, de ezt nehéz belátni a visszafejtett programot vizsgálva
– Egyszerű példa: (x + x^2) % 2 == 0
– A hatásosság nagyban függ a predikátumok változatosságától és bonyolultságától
● Ilyen elágazásokat elhelyezve a programban annak vezérlésfolyama bonyolítható
Példa feltételek
Opaque predicates példa I (Refused)
Opaque predicates példa II
●
Opaque predicates példa III
Opaque predicates
● Platformfüggő feltételek– Kihasználva egyes operációs rendszerek vagy
API-k sajátosságait● Regiszter értéke a program indulásakor vagy
valamelyik API visszatérése után
– Erős feltételek hozhatóak létre
– Kompatibilitás hiánya
● Összességében:– Hatásos és egyszerű
– Jól kombinálható más módszerekkel
CFG flattening(vezérlési gráf kilapítása)
● Célja a vezérlésfolyam elrejtése● Függvény basic blockokra osztása● Eredetileg más mélységben lévő blokkok egy
szintre hozása– switch kifejezésben (kiválasztás)
– A blokkok végén a switch-et vezérlő változó megfelelő beállítása
– A kiválasztás ciklusba ágyazása
CFG flattening példa
CFG flattening példa II
Diablo CFG flattening
Apple FairPlay CFG flattening
Junk code insertion(szemét kód beszúrása)
● Do-nothing vagy do-little● Az ember számára olvashatatlan és
értelmezhetetlen kód automatizált eszközökkel gyakran hatékonyan kezelhető
Junk code példa
További vezérlésfolyam obfuszkációk
● CFG arches meshing● Inlining/outlining● Cloning of functions● Combined functions
Mit és hol?
● A cél a kimeneti bináris obfuszkációja● De az egyes módszerek alkalmazhatóak a
– fordítás különböző lépéseiben (forráskód, köztes reprezentáció, tárgykód)
– kész binárison is
Mit és hol? II
● Célszerű a legmegfelelőbb helyet kiválasztani minden transzformációhoz
– Packelés csak a kész binárison
– CFG kilapítása bármelyik lépésben
– Szemét kód● Ha a forrásba illesztjük, a fordító
kioptimalizálhatja● Ha a kész binárisba, ügyelni kell a
mellékhatásokra (regiszterek, különösen EFLAGS)
Opaque predicates példa I
Refused
● Source-to-source transformation● C/C++ kódok támogatása● Funkciók:
– Opaque predicates
– Szemét kód (félkész)
– CFG flattening (félkész)
Clang/LLVM
● C nehezen parse-olható, a C++ még nehezebben
● Az LLVM frontendjének felhasználása (Clang)– Transzformációk az abstract syntax tree-n
(AST)
Morpher
● „Morpher is a versatile and flexible automatic software transformation toolkit focused on protection of software algorithms. Despite of other software protection solutions on the market which operate only on the final binary Morpher is tightly coupled with the industry-standard C/C++ compiler and thus can exploit much more information about sources to be protected. Note that such information is normally lost during compilation and codegeneration.”
● Functions interleaving and merging;
● Opaque predicates insertion;
● Opaque variables insertion (generic framework used by other transformation passes);
● Automatic constants (e.g. string literals) protection and encryption;
● Code flow graph altering;
● LLVM optimalizációs lépésekként implementált – obfuscating compiler
Deobfuszkáció – szintaktikus vs. szemantikus módszerek
● Szintaxis-alapú: csak az objektumok formátumát figyelembe vevő módszerek
– Gépi kód / assembly utasítások bájtjainak sorozata, esetleges wildcardok
● Szemantikus: az objektumok jelentését is számításba vevő módszerek
– Az utasítások hatásai/mellékhatásai
Szintaxis-alapú módszerek
● Pro– Gyors (gyakorlatilag mintaillesztés)
– Néhány problémára remek megoldást jelentenek
● Con– Sok probléma egyáltalán nem oldható meg így
● Tipikus felhasználás:– Signatures: packer entrypoint, FLIRT, anti-virus
– Egyszerű deobfuszkáció
Szintaxis-alapú deobfuszkáció
● Amennyiben a transzformáció valamilyen felismerhető mintázatot tartalmaz
● Emulált jmp és call: push/ret
Szintaxis-alapú deobfuszkáció II
● A korábbi szemét kód példa:
Korlátok
● Mi történne, ha az előző példa tartalmazna – egy aritmetikai utasítást amire nem készültünk
fel?
– egy feltételes ugrást?
– egy átlátszatlan feltételt?
● A szintaxis-alapú módszerek hatékonyak bizonyos esetekben, de gyorsan korlátokba ütközünk
Szemantikus módszerek
● Az objektumok jelentését is számításba vevő módszerek
● Számos felhasználás a reverse engineering területén
– Automatikus kulcsgenerátor generálás :)
– Automatikus hibafelderítés
– (részben) generikus deobfuszkáció
● A program analízis akadémiai eredményeinek gyakorlatba való átültetése népszerű téma
Egy utasítás szemantikája...
● Az and (x86) utasítás köztes reprezentációja (IR - Intermediate Language translation)
Absztrakt interpretáció
● A program analízis klasszikus technikája● Bonyolult módszer, de alapja egyszerű
– Absztrakt állapot a konkrét helyett
– Absztrakt szemantika a konkrét helyett
● Egyszerű példa: váltózok előjelének meghatározása
– A változók konkrét értéke helyett csak előjelüket tartjuk nyilván
– Ennek megfelelően definiáljuk az egyes műveletek szemantikáját is
Absztrakt interpretáció példa
● Minden más információt figyelmen kívül hagyunk
Absztrakt interpretáció
● Gyakran arra vagyunk kíváncsiak, hogy egy adott pont a programban egy adott változó milyen értékeinél érhető el
● Erre a kérdésre ad választ a szimbolikus végrehajtás,
– Az absztrakt interpretáció speciális esete
Szimbolikus végrehajtás
● Minden elágazás korlátozza az értékkészletet valamilyen módon
SMT (Satisfiability Modulo Theories) solving
● Alapötlet: alakítsuk a kódot logikai formulákká, amelyeken aztán különböző tulajdonságokat bizonyíthatunk be illetve egyszerűsíthetjük
● Felhasználás: input generálás (input crafting)● Milyen értéket kell az eax regiszternek
tartalmaznia kezdetben, hogy a kód lefutása után értéke 0x12345678 legyen?
SMT solving
● A köztes reprezentációból készített SMT formula (Z3)
SMT solving II
● assert(T175d == 0x12345678);
● T175d eax végső értéke
● Sat => a formula kielégíthető
● A kimenet egy model, ami
kielégíti a formulát
● Az utolsó sorban eax értéke
Kryptonite● LLVM IR obfuszkátor
– Az összeadás utasítást lecseréli egy assemblyben megvalósított bitenkénti összeadóra
– Egy összeadásból 2000 sor assembly kód lesz
– Junk code insertion extrém esete
● Deobfuszkáció egy lehetséges megoldása:
– Szimbolikus végrehajtással meghatározzuk, hogy a függvény kimenete hogy függ a bemenetektől (a két összeadandó szám)
– Egy SMT megoldóval megpróbáljuk egyszerűsíteni az előző lépés végén kapott formulát
● Ha minden jól megy megkapjuk, hogy a kimenet minden esetben a két bement összege
Kryptonite I (szimbolikus végrehajtás)
● A szimbolikus végrehajtó motor működése:
– Szimbolikus változók tárolása (gyk. ha inicializálatlan területről találunk olvasást, akkor létrehozunk egy változót). Ezek a változók lesznek a bemenetek.
– Az egyes utasítások emulálása, az állapotok frissítése
– Az obfuszkátor sajátosságai miatt viszonylag egyszerű
Kryptonite II (SMT solving)
● A függvény végén kapott formula még az SMT solverrel való egyszerűsítés után sem túl barátságos
Kryptonite II (SMT solving)
● Miért?– Az SMT solver simplify funkciója többnyire
szintaktikus szabályok alapján dolgozik, túl bonyolult a kifejezés
● Azonban– prove(eax == Sum(sym.sym_variables))
– True
– Azaz: valóban összeadást végez a függvény
– De: ha ezt nem tudtuk volna előre, hogy jöttünk volna rá hogy mit kérdezzünk a solvertől?
– Nyitott kérdés
OptiCode
● Deobfuszkációs megoldás– Opaque predicates
– Junk code
● LLVM köztes reprezentáció● Z3 SMT solver● Részben manuális megoldás
OptiCode (junk code)
● A különböző fordítók optimalizáló és kódgeneráló részei folyamatosan fejlődnek.
● Kiválóan alkalmasak redundáns kódok eltávolítására
● Szintaktikus és szemantikus módszerek● Az obfuszkált kódot a fordító köztes
reprezentációjára konvertálva lefuttathatjuk rajta az optimalizációs lépéseket
● A kimenetet újra lefordítva tisztább kódot kapunk
OptiCode (opaque predicates) ● Dinamikus analízis● Átlátszatlan feltételek kiszűrése● Részben automatizált megoldás
– Az analízist végző plusz információkkal segíti az eszköz működését, illetve ellenőrzi a feltételek kiválasztását
● LLVM IR-ből az egyes feltételek SMT formuláinak meghatározása
● Z3 SMT solverrel a formulák vizsgálata● Amennyiben a feltétel mindig igaz vagy hamis,
csak a megfelelő ág követése
Összefoglalás - deobfuszkáció
● A szemantikus módszerek egyre nagyobb teret nyernek
● Aktív kutatási terület (illetve a kutatási eredmények gyakorlati felhasználása lendületesen halad)
● Tökéletes védelem nem létezik– De reális cél a visszafejtés költségeit jelentősen
növelni
● Kevés a jól használható és ingyenes eszköz● Sok nyitott kérdés
Kérdések?
Köszönöm a figyelmet!
Felhasznált források
http://www.wtbw.co.uk/semantics-based-methods.pdf
● http://doar-e.github.io/blog/2013/09/16/breaking-kryptonites-obfuscation-with-symbolic-execution/
● Binary-Code Obfuscations in Prevalent Packer Tools by KEVIN A. ROUNDY and BARTON P. MILLER
● http://www.inf.u-szeged.hu/~akiss/pub/pdf/laszlo_obfuscating.pdf
● http://blog.sei.cmu.edu/post.cfm/semantic-code-analysis-for-malware-code-deobfuscation
● http://www.data.proidea.org.pl/confidence/11edycja/NGUYEN_Anh_Quynh.pdf