In this article I will first give an introduction to LLVM, and then I will present a little LLVM-IR obfuscater PoC I have coded for fun. Here is the introduction of the article:

For several months, I came across a lot of papers that use the LLVM framework to develop really cool tools like:

  • decompilation framework (Dagger),
  • universal deobfuscation (Opticode),
  • bug-finding with static binary instrumentation (AddressSanitizer),
  • fast C compiler (Clang),
  • automatic test cases generator (Klee),
  • etc.

In other words, LLVM is everywhere, and it’s only the beginning.

In this paper, I will try in a first part, to give you an overview of the framework: basically what you can do with it and what you cannot. Then, I will introduce a PoC called Kryptonite: a small obfuscater based on LLVM. We will talk about how you can build such tools and how they can be improved.

I’m currently playing with the version 3.3 of LLVM (the latest when I’m writing this paper), so the code may changed a bit for the upcoming version (don’t hesitate to shoot me an email if this is the case).

Keep in mind that no CPUs were harmed during this piece of research, trust me.


The article has been uploaded here, the sources of the PoC are available on my github account here, and the binaries for the crackme are here.

I hope you will enjoy the read, cheers!

15 commentaires pour le moment

Ajoutez votre commentaire
  1. Great reading and cool approach to code obfuscation, I was wondering could it be used with llvm output obfuscation too?

  2. Hey Bartosz,

    First of all, thank you for your feedback, I’m really glad you enjoyed the reading!
    But I’m not sure I understand fully your question, could you be more specific please ?
    As soon as you’re able to produce a valid LLVM-IR code (by using a frontend like clang, or any way you want), you can use an optimization pass to do the transformation work ; then you can use whatever backend you want to produce a fully-obfuscated final binary: like a ARM PE32 ; or a Sparc32 Elf :-)!

    Have a nice day Bartosz, and thanks again!

  3. Very nice and interesting.

  4. Thank you qnix!

  5. 0vercl0k I mean you are modifying code in the optimization phase right, but my question was is it possible to obfuscate the IR source code too or it makes no sense at all? 😀

  6. Oh ok, you mean like to modify the raw sources with regex or stuff like that ? It is possible yep, maybe a bit crazy, but it’s doable :P. But trust me the LLVM frontend API is quite easy to use, you should try it out!

  7. Hello. Could you tell me how can i build and run kryptonite on windows? I tried to build it by using commands from https://github.com/0vercl0k/stuffz/blob/master/llvm-funz/kryptonite/llvm-functionpass-kryptonite-obfuscater.cpp
    but every time i failed with some errors. So basically i want to understand how to build kryptonite and run it with crackme on windows. Thanks.

  8. Hello there,

    Do you have more details about the error messages ?
    During the compilation process or ?


  9. I’m trying to execute this command – « clang++ cr.cpp $(llvm-config –cxxflags –ldflags –libs core) -I../include -shared -o cr.exe » (I don’t really know what i’m supposed to get – .exe or .obj) and that’s what i get – http://puu.sh/4ZUWI.png

  10. That command is supposed to give you a dll file, loadable in « opt ». The thing is, if I remember correctly, that « opt » on Windows isn’t able to load dynamically optimization pass.
    My trick was to do most of the work on a Linux machine, because easier, and then when you have an object file (ouput of « llc »), you move it to your Windows machine and you compile it statically with your Windows-clang.

    On my linux machine:

    overclok@theokoles:/tmp$ wget https://raw.github.com/0vercl0k/stuffz/master/llvm-funz/kryptonite/llvm-functionpass-kryptonite-obfuscater.cpp
    overclok@theokoles:/tmp$ export PATH=/tmp/clang+llvm-3.3-i386-debian6/bin:$PATH
    overclok@theokoles:/tmp$ clang++ llvm-functionpass-kryptonite-obfuscater.cpp `llvm-config --cxxflags --ldflags --libs core` -shared -o llvm-functionpass-kryptonite-obfuscater.so
    overclok@theokoles:/tmp$ wget https://raw.github.com/0vercl0k/stuffz/master/llvm-funz/kryptonite/kryptonite-crackme.c
    overclok@theokoles:/tmp$ clang -S -emit-llvm kryptonite-crackme.c -o kryptonite-crackme.original.ll
    overclok@theokoles:/tmp$ wc -l ./kryptonite-crackme.original.ll
    318 ./kryptonite-crackme.original.ll
    overclok@theokoles:/tmp$ cp kryptonite-crackme.original.ll kryptonite-crackme.ll
    overclok@theokoles:/tmp$ opt -S -load ./llvm-functionpass-kryptonite-obfuscater.so -kryptonite kryptonite-crackme.ll -o kryptonite-crackme.opti.ll
    Function being handled: main (heavy mode: no, anti debug: 0)
    0. Let's find instructions to obfuscate.. -- Found 26 instructions to obfuscate (total instructions: 233)
    1. Time to obfuscate them now..
    overclok@theokoles:/tmp$ mv kryptonite-crackme.opti.ll kryptonite-crackme.ll ;
    overclok@theokoles:/tmp$ wc -l ./kryptonite-crackme.ll
    2338 ./kryptonite-crackme.ll

    On my Windows machine, you have to edit the « target triple » line on the kryptonite-crackme.ll:

    target triple = "i386-pc-linux-gnu"
    target triple = "i386-pc-win32"

    If you don’t do that llc will generate a object file for linux target and link.exe won’t like it much :)).
    Then you can generate the Windows object file with llc:

    D:\Downloads\tmp>wget http://download.tuxfamily.org/overclokblog/clang%2bllvm3.3%20WinX86%20VS2k10%20Release.7z
    D:\Downloads\tmp>cd "clang+llvm3.3 WinX86 VS2k10 Release"
    D:\Downloads\tmp\clang+llvm3.3 WinX86 VS2k10 Release>cd "clang+llvm3.3 WinX86 VS2k10 Release"
    D:\Downloads\tmp\clang+llvm3.3 WinX86 VS2k10 Release\clang+llvm3.3 WinX86 VS2k10 Release>llc -O0 -filetype=obj -march=x86 ..\..\kryptonite-crackme.ll -o ..\..\kryptonite-crackme.Win32.obj

    Now you just have to link it with VS’s link.exe:

    D:\Downloads\tmp\clang+llvm3.3 WinX86 VS2k10 Release\clang+llvm3.3 WinX86 VS2k10 Release>link.exe ..\..\kryptonite-crackme.Win32.obj -defaultlib:libcmt
    Microsoft (R) Incremental Linker Version 11.00.50727.1
    Copyright (C) Microsoft Corporation.  All rights reserved.
    D:\Downloads\tmp\clang+llvm3.3 WinX86 VS2k10 Release\clang+llvm3.3 WinX86 VS2k10 Release>kryptonite-crackme.Win32.exe
    D:\Downloads\tmp\clang+llvm3.3 WinX86 VS2k10 Release\clang+llvm3.3 WinX86 VS2k10  Release>kryptonite-crackme.Win32.exe you_got_the_key!
    Good job dude! The key is: you_got_the_key!

    And here you go :), I hope it will help you!

  11. Well it took two days for me to build it but finally it’s been worked! Thank you.

  12. Hehe congrats mate!
    Sorry, I should have put the build notes somewhere, ’cause it’s a bit tricky/weird I agree :).
    Anyway, I was happy to help you!


  13. […] software, and few of them are able to obfuscate C/C++/Objective-C code in an effective way (Kryptonite being an example). Moreover, I am aware of only a handful of vendors selling commercial tools of […]

  14. Excellent read!

    I think the Cout and S column headings in your full adder truth table are swapped though.

    Thanks for this!

  15. Oh brilliant Bonedaddy — you are indeed right, I’ve corrected this: https://github.com/0vercl0k/articles/commit/346c996d4d4c07ee955256aae57c2b2333014284 :).


Get Adobe Flash player