We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Intro to Wichcraft Compiler Collection

00:00

Formal Metadata

Title
Intro to Wichcraft Compiler Collection
Title of Series
Number of Parts
93
Author
License
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
With this presentation, we take a new approach to reverse engineering. Instead of attempting to decompile code, we seek to undo the work of the linker and produce relocatable files, the typical output of a compiler. The main benefit of the later technique over the former being that it does work. Once achieved universal code ‘reuse’ by relinking those relocatable objects as arbitrary shared libraries, we’ll create a form of binary reflection, add scripting capabilities and in memory debugging using a JIT compiler, to attain automated API prototyping and annotation, which, we will argue, constitutes a primary form of binary code self awareness. Finally, we’ll see how abusing the dynamic linker internals shall elegantly solve a number of complex tasks for us, such as calling a given function within a binary without having to craft a valid input to reach it. The applications in terms of vulnerability exploitation, functional testing, static analysis validation and more generally computer wizardry being tremendous, we’ll have fun demoing some new exploits in real life applications, and commit public program profanity, such as turing PEs into ELFs, functional scripting of sushi in memory, stealing crypto routines without even disassembling them, among other things that were never supposed to work. All the above techniques have been implemented into the Witchcraft Compiler Collection, to be released as proper open source software (MIT/BSD-2 licenses) exclusively at DEF CON 24. Bio: Jonathan Brossard is a computer whisperer from France, although he’s been living in Brazil, India, Australia and now lives in San Francisco. For his first conference at DEF CON 16, he hacked Microsoft Bitlocker, McAfee Endpoint and a fair number of BIOS Firmwares. During his second presentation at DEF CON 20, he presented Rakshasa, a BIOS malware based on open source software, the MIT Technology review labeled &lquo;incurable and undetectable&rquo;. This year will be his third DEF CON … Endrazine is also known in the community for having run the Hackie Ergo Sum and NoSuchCon conferences in France, participating to the Shakacon Program Committee in Hawaii, and authoring a number of exploits over the past decade. Including the first remote Windows 10 exploit and several hardcore reverse engineering tools and white papers. Jonathan is part of the team behind MOABI.COM, and acts as the Principal Engineer of Product Security at Salesforce.
33
35
CompilerVulnerability (computing)Reverse engineeringSingle-precision floating-point formatOpen sourceSoftware frameworkContent (media)Component-based software engineeringWeb 2.0Programming languageFile formatTrailBitGoodness of fitShared memoryDuality (mathematics)CodeSocial classComputer hardwareFirmwareSocial engineering (security)Demo (music)Projective planeCore dumpFeedbackBootingKey (cryptography)Lecture/Conference
Directory serviceInternetworkingInfinite conjugacy class propertyCodeMultiplication signSemiconductor memoryFeedbackPresentation of a groupMessage passingUser interfaceScheduling (computing)Hard disk driveInternetworkingDebuggerRevision controlMalwareRight angleSoftwareNeuroinformatikMereologySlide ruleLocal area networkCausalityLecture/Conference
Reverse engineeringContent (media)Category of beingElectronic mailing listInformation securityKey (cryptography)FAQBitCuboidSlide rulePresentation of a groupMereologyComputer programmingCASE <Informatik>CausalityFreewareShared memoryWordLecture/Conference
Library (computing)Metric systemWritingExpert systemComputer fileBitCompilerInstance (computer science)Slide ruleData compressionBinary codeMultiplication signMathematical analysisInformation securityShared memoryChainOpen setProjective planeRight angleProcess (computing)Reverse engineeringRevision controlServer (computing)Java appletVulnerability (computing)Term (mathematics)Cartesian coordinate systemLecture/Conference
CurvatureFunctional (mathematics)WritingAsynchronous Transfer ModeGenetic programmingStatement (computer science)Vulnerability (computing)Remote procedure callMathematical analysisoutputPredictabilityLibrary (computing)Binary codeComponent-based software engineeringFunctional programmingCellular automatonRight angleRootCASE <Informatik>CompilerLocal ringFluid staticsLecture/Conference
Social classGastropod shellDemo (music)outputScripting languageCodeInterpreter (computing)CompilerPower (physics)BuildingComputer scienceLinker (computing)Binary codeComputer fileComponent-based software engineeringDynamical systemCore dumpLibrary (computing)XML
Demo (music)Data compressionLine (geometry)CodeState of matterCompilerCompilerInstance (computer science)Computer fileMultiplication signComputer programmingRoutingAsynchronous Transfer ModeError messageDrop (liquid)Real numberSource codeComputer animation
Revision controlCompilerComputer configurationLjapunov-ExponentoutputComputer filePatch (Unix)Library (computing)Information privacyInstance (computer science)Data compressionRight angleComputer configurationType theoryObject (grammar)CompilerBinary codeSource codeProgram flowchartComputer animation
Computer configurationSocial classoutputScripting languageFlagCartesian coordinate systemLibrary (computing)Computer programmingLinker (computing)Semiconductor memoryFunctional (mathematics)Scripting languageCyberspaceDemo (music)File Transfer ProtocolRevision controlMoving averageGenetic programmingString (computer science)Default (computer science)Structural loadJSON
File formatParameter (computer programming)Server (computing)Patch (Unix)Semiconductor memoryLibrary (computing)Right angleDivisorBitFunctional programmingDemo (music)Linker (computing)Reading (process)Data compressionSingle-precision floating-point formatCartesian coordinate systemFunctional (mathematics)Kernel (computing)Binary codeType theoryBoom (sailing)Program flowchartSource codeLecture/Conference
IntelCartesian coordinate systemLibrary (computing)Normal (geometry)Parameter (computer programming)Open sourceComplex (psychology)Computer fileData compressionMathematical analysisLine (geometry)Reverse engineeringStability theoryBinary codeCurveFunction (mathematics)CompilerComputer architectureInheritance (object-oriented programming)AnalogySystem callData Encryption StandardLecture/Conference
Server (computing)System callVariable (mathematics)String (computer science)Computer fileSheaf (mathematics)String (computer science)Uniform resource locatorNumbering schemeRead-only memoryReading (process)Parameter (computer programming)Program flowchartComputer animationJSONSource code
System callFlagType theoryData compressionShared memoryComputer fileBinary codeCompilerLinker (computing)CompilerSource codeJSONComputer animation
outputLinker (computing)Binary codeoutputComputer fileData compressionKey (cryptography)TableauLecture/ConferenceComputer animation
DebuggerUniform resource locatorType theoryBinary codeMultiplication signBefehlsprozessorLevel (video gaming)Online helpComputer architectureObject (grammar)BitDampingComputer fileExtension (kinesiology)ArmLecture/Conference
Linker (computing)outputRevision controlComputer fileBinary codeRow (database)Virtual machineUser interfaceLibrary (computing)Proper mapRight angleData compressionOpen setCodeBitOpen sourceComputer animation
Directory serviceEwe languageSymbol tableError messageDiscrete element methodElectronic visual displayBinary codeCausalityRight angleLinker (computing)Tracing (software)JSONSource codeLecture/Conference
AerodynamicsLinker (computing)PasswordJapanese honorificsDirectory serviceLinker (computing)Sheaf (mathematics)Uniform resource locatorRight angleBinary codeInterpreter (computing)Patch (Unix)BitDynamical systemExpected valueComputer animationSource code
Directory serviceAerodynamicsLinker (computing)Japanese honorificsPasswordSymbol tableError messagePatch (Unix)Lipschitz-StetigkeitRight angleSource codeComputer animation
Japanese honorificsDirectory serviceLinker (computing)AerodynamicsSymbol tableError messageFerry CorstenFunctional (mathematics)Library (computing)Data structureVirtual machineBinary codeOpen setLine (geometry)Source code
Proper mapBinary codeProgramming languageRight angleSocial classType theoryInformationReflection (mathematics)Interpreter (computing)Semiconductor memoryJust-in-Time-CompilerFunctional (mathematics)DebuggerSlide ruleParameter (computer programming)QuicksortVirtual machineTracing (software)Structural loadCompilerDemo (music)Multiplication signLecture/Conference
SineDirectory serviceClient (computing)Sample (statistics)MathematicsServer (computing)Revision controlDemo (music)Multiplication signServer (computing)Slide ruleProgram flowchartComputer animation
Structural loadCodeControl flowRead-only memoryPhysical systemOnline helpFunction (mathematics)Sheaf (mathematics)Electronic visual displayBinary fileSemiconductor memoryStructural loadFunctional programmingMobile appFunctional (mathematics)Instance (computer science)Musical ensembleProcess (computing)CausalityComputer animationJSON
Total S.A.Structural loadSheaf (mathematics)Software frameworkFunction (mathematics)Sheaf (mathematics)Function (mathematics)Semiconductor memoryLibrary (computing)RecursionCausalityComputer programmingFunctional programmingComputer animationSource code
Total S.A.Function (mathematics)Network socketFunctional programmingSemiconductor memoryLibrary (computing)BitFunctional (mathematics)Instance (computer science)PrototypeRevision controlFile Transfer ProtocolSource codeComputer animation
Function (mathematics)Revision controlRevision controlCurveNumbering schemeVariable (mathematics)CausalityRight angleString (computer science)Context awarenessFunctional (mathematics)Real numberResultant
Function (mathematics)Total S.A.State of matterError messageContext awarenessMultiplication signFunctional programmingFluid staticsMathematical analysis2 (number)BuildingSemiconductor memoryElectronic mailing listSoftware testingJSONComputer animation
State of matterSoftware testingError messageStack (abstract data type)Military operationFunction (mathematics)Multiplication signSemiconductor memoryLocal ringBinary codeDemo (music)Structural loadArmInstance (computer science)Gastropod shellRadio-frequency identificationReverse engineeringWeb 2.0CompilerAsynchronous Transfer ModeCartesian coordinate systemVirtual machineDivisorComputer programmingFunctional programmingProcess (computing)Library (computing)Principal ideal domainRight angleRootSource codeJSONComputer animationXMLProgram flowchartLecture/Conference
Directory serviceExploit (computer security)Function (mathematics)Server (computing)Physical lawRule of inferenceClosed setParameter (computer programming)Functional (mathematics)Scripting languageSystem callRight angleTexture mappingRing (mathematics)String (computer science)
State of matterError messageWritingComputer fileString (computer science)Mathematical analysisReverse engineeringFluid staticsoutputFormal verificationResultantFunctional (mathematics)Computer animation
Transcript: English(auto-generated)
Um, thank you guys all for coming here. Uh, bright and early first talk of the day, track 3, rocking it. Um, this is our first speaker, Jonathan. Uh, he is going to be, uh, presenting an introduction to the Witchcraft compiler collection. Um, I hope you guys really enjoy it. And, uh, I'll let him take it away. Good morning DEFCON. It's a tremendous
pleasure to be here with you. We're gonna talk about, uh, some badass reverse engineering hopefully. Um, as you saw we got some technical problems but, uh, hopefully with a bit of imagination we managed to see everything. Uh, so my name is Jonathan
Brassard. I have a, a whole lot of, uh, content to share with you today. So I'm gonna start with the boring things a little bit and, uh, hopefully we'll switch very, very quickly to, uh, full demo stuff. Um, I cannot give, like, you know, the full demo
feedback, uh, I mean the full prerequisites and, and go through, um, why everything works. So I'm gonna stick to the demos and try to outline, like, why the, you know, the things which are a little bit, little bit touchy work. Uh, but I can assume that you already know about the ELF format. Uh, you're familiar with POSIX. And basically the
more, uh, reverse engineering you adopt previously, the more I think you'll be appreciate to, um, uh, you'll be able to appreciate this talk. Okay, let's get started.
So thank you very much, uh, for coming this morning. I know it's, uh, 10 AM. It's definitely starting, so you should, uh, all be exhausted by now. The real motivation of this talk is to, uh, share with you, um, a new toolkit to do reverse engineering which really facilitates a whole bunch of things that I thought were impossible before even
trying to do it. Um, so it's published under MIT license, I mean a dual MIT MBE license because I'm reusing components which were, um, already licensed this way. Uh, and I would very much like if you, um, contributed to this witchcraft compiler collection.
You don't have to be, you know, very familiar with C or assembly to do this. As a matter of fact, you can write all the code you need on top of this framework using Lua or web programming language that stems from Lua that we created specially for this tool which I call Punk C. Okay, so quickly, where am I? Uh, so to, to introduce me, uh, I
thought it would be good to tell you about my love relationship with DefCon. Uh, my first talk ever was at DefCon 8 years ago. It was on, um, um, bias vulnerabilities. Basically we found a new class of vulnerabilities on the bias which allowed us to, uh,
pop using a single exploit, truecrypt, bitlocker, McAfee endpoint, and a fair bit of, um, um, bias firmwares. Uh, then I've been rejected pretty consistently at DefCon until 4 years ago where I gave this talk on hardware back drawing. This is a, um, a talk I
really liked because I did it with the people who engineered, um, um, an open source bias called Coreboot. And the real pretext of this talk was to work with them. Uh, we basically, uh, they, they dropped the project and I pursued it a bit and, uh, yeah, it
ended up being pretty cool. The MIT, uh, technology review gave me, um, you know, give a review on it and said, like, that's a computer infection that can never be cured even if you reflash the hard drive, even if you change the hard drive or erase your bias and things like this. Incidentally, that's where my ex-teachers in engineering school
stopped talking to me. Uh, the thing also got, uh, featured in, you know, more mainstream press. Uh, it got featured in Forbes, which is interesting. Uh, they had pretty much the same feedback. I'd like you to pause for a second and imaging, like, you know, the kind of online presence this gives me. Imaging, uh, you know, I get, I get to meet a
girl on Tinder or whatever and she Googles me. She's like, oh, also I miss being on Forbes. Yeah, for writing malware, baby. So I'm telling you I've been, yeah, pretty consistently rejected. That's a message to you if you submit to conferences. Being rejected is part of it. It's normal. It's completely expected. Uh, so stuff that didn't make it
to, uh, DefCon but that I presented at Black Hat, uh, that was a, a, a pretty cool debugger I thought. Uh, it's called PMCMA. You can find the, the codebase online if you're interested. Basically, the normal way it works is, um, you have one debugger who's debugging a debuggee and you get a one shot. If you crash the
debuggee, like, you have to restart everything again. So instead of doing this, my debugger was attaching to the debuggee, forcing it to fork, to replicate itself in memory and then we'd work at, on one fork at a time. That's the routine you can see over there. Um, finally last year we did a presentation with, uh, my team from Salesforce. Um,
we pretty much redirected SMB relays and our contribution was to show that it doesn't work just on LANs. It actually works from the internet. Uh, I saw on the schedule, um, this year that there were more talks on SMB at Black Hat, so, uh, yeah, I hope we, uh,
resurrected something. If you run, uh, Windows networks, you want to, to watch this talk, uh, cause this is still unpatched and this is affecting every version of Windows. Okay, this, uh, slide is brought to you by the Security Vacation Club. What do you do once you've done all the work to, um, you know, create a badass
presentation and that you have massive content you'd like to share? Well, do it more than once. There's all this list of very cool conferences. Uh, so Akito Agosom in Paris. I'm a bit biased cause I created it. Akin the Box in Malaysia, which is really awesome. H2HC in Brazil, it's insanely good. Syscan in Asia, uh, things like Shacacon in
Hawaii, uh, I'm also part of the program committee of that one. Infiltrate in Miami, Rekon in Canada, only reverse engineering, very, very cool. Kiwicon in New Zealand, Eco Party in Buenos Aires, Zero Nights in Russia. So basically, if you do all the work to create one presentation, I suggest you, you know, enjoy your Security Vacation
Club tour and give it to all those conferences. There is one left I didn't put in the slides because it's a trap. It's called Roxcon in Australia. I was supposed to go there for one week to speak and I stayed four years. So it's a trap. Hahaha. Okay, a bit of disclaimer and then let's go, let's go to the meat. Uh, so my employer does not wish
to be named, even though I just did. Um, they're not associated with this talk and this is my personal research. On the upside, it means I'm free to, uh, share it with you. There's no intellectual property problem. But on the downside, it means you want to do reverse
engineering and you're on your own. What do you do in this case? You call EFF to the rescue. And before anything, I'm gonna ask you to give a big warm, uh, uh, you know, a big clap to the people of the EFF because they've been amazing. Thank you very much. I
know some of them are, uh, are talking today, so they're definitely around. Uh, if you manage to catch them, like, you know, pay them a beer because they're, they're really helping us when, uh, we're in situations like this where we cannot afford, like, you know, legal advising. And, um, if you do reverse engineering, they have a nice
fact, uh, that I suggest you check, um, the words on the slides. Okay, uh, so my employer doesn't want to be named but he's recruiting. It's a badass security team. Uh, if you saw the attacks on, like, breach and things like this, denonymizing SSL, uh, ravage, which
was, uh, a very cool tool to provide Java or the research we presented last year at, uh, Black Hat, uh, yeah, feel free to decrypt those slides. I think we cool, uh, the legal department and the PR department are very unlikely to decipher this slide. In terms of
agenda, I'm gonna talk to you quickly about why I started this project and why, you know, it's relevant, hopefully, and then we're gonna do, like, some really serious black magic, uh, with the witchcraft compiler collection. I show you, um, you know, what are the main tools in it. I show you how to transform the shared library, like, uh, sorry, I'm
gonna show you how to transform an executable into a shared library. Okay, that's not supposed to fly but that's super helpful when you do reverse engineering or exploit writing. Um, then we go further and we'll completely unlink, um, an ELF to a relocatable file. Um, and then we'll extend that and go a bit crazy. Okay, so
I don't get to see my slides, so it's a bit touchy for me too. Um, quickly, let's imagine we're working on an application and we don't necessarily have the source code. Honestly, even if you have it, it takes time, like, you know, to recompile things,
uh, possibly to adjust your toolchain, um, you know, you have missing dependencies and things like that. You often don't have the right headers and things. So working with source code isn't easy. I'd really like to work with binaries directly. As an example, um, I took a very old version of, uh, SMB. It's called SMB server 1532. It's
basically a predecessor of Sambal. So, um, if you do static analysis, that's a pet project I run on the side, uh, with another company I work with full time. So I have two full time jobs, right? The one with the company who doesn't want to be named. One with a startup in France. And I have so much free time that, you know, it allows me to,
uh, do more research and share it with you. So basically that's a thing we run with our startup in France. Uh, you can, you can register for free. It's only for security researchers for the time being. It does full featured static analysis. So you upload your binary and you get back a bunch of metrics. Um, on this slide, like, the
more red you get, the better it is. You can see that it's checking, you know, five different aggregated metrics. Without going into the details, the bit we're gonna cover today is like, okay, you can see that the binary for instance is compiled without ASLR, uh, without Fortify, uh, hardening and things like this. But what
we're really gonna look at is like finding proper vulnerabilities from this binary without using source code. One which looks pretty cool is, um, uh, the one with fopen right here, which is opening, um, I mean, it seems like it's opening, um, a
predictable name in write mode in slash TMP. Uh, since this thing is running as root, there might be, you know, um, possibility for a sibling attack and basically a local privilege escalation. The thing which is interesting here is that we don't have a full backtrace. So the way the tool works internally is like, it does like, you
know, the compilation, I mean, disassembly, the compilation, full static analysis on the binary, um, uh, by using, uh, symbolic execution, we wrote the engine ourselves, so it does it straight on binary. And a problem you commonly face when you use advanced techniques like this is that you don't have a full stack trace. So I have only a partial stack trace here and I'd like to verify these vulnerabilities does exist.
Okay. Another way to do this is, uh, to hit this problem is when you do fuzzing, like often, like in this case, this is taken from the, um, the bugzilla of, uh, Red Hat. It's also SMB which is, which seems to be crashing. And we have only a partial stack trace. And this thing is actually bizarre, right? Because it, it's not called
from main. So we don't really know what's happening. What I know is that I don't want to call the whole thing from remote by sending packets. I'd like to verify the vulnerability exists by calling directly an arbitrary function inside the binary or inside a shared library. So that's our problem statement today. I want to be able to call any
function inside any binary without even to craft an input to reach it. And without necessarily going through main and whatever layer of function and then reach it. I want to be able to call those functions directly. Okay. So here are the components of the
witchcraft compiler. Um, it has a, um, a linker, uh, which is a, a badass tool which patches 1 bytes in binaries but its power is incredible. You're gonna see this. We got the, uh, WCC which is the core compiler which is the tool which takes a binary as an input and gives you relocatable files that you can later on relink to generate new shared
libraries or, or relink against your own code and like get new executables. And finally we have, uh, the witchcraft shell which is by far the most complex. It's a, a full dynamic interpreter and scripting engine. Uh, built on top of Lua. And, uh, yeah, we're
gonna see that this is pretty cool. Um, with this shell you can write your own scripts. So an example of scripts we're gonna see today are WCCH and WLDD. Let's go to the meat. Libifications. So if you did one class of computer science and C programming, the
first thing people tell you is that what we're gonna do today is impossible. Let's start with the demo. I don't see anything. Yeah, yeah, I know you're not seeing this.
Okay. Here we go. Okay, so for instance, um, to give you an idea of where, where is the
state of the art of decompilation and why we're not gonna take this route. So this is a elo.c file. Okay. And I'm gonna show you the equivalent code generated by, uh, possibly
the best decompiler you can get for free. It's called Snowman. It works in two modes, either on top of IDAR or it has a mode where it can run by itself, uh, autonomously which is free. So to give you an idea, like, when you, when you decompile these two lines of code program with, uh, Snowman, you get something like
this. Okay, so that's the source code which is supposedly equivalent. So if you take that path to decompile a real binary, let's take proftpd for instance. It's 200,000 lines of code. Okay, you're gonna get about 200,000 times this. So decompiling this
and recompiling this is not reasonable. Uh, if we, if we give it a try, just for fun, let's try to recompile the one from Snowman. I'm just gonna, uh, grab the errors. Maybe. I don't see shit. Okay, let's, let's drop this. I think you got the idea.
Okay, so what's libification? Uh, basically we're gonna take an elo file. This is the main leader, uh, the elo feeder. We're gonna patch one byte. We're gonna tell it you're not a, you're not a binary, you're not an executable binary anymore. Uh, you're
not a shared library. So patch it from et exec to et din. So let's do it with proftpd for instance. Let me get this full size. Can you get, see any of this? That flies? Yeah?
Okay, so, uh, as an example, let's take proftpd and let's assume we don't have the source code. Let's copy to slash tmp. If we check the type of the file, um, okay, it's obviously an elf executable, as seen right here. I'm gonna use, uh, wld. So the first tool
from the witchcraft compiler collection. It takes only one option, which is libify and then the name of the binary. So I'm gonna run this. And let, let's now check the type
of this file. Okay, and surprisingly it's a shared object. Okay, but what's crazy now is that it really is a non relocatable shared library that can, that I can relink against my own applications. So let's check what to do with this. Okay, so that's a simple program
which is gonna load, uh, slash tmp proftpd dot so into memory. So let's start with renaming, uh, proftpd we just patched into proftpd dot so. It's gonna de-open it, so
it allows you to call dmsim and find the address in memory of any of the symbols in there. What I'd really like to call is this function called pr underscore version underscore get underscore string, which returns inside proftpd the version of proftpd. So what's very
crazy, let me show you the, the makefile quickly. There's nothing very crazy. Okay, we're just using a linker script to avoid gcc giving by default the same address to this
program and to proftpd dot so so they do not collide in memory. So what I do is basically my demo is mapped much lower, much higher in memory to make space for this, uh, non relocatable shared library. And what's very crazy is that this thing actually works. Okay, so if
you look up there, it, it really returns like 1 dot 3 dot 3d which is incidentally the version from proftpd which we got from the shared library. Isn't this insane? Okay. Um,
so that's exactly what we just did. You can see that we really just patched 1, 1 byte in memory. So without going into, you know, the crazy details, uh, there's a couple reasons why this works. The first reason is that, um, oh, and I need to show you something
else, which is very crazy, is that the, the library we just patched is still a valid executable. That, that is completely unexpected, right? So the reason this works, the reason it's still a valid executable is that basically the way we, we, uh, pushed
FOL and SLR in the Linux kernel is by allowing you to compile your binaries as a shared library and execute at any, execute them at any address in memory. Um, and, and, um, so yeah, you can have, you can have a binary with technically a shared library. We're gonna see that a bit more on this later. Um, the other thing which is a bit crazy is that this
newly re-crafted like shared library cannot be remapped in memory, right? Because it was never meant to be relocated that way. So we have a shared library but that can only be mapped at a single address in memory. Um, this actually does exist in the normal world. Uh, it's called pre-linking. It's the fact of giving a base address to speed up
booting essentially, um, to shared libraries. And, uh, yeah, so that's exactly what's happening in here. Okay, let's do a demo with Apache. I'm gonna show you that, um, you can actually relink against Apache, which is not a shared library, but pretend it's a
shared library. Okay, so, uh, let's look quickly at, uh, the source code. Okay, so it does nothing crazy. It tries to call AP get server banner, which is a function which is
defined inside Apache. And to do this, we're gonna link straight away against Apache as if it was a shared library. So let's type make quickly. Okay, it's complaining. Boom. And if now I run this application, it's very crazy but that also works. So Apache is not
really a shared library, right? It's an executable, but it's compiled as ETDN to have, like, full, uh, ASLR. And, uh, if you link directly against it, you can actually call functions directly inside it. This is so amazing that I'm tempted to end my talk here.
Okay, if you look at, like, the way, um, you know, if, if, if you try to print, like, which shared libraries, uh, this recursively this application is linked with, you see that the first one is very much Apache and that looks very crazy but it works. Okay,
let's go one step further. Uh, so this, uh, this technique we just used is by far my favorite because it's cross platform, it works across architecture, and it's super stable. There's no such thing as, like, complicated analysis that might fail and stuff
like that. Like, all we did was patching one byte, which, you know, incidentally is pretty reliable. If you wanted to go one step further, and instead of transforming an executable into a shared library, go back to the, uh, output of a compiler before the, the, the application is linked. So we call this, uh, unlinking. Um, well, we're gonna use
this tool called WCC, which is a lot more complex and less portable and, you know, basically what it tries to do is recreate the relocations, um, uh, that were missing from the final executable and add them to the, the, the binary so that you can relink it. So the
normal way to, um, to do reverse engineering and to solve this problem would have been this. Um, when you have, uh, compiled source code, you would use a decompiler, which is totally not what we're gonna do. We're just gonna go to, back to the relocatable files and once I have the relocatable files, I'll be able to relink them
again. So the common line is made so that there is zero learning curve. If you know to use GCC, it takes essentially the same parameters as GCC, only it doesn't take source code as an input, it takes a binary. Okay, uh, I'm gonna give you a demo on this. So I have a, a
small file here, which is a small C file, and it has a whole bunch of relocations. And okay, it has a number of imports, um, it has strings, which are in the read only data section, it has strings, which are, you know, passed as arguments, um, so yeah, it has,
it has pretty much all the type of relocations that do exist. I'll, I'll, you know, I'll share, I'll share the source code so you guys, um, can verify this. But essentially what we're gonna do is first compile it, then, uh, so the, the normal compilation will give us a binary called small. Then we'll use the witchcraft compi, uh, compiler to go
back to a relocatable file from this final binary, and we'll link it as another binary using GCC called small 2. And the question is like, does small 2 actually run? Because that would be very crazy. So let's compile it quickly. So if I run small, which is the
original binary, it tells me something like hello from Defcon. You can see that WCC, so let's redo this manually actually. Let me re, re, re delete this and this. Okay, so I start, I have only this small binary. I'm gonna use WCC, the tool I just told you
about. If I, if I played stupid and I, I assume, I want, uh, you know, if I wanted to use GCC, so I would like to do something like this essentially. Uh, until it give me a, um, you know, small WCC dot O and I'd like it to be a relocatable file. If you run
this, like GCC is gonna be like, I don't understand what you're trying to do. The input is not a source, is not a, a, a source code. But if you do it with WCC, it's gonna be like, yeah, okay, let's do this. And it gives you this relocatable file that then you can absolutely relink into small 2. And what's amazing is that,
small 2 does the same thing as the original binary. This sounds very crazy, doesn't it? So if you like it, uh, I'd really like you to contribute back to this tool and extend
it. For the time being, it works mostly, uh, on, uh, AMD64. I'm trying to port it on ARM. And the drawback as opposed to the first tool which, you know, worked everywhere because we were just patching one binary. Here it's a, it's a bit of work because we have to deal with all the type of relocations for all the type of CPUs. So I need
your help with this. Okay, uh, I'd like to explain you one thing. Um, I choose, so to architecture this, uh, the front end is basically libbfd. So it's like objdump and tools like this or objcopy. Uh, which has a nice, I mean, the drawback is that it's not very
precise. Uh, but the advantage is that it works with many type of binaries, not just ELF files. So technically at this stage, we can try to do very crazy things, like, let's do witchcraft baby. Let's try to transform a PE file into an ELF file. I'm running late so, uh,
I'll let you play with this at home, but that basically works. We have one problem here, it's like, I don't know what you, what you relink this with, right? Um, so an idea would be to use, like, the libraries, um, shipped with wine, which already give us, uh, you know, the Windows API compiled as an ELF file. This is left as an exercise to the
reader. We're gonna do something way more crazy right now. Can you run open BSD binaries, like, natively on Linux? I mean, if you've been through, you know, if you've done a bit of engineering, like, that's not supposed to be possible. Like,
technically, you're supposed to have a virtual machine. Let's do it without a virtual machine. Proper witchcraft. Okay, so we could do this, uh, manually. I'm, I'm gonna do it
with a makefile. So the original binary, so here the, the original binary we're gonna
play with. Uh, you can see that it's very much an open BSD binary. Okay? The source code is trivial. It's basically this. So it's, it's doing a bunch of printf in a row. Okay? Here comes the main file. Fuck the display today. Okay. So we're gonna copy the
binary, blah, blah, blah. Okay, basically, there's a couple problems. The, the dynamic linker is expecting to find, does not exist. So, to show you manually, if I
do, like, uh, S trace on this particular binary. That was not supposed to work, actually. Oh, cause I already patched it. Okay. Um, okay, let's just run it. I'll
explain to you how it works later. So basically, the dynamic linker is not the right one. This is outcoded inside the binary, inside the interpreter section. I could patch the binary to put my own dynamic linker. Instead, what I'm gonna do is copy my
real dynamic linker to the location it's expecting. The dynamic linker to be encountered. Okay. Right. Uh, so then it has a little bit of a problem. It's looking for
libc, which is called libc dot so dot 62 dot something. And my libc is not called like this. So I could patch the binary there again to tell him, like, no, look at, like, the libc I've got. But instead of this, I could also copy the libc, my own libc to the
libc is expecting. And if you do all that, I share all the, the, the material so you can reproduce yourself. But essentially, amazing. Okay, if you, uh, there's an, a last problem, it's like, it has a missing dependency on, um, right, if I try to run it
now, uh, it has a missing dependency on at exit. So what we're gonna do is use, uh, you know, a shared library with all the dependencies is missing, like at exit. We don't really care, right? At exit is a function which is called basically when you exit, um, uh,
to called, um, you know, deconstructured and things like this. So I don't really care. Long story short, if you look at the last line, you do the LD preload, you run this open BSD binary which has been slightly adapted inside, um, um, a Linux machine and it does print what it was supposed to print, which is also very crazy because there's no
virtual machine and this was never supposed to work. Okay, now let's go to proper witchcraft, uh, and I'm gonna introduce you to a programming language that comes from basically, um, allowing, I mean, uh, implementing a sort of reflection in C inside a
Lua interpreter. So what I'd like to do is basically to get, um, reflection like features but on binaries. Reflection is typically something which only exists on a virtual machine, right? It allows you to load, um, classes of binaries in memory and instrument
them, like get a, get a bunch of information on them, like what are, you know, um, what type of argument they're expecting and things like this, and then to invoke them directly in memory. So I'd like to do that but without a virtual machine straight from
binary. Um, so it's based on dlopen, uh, which is a function we used earlier, uh, to link with proftpd. You can, you can, uh, compile it with luagit which gives you, uh, just in time compilation in memory. There's no ptrace and it typically doesn't work like any,
um, you know, debugger you might have used before. I don't see the slides so I'm gonna, I'm gonna go quickly on this, uh, and we're gonna stick to the demos. 10 minutes. Okay. So it's time to activate. Okay. Since I don't see the slides, I'm, I'm just
gonna run it for you. Um, okay. Okay. The SMB server I, I showed you earlier with the
static analysis thing. So let's, let's talk, let's copy the SMB. Fuck that shit. Okay, nothing works. So I'm gonna load like the proftpd binary we've, uh, patched before and I'm gonna, um, you know, showcase you the capabilities of wsh. So we just loaded it in
memory. Um, it has a bunch of built in functions. When you don't know one of the functions, you can use, um, you know, the app which is, uh, the only documentation you'll get in this respect. Okay, so, um, let's call this function for instance.
Hey everybody. Is Jonathan doing a good job? Thank you folks. Okay, I really want to show you this cause it's, it's, it's, it's beautiful. So we can do crazy things like, uh,
print the section headers that the output you would get from, uh, nm typically only this is dynamic and this is recursive over all the shared libraries inside your memory. This is a feature I always wanted cause it's not built into gdb and it's always a problem when you're trying to do this. Uh, you can have the program headers, you can look at like
what are all the functions which are loaded right now in memory. Uh, let me show you this first. You can, you can ask him to print what are all the, the libraries that you have loaded in memory. I just loaded preftp but that also loaded all its dependencies. So if we
look at like all the functions that this has actually loaded in memory, there's a fair bit of them in a bunch of, you know, libraries and we can now invoke them straight away. So already we got like 6000 functions to play with in memory. I don't even know the prototype. I know nothing about them. So let's look for instance if there is a
function, uh, which print the version or something like this inside preftp. Ok, so, uh, like before we find this version called pr underscore version underscore get underscore
number. I'm gonna print this inside, um, a variable. And if I print the variable like before, uh, that's not what I expected. Uh, cause that's not the right one. Let's try with the string one. Yeah, so like before, that's printing me internally the
version number. No, no, no, no. You've seen nothing. The real good thing, the real good thing is, um, uh, so the real bad thing and why I took lua, I'm gonna try to activate, is
that you can have more than one return value. So I'm gonna, I'm gonna tell him, ok, I want A, the result of this function, but also give me a context. And now if I looked at the context, it tells me a whole bunch of things is done, um, I mean, of the context of this
execution. So that there's L number, you know, was 0, there's no segfault and stuff like that. I had not planned to do this, but let's do something crazy. Um, I mean, this allows you basically to build static analysis, uh, on top of, uh, wsh very simply. I won't have
the time to explain everything today. Uh, let's just say we wanna test all the functions inside proftpd. I'd like you to fold them and call them a hundred times each. So it's gonna list all the functions in memory and what it's doing right now is like calling them, ok? Ok, let's stop this for a sec. Dear god, I've been too ambitious. Ok, a
hundred times is too much. Let's run it like once. And what happens is that it's recording
all this stuff in memory and you can see them, uh, right after. Ok, I don't have the time to see you all this, I don't wanna sabotage this talk, but, uh, that's too bad. We're leaking time. Invite me to your local conference. Uh, yeah, I won't talk about this, I won't talk about this. Future work. What I'd like you to help me with? Yeah, I know,
we were super late. Uh, so I think this is a very cool base to do reverse engineering. There's a whole bunch of stuff I don't have the time to do. So, uh, if you would like to participate, uh, get in touch. Do you have any questions? Or do you want me to stick to demos? Oh, there is one thing I need to show you because it's amazing.
Uh, what if I wanted to analyze an ARM binary on my Linux machine? So, typically, to do this, uh, there again, you would need like, uh, uh, you know, a full hypervisor and things like this. What I did is just, uh, cross-compiled my WSH shell to WSH ARM. Ok?
I've registered QEMU in a weird mode, um, to do me, when I execute natively, an ARM binary on my machine. Um, in-memory binary translation. So this is really an ARM binary. I'm running on my own machine right now. And what we're gonna do with this is load this
libse Linux thing which comes from ARM. So it's complaining because some dependencies are missing. Typically, you would do this inside a CH root to have all the dependencies. But you can see that like before, we have a bunch of functions and we
can call them directly. Now let me show you something which is really insane. Uh, for instance, ok, let's print, let me get my PID. So that's my PID. And it didn't work. That's amazing. Ok, uh, let's get it another way. I cannot get a shell. That's
beautiful. Ok, uh, I can have it another way. Um, let's just look at like the libraries mapped inside memory. So my process is really an ARM process. It's loading an ARM
binary and it's running natively on Linux. The binary translation is also inside the same process, thanks to QEMU and the weird mode it's using. And it's all, all of this is just one program in memory. You don't need a virtual machine, you don't need all that garbage. And that facilitates a lot like, you know, the fact of sharing this tool or, or
having like a ARM binary and calling functions inside it, uh, from other application without any reverse engineering. Last but not least, I'm almost done. I told you SMB
server, I wanted to write an exploit for it. So let's do that quickly. We saw before that, uh, we wanted basically to call this particular function called reply close inside SMB server. So we have the binary here, ok. So let's do WSH of SMB server. If I want to
call reply close directly, I can. These six faults, by the way, this is amazing. Um, we get to know that it writes, but we didn't decompile. We didn't ptrace. We get that basically by writing a custom signal end law and passing better like, you know, the
output we can get out of it. Let's give it a couple arguments and let's see why it's crashing. Ok. So right here it's crashing because basically the second argument, as you can see, is trying to write. So let's map something here. Ok, in Lua strings are
supposed to be immutable, but in PUBG C, which is, you know, what's happening in this script, you can break all the Lua rules. In particular, yeah, you can absolutely write two, two strings. So I'm gonna try to this string. It did reply close, ok, and if you remember like the static analysis we saw, uh, this is supposedly creating a file in
slash GMP with a predictable name which is G something. And you can see here that, yeah, this file was actually created. And what's amazing here is that we can verify results of static analysis without any reverse engineering basically and we can call any
function we like in the stack trace even if we have, we don't have the full stack trace and even if we don't know an input to take it there. With this my friends, I think I'm done. Thank you very much for your attention today.