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

Next Generation Process Emulation with Binee

00:00

Formal Metadata

Title
Next Generation Process Emulation with Binee
Title of Series
Number of Parts
335
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
The capability to emulate x86 and other architectures has been around for some time. Malware analysts have several tools readily available in the public domain. However, most of the tools stop short of full emulation, halting or doing strange things when emulating library functions or system calls not implemented in the emulator. In this talk we introduce a new tool into the public domain, Binee, a Windows Process emulator. Binee creates a nearly identical Windows process memory model inside the emulator, including all dynamically loaded libraries and other Windows process structures. Binee mimics much of the OS kernel and outputs a detailed description of all function calls with human readable parameters through the duration of the process. We've designed Binee with two primary use cases in mind; data extraction at scale with a cost and speed similar to common static analysis tools, and second, for malware analysts that need a custom operating system and framework without the overhead of spinning up various configurations of virtual machines. Currently Binee can run on Windows, OS X, and Linux. Kyle Gwinnup Kyle is a Senior Threat Researcher in Carbon Black's TAU team. He has over 10 years of experience in many areas of computer science and IT. Prior to Carbon Black, Kyle worked in finance and with the DoD in various roles ranging from network/systems administrator, software engineer, reverse engineer, penetration tester and offensive tool developer. At Carbon Black, Kyle's focus is on large scale program analysis, primarily static but moving asymptotically toward dynamic analysis. John Holowczak John is a Threat Researcher on Carbon Black's Threat Analysis Unit, focusing on automation of threat detection and building out infrastructure for large scale malware analysis. Within the field of threat detection and analysis, John specializes his research in binary classification, dynamic analysis and reverse engineering.
Sample (statistics)InformationTotal S.A.Mathematical analysisEquals signBinary fileScale (map)Reduction of orderAerodynamicsInformation extractionDomain nameThermodynamischer ProzessType theoryScaling (geometry)Different (Kate Ryan album)EmulatorFluid staticsFunktionalanalysisMalwareComputer configurationSet (mathematics)Roundness (object)Sampling (statistics)Dynamical systemFinitismusBinary codeMathematical analysisInformationComputer-assisted translationInfinityService (economics)Virtual machineKeyboard shortcutWindowNumberInstallation artSound effectParity (mathematics)Key (cryptography)Total S.A.Internet service providerSymbolic dynamicsExtension (kinesiology)Infinite setGraph (mathematics)AdditionComputer animation
EmulatorFunction (mathematics)Physical systemExistenceType theoryMechanism designSoftware frameworkIntegrated development environmentConfiguration spaceKeyboard shortcutKey (cryptography)Windows RegistryElectric currentData structureThermodynamischer ProzessMemory managementFormal languageInstallable File SystemParsingHookingAddress spaceBuildingTable (information)Read-only memoryOpen setAbstractionRevision controlCore dumpComputer fileStructural loadFunktionalanalysisParameter (computer programming)CodeMedical imagingThread (computing)Process (computing)Software frameworkExecution unitMathematical analysisReal numberSpacetimeMalwareConfiguration spaceEmulatorKeyboard shortcutSynchronizationIntegrated development environmentImplementationLevel (video gaming)Table (information)Address spaceVirtual machineWindowSemiconductor memoryStructured programmingMereologyContext awarenessBitMikroarchitekturSystem callCASE <Informatik>Touch typingUnit testingSampling (statistics)Binary codeHookingParsingComputer-assisted translationDifferent (Kate Ryan album)Software engineeringInfinityService PackDemo (music)Enumerated typeLibrary (computing)Revision controlWindows RegistryCore dumpFunction (mathematics)Mechanism designWebsiteDynamical systemComputer configurationProjective planePoint (geometry)Physical systemService (economics)CausalityMultiplication signSet (mathematics)Formal grammarMiniDiscSingle-precision floating-point formatMathematicsSlide ruleMeeting/Interview
Maxima and minimaMalwareMalwareAddress spaceValidity (statistics)FunktionalanalysisAnalytic continuationUnit testingWindowIdentifiabilityPhysical systemCASE <Informatik>
HookingString (computer science)Parameter (computer programming)ImplementationType theoryHookingString (computer science)CASE <Informatik>System callVariable (mathematics)Semiconductor memoryAddress spaceSoftware frameworkFile formatFunktionalanalysisSlide ruleMappingParameter (computer programming)Default (computer science)Electronic visual displayComputer configuration
Parameter (computer programming)Type theoryHookingString (computer science)Function (mathematics)EmulatorDisk read-and-write headDifferent (Kate Ryan album)HookingPoint (geometry)Parameter (computer programming)FunktionalanalysisPartial derivativeString (computer science)Electronic mailing listFunction (mathematics)Intercept theoremPointer (computer programming)CASE <Informatik>Message passingContext awarenessType theorySystem callInformationImplementationStack (abstract data type)CountingMetadataAddress spaceKernel (computing)Group actionMalwareNormal (geometry)File formatTouchscreenStandard deviationMereologyComputer fileField (computer science)Asynchronous Transfer ModeBefehlsprozessorPerfect groupReal-time operating systemDemo (music)Line (geometry)Form (programming)Branch (computer science)Right angle2 (number)Price indexSlide ruleComputer animationMeeting/Interview
BootingRead-only memoryFunction (mathematics)Object (grammar)Kernel (computing)Physical systemApproximationPointer (computer programming)MalwareEmulatorStack (abstract data type)Limit (category theory)Image resolutionAddress spaceSampling (statistics)Extension (kinesiology)WindowEmulatorThermodynamischer ProzessThread (computing)Physical systemField (computer science)Integrated development environmentPoint (geometry)Structured programmingInformationComputer programmingImplementationMultiplication signData structureCodeMalwareBootingState of matterHookingSystem callCASE <Informatik>Parity (mathematics)Kernel (computing)Context awarenessRevision controlBlock (periodic table)Asynchronous Transfer ModeTouchscreenObject (grammar)CausalityStructural loadLevel (video gaming)Ocean currentMeeting/Interview
Integrated development environmentThread (computing)InformationType theoryAbstractionString (computer science)Maxima and minimaInformationSampling (statistics)Pointer (computer programming)WaveBuildingLevel (video gaming)NumberComputer programmingWindowQuicksortBlock (periodic table)Semiconductor memoryThermodynamischer ProzessComputer fileMalwareType theoryWindows RegistryThread (computing)
Memory managementEmulatorWindows RegistryLemma (mathematics)Core dumpHill differential equationInstallable File SystemBeer steinMemory managementSuite (music)Normal (geometry)Touch typingEmulatorComputer fileFunktionalanalysisThermodynamischer ProzessImplementationData managementBitDirectory serviceCASE <Informatik>WindowData structureLibrary (computing)Semiconductor memoryAbstractionMalwareHookingFile systemSystem callSpacetimeWindows RegistryPhysical systemPartial derivativePoint (geometry)Proper mapFlow separationIntrusion detection systemRootSoftware developerProjective planeComputer animation
Memory managementWritingTable (information)Parameter (computer programming)System programmingEmulatorMalwareKernel (computing)HookingSampling (statistics)Group actionFile systemAddress spaceEmulatorComputer fileSystem callParameter (computer programming)CausalityMemory managementTable (information)SpacetimeJSON
HookingSystem programmingComputer fileEmulatorMathematical analysisPhysical systemParameter (computer programming)MalwareTable (information)Sampling (statistics)CausalityType theoryFile systemBinary fileRight angleDifferent (Kate Ryan album)Computer fileWritingMalwareWindows RegistryProtein foldingPhysical systemBitMechanism designUniform resource locatorJSONProgram flowchart
Computer fileData analysisIntercept theoremDifferent (Kate Ryan album)MereologyNumberMalwareComputer configurationComputer fileValidity (statistics)HookingLine (geometry)WritingFunction (mathematics)Parameter (computer programming)Asynchronous Transfer ModeSystem callForm (programming)Video game consoleSource codeJSON
Video game consoleComputer virusContent (media)EmulatorParameter (computer programming)Function (mathematics)SpacetimeWindows RegistryData conversionType theoryRead-only memoryHookingHookingWindows RegistryFiber bundleComputer fileWindowMalwareThermodynamischer ProzessComputer configurationDemo (music)System callKey (cryptography)Kernel (computing)Sampling (statistics)Validity (statistics)Real-time operating systemDrop (liquid)Configuration spaceReal numberMiniDiscDirectory serviceFile systemAsynchronous Transfer Mode
Integrated development environmentContext awarenessRead-only memorySoftwareControl flowComputer fontRange (statistics)Address spaceRevision controlVirtual machineRootkitWindows RegistryConfiguration spaceWindows RegistryIdentifiabilityNetwork topologyComputer fileAbstractionIntrusion detection systemThermodynamischer ProzessEmulatorConfiguration spaceSampling (statistics)Type theoryRootWeb pageParsingCodeHookingSource codeJSON
Software testingIntegrated development environmentComputer configurationThread (computing)Equals signContext awarenessMultiplicationScheduling (computing)EmulatorWindows RegistrySampling (statistics)Row (database)Machine learningQuery languageMalwareThread (computing)Computer fileData managementMultiplication signRoundness (object)QuicksortInterpreter (computing)WaveEmulatorResultantPoint (geometry)Error messageInformationCASE <Informatik>Configuration spaceSingle-precision floating-point formatScheduling (computing)Natural numberSource codeJSON
Parameter (computer programming)File formatStandard deviationNumberPoint (geometry)Multiplication signThread (computing)Letterpress printingGroup actionContext awarenessFile formatSystem callFunction (mathematics)Line (geometry)FunktionalanalysisString (computer science)Intrusion detection systemPoisson-KlammerCausalityMathematicsSource codeJSON
Instance (computer science)System callWordEmulatorStack (abstract data type)Chord (peer-to-peer)MalwareEntire functionThermodynamischer ProzessSpacetimeChainAddress spaceKeyboard shortcutEmulatorPhysical systemAddress spaceInterrupt <Informatik>BitStructural loadSampling (statistics)Parameter (computer programming)Kernel (computing)Level (video gaming)Point (geometry)Different (Kate Ryan album)Multiplication signCASE <Informatik>Library (computing)Stack (abstract data type)State of matterParsingHookingMalwareImplementationAnalytic continuationMiniDiscSemiconductor memoryLine (geometry)Pointer (computer programming)Demo (music)BootingSoftware testingField (computer science)ChainResultant
12 (number)Demo (music)MalwareScaling (geometry)Real numberComputer fileConfiguration spaceBranch (computer science)1 (number)Sampling (statistics)QuicksortFamilyMathematicsInformationFunktionalanalysisMereologyIntegrated development environmentCASE <Informatik>HookingBuildingService (economics)Real-time operating systemParameter (computer programming)SubsetSet (mathematics)Asynchronous Transfer ModeFlagException handlingCore dumpWritingString (computer science)Server (computing)Video game consolePoint (geometry)Figurate numberCartesian coordinate systemMoment (mathematics)CausalityMathematical analysisCloud computingAddress spacePartial derivativeMultiplicationKey (cryptography)Fluid staticsComputer wormRegular expressionRight angleTable (information)Windows RegistrySystem callVirtual machineBitComputer animationLecture/ConferenceSource codeJSON
MereologySampling (statistics)Semiconductor memoryReceiver operating characteristicStructural loadUniform resource locatorAddress spaceLibrary (computing)Computer fileWindows RegistryBitBinary codeMiniDiscNumbering scheme1 (number)Open setSource code
Data storage deviceComputer networkMiniDiscMIDIDebuggerAsynchronous Transfer ModeSingle-precision floating-point formatImplementationMach's principleEmulatorComputer animation
Transcript: English(auto-generated)
Alright, so, Kyle and John are going to talk about process emulation, uh, they're all the way in from Boston, so, uh, this is, uh, this is heat for them, uh, luckily they haven't melted. Let's give these gentlemen a big round of applause. Have a good time boys. Alright, thank you. Alright, thanks everyone for coming. Um, so like you said, uh, this is
about process emulation, um, in particular automating that, uh, process emulation at scale. Uh, so before we get started, uh, what I want to talk about is kind of like how we think about analyzing, uh, all the, all the malware and all the binaries that we get. Um, and in particular we have a fairly large ingestion pipeline and we need to be able to process all these samples, uh, quickly and efficiently. Um, so when we think about a
sample, uh, what we think about is like every sample has some, you know, finite amount of, of total, uh, features or, or data that can extract out of it. Uh, and all of those, uh, pieces of information cost a little bit different or they have a different cost, um, with each one. So, when we talk about the cost, the reason that the cost is, is there is because, um, as you can see in the graph, we have static, the two, the
two domains of, uh, extracting the information is, you know, static and dynamic. So, static is obviously the cheapest and the fastest and, you know, the primary reason is because you can just do that at scale very easily, throw it in Docker or your function as a service or whatever cloud provider, uh, and you can just extract those features really quickly. Um, dynamic of course is, is kind of the opposite of that. It
runs, you know, it's very slow, you have to spin up lots of machines, you have to configure them in particular ways, um, and it just, it, it increases our cost for getting information. So, as we collect more samples and as like, particularly when malware comes in, uh, there's some problems with that, right? So, when doing this research, we, we really have, we have three problems that we wanted to solve, uh, particularly with
regard to malware. Uh, and the first one is obfuscation, uh, in packers and encryptors and, and to a lesser extent, different types of installers. And what these have the effect, the effect to do is they actually limit the amount of information we're able to extract from static analysis. So, they reduce that total set. Uh, and then what it forces us to do is push those samples, because we're not getting all the information we want from them, we're forced to push those into the
dynamic analysis domain. Um, but the dynamic analysis domain, you know, it's more expensive, it increases our cost, which is not something that we like. Um, but the dynamic analysis domain also has some problems, right? So, there's, you know, anti-analysis techniques, like no malware likes to be, like, run in a debugger or like on a different type of hypervisors, um, but effectively there's this infinite set of,
like, cat and mouse, uh, kind of things that you need to add to the, to the machine to trick the malware into thinking, to, to run. Um, in addition, uh, not all malware is, like, equal opportunity. It doesn't run on every machine equally, some malware is targeted, so it won't run the same way on a, on a Windows machine in English as it would, uh, you know, a French machine or some other, you know, keyboard or, or any number of
features in there. So, you know, when, with those three problems in mind, you know, our goal is to, basically, we have three goals in mind. Uh, first is we want to reduce the cost. We want to bring, um, the, the static analysis features that we lost due to obfuscation. We want to remove those from the, uh, the dynamic domain and bring those back into the static analysis domain. So, that's kind of the key one. So, we
want to come, bring back parity of static analysis, um, or at least the cost associated with that. And then the second thing we want to do, and this is, you know, we would hope to bring as much as we can, but what we really want to do is we want to take some of the features that you would find inside of a dynamic, dynamic analysis domain and emulate those or bring those back into, uh, or bring those into the
static analysis domain, increasing, like, the total set that we could actually extract via static analysis, or at least more than traditionally, uh, you would accept. Uh, and then the last thing, of course, we want to do all this at scale. So, the static analysis kind of implies the scale, but we want to make sure that we can run all these things either inside of Docker or inside of a, you know, function as a service. Uh, so with that, we came, explored several options and what we
decided on was emulation, uh, and if anyone's not aware, there's a really amazing, uh, emulator out there right now called Unicorn Engine, uh, and this basically is a CPU architecture emulation, but they also emulate memory, uh, and this is key. So, what we want to do is we want to load up malware and we want to replicate the Windows process memory inside of the emulator, uh, is with as high fidelity as we can. And
what this allows us to do with emulation in particular is we get full introspection into every single instruction on the system, uh, we get full introspection into system calls so we can hook everything. Um, and then what that also allows us to do is because we can hook everything and we can see everything, uh, we can also mock out more of the system. And this was key and this is where we feel like we're adding a lot of value
is we took, uh, kind of an idea from unit testing with software engineering where you're mocking out functions and services and we thought, well, why can't we just mock out, you know, large chunks of the OS to allow the malware to execute, you know, further than we, we would normally expect. Um, so with that, uh, there were other, uh, you know, PE emulators that were out there, uh, the 3 at the top were I found on the
Unicorn website and these are pretty nice, right? They, this is where we got some inspiration and what they do is they'll actually take the PE file, they'll load up a bunch of DLLs and they'll actually throw it into the emulator space and execute them. And they do it pretty well and they'll output, you know, you get the parameters for the function, you get the, you know, where they're called, what the
function name is and the return values. And they work, they work quite well, um, and we want to see, alright, using this as inspiration, how can we take this like the next step further? Um, so with that kind of in mind, we had some requirements for when we decided to, what we wanted to build, right? So, uh, there is one extra requirement is we wanted the, the code to be simple, so we wanted to build this framework for
executing, so we wanted the actual code to be very simple, um, and when we originally POC'd this, we did it in C and then we, you know, to make it even more accessible, we, we switched it to Golang. Um, so that's just as a side note, but then the 4 core requirements to BINI were, uh, 1 we wanted to kind of formalize that mechanism for loading a PE file and all of its DLLs, so we like sync all them up, get the
imports working and so when, when a call is made, it actually jumps to the real DLL within, uh, or the real function within the DLL that it was called. So once we have that, uh, then we can, then we can really build a good hooking framework. And this is, the hooking framework is really the, is the core part of, of BINI and it enables everything else and we wanted this to also be as simple as possible, so when you
wanted to find a hook, you just basically fill in a structure that defines the name of the hook, the parameters and, and then the implementation. And then the third thing, because of that, uh, we want to, you know, extend the current research a little bit and then add, you know, mocking out some of the, some of the OS, so a lot of malware, you know, touches the file system, touches the registry, has threads, things like
that, you know, what if we can actually mock that inside of the emulator and then make the malware think that it is actually running inside of a real PC. Um, and this, what this really allows us to do is add more fidelity to some of the function calls and really kind of take the next step, uh, we think, uh, in the PE emulation space. And then lastly, we want this to be highly configurable. So, we want, with the problem
with dynamic analysis, right, is that you have all, kind of an infinite array of cat and mouse, uh, in figuring out, you know, you know, anti-analysis techniques and like the, whether malware will run on a machine, so what we want to do is we want to define a single configuration file that represents the entire environment of the machine, so the entire context, with the idea that then we can enumerate a bunch of different configuration files and then we can run Bini against a particular sample much
faster against a hundred, you know, configuration files than we could spinning up a hundred different enumerations of those machines. So, the idea is, you know, you can change the keyboard, change the registries, uh, and then you can do this kind of very rapidly and then you can take, have the malware take different branches, um, and then just really explore what it actually does. Uh, so with that, so now we're
going to talk about the implementation details of Bini and, and while we're going through this, so a little, a quick history on Bini is that it started as just like a side project. We were looking at those three, uh, examples that I showed you from, uh, the Unicorn website and then we were just kind of playing around with it, throwing the PE in the emulator and seeing what it would do. Uh, and then eventually we got to this point
where we were actually getting interesting data or useful data, uh, and then we decided it was a, it was actually worth pursuing as a, as a real project and now it's actually living inside of our, our ingestion pipeline and everything goes through it. Um, so this was, uh, this talk will be from now and will kind of be like a little bit, we'll have
screenshots of that to, and explain what we were talking about, you know, in the slides prior. Uh, and then this will be kind of in chronological order of, you know, the different problems that we had while we were, you know, running different samples through it. So, you know, with that said, what's the first problem when you're building an emulator like this? So the first thing is you need to write a, you need a parser to parse the PE files and you need something to parse, you know, the DLLs and, and
all, and all the, get all the information out of there and you need to be able to link that up and throw it in the emulator. So, the first thing we did is we, of course, wrote a parser. So we wrote a PE parser that would, you know, parse, you know, our PE file, all the DLLs and then we added some, the reason we did, we wrote the parser is because we wanted to do all of the linking and the updating of like the base address
and, uh, you know, the imports and various other features. We wanted to do that all outside of the emulator and the main reason to do that is because we want, once we get everything in the emulator, we only want to start the emulator once. You know, we don't want to interact with the emulator a bunch, it's just, it's more time consuming and kind of problematic. So, you know, writing our PE parser and, and getting that
going, you basically, you know, you load the PE, you get its imports tables recursively and you go through and you get it, load up all the PEs and then you update the base address of the, of the DLLs, uh, and then once those are all synced up, then you throw that in memory. And, and one other reason we wanted to do this outside of the emulator was because for every DLL, once we finish linking everything up, we go back
through every DLL and we grab the exports. So we, we now we know where the real image at, images for, or the addresses for a particular function, uh, in the memory space, and now we're going to build our own map outside of the emulator that has a map between, you know, the DLL, the function and, and where the address actually is in memory. And this is so we can enable the hooking. So when the emulator actually jumps to that address, we know to stop the emulator, run our hook, uh, if, if there's a hook
available and then, and then move on. And you would think that this would work right away, right? Um, but on, on modern, on modern binaries or modern Windows machines, uh, there's these things called API sets. Uh, so when you compile a binary on Windows, um, anything after maybe Windows 7, I think, some service pack in
there, you'll actually, when you, you know, you pound a, uh, include a particular, uh, file and you do like load library in this case, as the screenshot, um, indicates, you're not going to get the real DLL. So we didn't actually know what the DLL was. Um, fortunately, uh, Jeff Chappelle has, you know, some amazing documentation, he's done a lot of RE work on this, and we were able to pull that implementation directly into Binny and add this to our PE parser. Um, so now when we, you know, when our PE
parser gets this kind of file, it grabs that, that full, uh, API set, grabs the API set schema DLL, which is in, you know, every version of Windows, you know, beyond, I think, 7, um, which is the lookup table for the actual real DLL on disk. So now we can do the real linking and load all this into, into the memory space. So this is kind of the
first problem that we had. So now, you know, we have the PE file inside of memory, we have all the DLLs linked up, uh, we haven't quite hit go yet, um, but the next thing we want to be able to do is, you know, we're mocking kind of the system, right? We're doing unit testing of the malware effectively, so we don't need to implement, you know, all
of the Windows, you know, subsystems, of course, that would obviously be painful, but we can implement subsets of it. And, but we, at the end of the day, what we really want is we want the malware to just think that this particular API was executed successfully. Like we don't really care that, about, like all the other details of the API, we just need, alright, does this function return a value? Is that value, what does that value need to be in order for the, the malware to continue executing? So in, in
the case of like create file, uh, all we really need here is we need to pop the, some values off of the stack, uh, and then we need to put a, like a valid, uh, a valid address or a valid, uh, identifier into EAX. So basically just not negative one there. And then, you know, the malware will continue thinking that it was executed successfully. So that brings us to hooking. So I mentioned hooking, we want it to be
incredibly simple, um, and, you know, we, we believe it is. So when you define a hook, as I said earlier, we have, we have a mapping of all the hooks where the addresses actually are. And what you do is when you want to implement this, uh, inside of, inside of the framework, you just define a type of struct that, you know, describes your hook. And
all you really need is the name of the function you want to hook, uh, the parameters, which is just a string, uh, an array of strings, um, and they also accept format string variables, which I'll explain on the next slide about, you know, display. And then the last two are optional, uh, function, or optional parameters. So if you define the function, this is the actual implementation that you would be over, uh,
overriding, uh, and then the return value. Um, and if you don't, you know, if you don't have these, it'll just assume, uh, its own default behavior. So with that, then, we ended up with two types of hooks. There's a full hook where we actually override the implementation in the DLL. So when Bini is executing inside of the PE, it goes to a
function call, so in this case it hits sleep, and then what'll happen is it'll do, it'll call instruction to sleep into, you know, kernel 32, whatever, and it'll go into that address in memory, and then what happens is, when we hit that address, because we have them all, we have the, the lookup table, we'll hook that address, stop execution, and run our implementation, which then can, you know, either override it in a full hook case,
um, or what I'll talk about in a second is partial hook. So looking at that, so we think this is fairly, the only way to define this hook is you just define the name, which is sleep, right? And then you define a pointer to the hook, which contains the parameters, which is the string, and then the function. And one thing that we think is pretty cool here is, particularly with malware, if it's doing like a sleep very
early on, you know, sometimes it's trying to evade something, so sleep in this case, we can actually in, uh, intercept the parameter, so with our function implementation, you get two parameters that are built into it, and those pass in the context of what the function's called, so basically the parameters that it's called and some other, you know, uh, metadata. And what we can do is we can just increment the tick count of the
CPU, and then just return immediately, and then the malware's just like, okay, yeah, we must've executed successfully, uh, we slept for five minutes or whatever, and it can go then call gets tick count later, and then it'll actually get an incremented tick count. So this will happen in real time, and it's just right, and it's just instant. So that's a full hook. Uh, but unfortunately we don't want to do, or fortunately we don't
want to hook everything because this would just take forever. So we really only want to hook things that make a system call. Um, so for everything else that doesn't actually make a system call and transition into kernel mode, we just want to do what we call a partial hook. And effectively what this does is this just gives us the details of the parameters in like a human readable form, uh, for that particular function. And so what happens here is when the function is called, it jumps into the DLL, that's that function
within the DLL, and it literally emulates that function and then returns, uh, back to the PE file as normal. Uh, so as I mentioned, the parameters field, so this is a particularly important field and it actually does like three things. Uh, the first is it
defines the, the string values, it sets the parameter name, so when you output as kind of in the bottom part of the screenshot, it'll give you the human readable values, uh, to the screen. So this is, this is information that we would capture, uh, in our data pipeline. Um, the second thing it'll do is it'll, uh, it'll dictate what gets popped off of the stack. So when you return from a function, it'll actually say,
alright, we have some helper functions built in that, so if you go back a slide, the skip function standard call, that's built in and that'll recognize how many parameters are on this, in this, in this list and then it'll pop those, those values off of the stack. And so it'll do all of this for you. Um, and then lastly, the parameters are what's used for when you call, when you call into that function and you
want access to those parameters to do your implementation, uh, this is how you would reference them as, you know, as the offset that they're actually in. So, a quick example, and there'll be several of these demos, you know, throughout, or these screenshot demos throughout, but if we look at the highlighted lines, the first one is, you know, we're
actually running Binny, um, and we have various parameters, so the dash V will actually say, we'll spit out all of the, uh, instructions, so this will be like verbose mode and it'll give you all the instructions leading up to a particular, uh, function call. And then the last line, uh, that's highlighted is the actual function call that we're, that we're getting, so we've actually hooked it, right? And you can see it's at a different address, so we know that this is where the DLL was mapped, this is where that
function is within that DLL and then just next to the address there, because it's slightly different than where the PE is, just next to that address is an F, so this would indicate that it's a full hook, uh, versus the partial hook, uh, and knowing this is actually very useful for debugging it when you're going through a malware and you're trying to get it to go to different branches, um, but that is that indication, and then you
get the, you know, the actual name of the function and, you know, the parameters, um, and they can be in human readable format, they take a format strings, um, parameter, um, and then of course the return value, which is also pretty important. Alright, so now at this point we basically have a PE parser, we're able to
load in DLLs and actually get everything set up to, to a certain extent, you know, we, we actually have some hooks probably implemented, we have our hooking system implemented, and that's all great, and this is where we kind of hit the feature parity mark for some of the other emulators that we were, that we were, uh, kind of describing earlier, um, and so we asked ourselves are we done here, and of course not, um, so we
were able to actually set an entry point and then start the emulator, um, set everything up as, as Kyle had mentioned earlier, and then press go and, and, and continue forward and hopefully get through most of the sample and have it terminate successfully. Well, in the case of some of what we were doing with partial hooking, it wasn't particularly working properly for us, um, in the case of, like say, get current
process ID, as you can see on the screen here, um, we were partially hooking this mainly because it wasn't making a system call, and typically we, we only want to full hook functions that are making system calls ultimately, and so in the case of get current process ID, it was actually accessing Windows user land objects, and we did
not have those set up at all, and so before we can actually go and set up these user land objects, we actually had to implement segment registers, and that was kind of a glaring oversight when we first set this all up, um, so fortunately, uh, there's actually, and thank, thanks to Chris Eagle on that, um, there's actually a lot of examples on how to, uh, on how to do that, and so we were able to kind of take the code that he had
written and kind of take that and, and make it, uh, suited to our needs. So now that we actually had the segment, uh, the segment registers, we were actually able to start building out Windows user land structures, uh, in particular. Um, most of what we've actually done is like the TIB and the PEB, which are the thread information block and
the, the process environment block respectively, um, and we actually wanted to start filling those out, because it turns out that malware actually, or any, any program really, uses those, um, extensively, um, typically when the Windows loader actually starts up a process, it will, it will actually populate a lot of the, a lot of these structures, um, so that the, you know, whatever's running can actually reference that,
and in, in many cases, uh, uses that information so it doesn't have to make, say, a, uh, contact switch into kernel mode to get certain information. So, we actually wanted to, to build these out, and much like the rest of the requirements of Binny, Binny, they needed to be configurable. So, with that, we actually started building out the TIB and
the PEB, and, and at first it was, it was mainly just as we saw fit, um, we'd see samples that would hit a certain portion of, of these structures, and then from there, it would fail, and then we'd say, okay, we're missing this, this certain field. And so, we actually built up the structures, and these structures are actually quite large, uh, for those of you who, who have maybe seen it before, these structures are quite long,
and every version of Windows, they keep adding more and more to this. So, as we were kind of going through the Windows versions, making sure that we had all the information, um, these, these structures actually ballooned in size quite a bit, um, but the important takeaway on this is that we actually, again, only populated the, the fields that we needed at that current time. Um, so, most of what we did was usually lower in the
structure, but, uh, higher level stuff, we kind of ignored and would nop out. And so, if, if we had an issue, we would then populate that and then move on. Um, and again, much like we did with the PEs and the, um, and the DLs when we were parsing, we were actually setting up the TIB and the PEB ahead of time, and actually having it kind
of in a, in a semi-working state before we actually started the emulator itself. Typically, that's done as the loader is going, but in this case, we, we again just kind of set up ahead of time with mock values that would kind of make the sample run and be happy and kind of go through what it needed to do. So, now that we actually had something going, we were actually getting through some samples. It was, it was great to see. We, we
actually got through a few, you know, example programs that we had written to test certain things out. We were going from start to finish. We were actually seeing the terminate process at the end, which was great to see, you know, really exciting stuff. So, then we actually came to like a crossroads where we wanted to actually continue adding more to it, like Kyle, Kyle mentioned with the requirements. There's,
there's a number of subsystems that we want to mock out, especially on the OS level. But before we can do that, we actually have to go and set up some, some more stuff that Windows would require. And for, for that reason, we actually, actually started doing, started doing stuff with handles. Um, Windows actually uses handles for a number of things. Um, basically anything that you can think of on like the lower level side of
things, like especially like file, file access, registry stuff, anything with the threading, uh, that, that's all done via handles, which are effectively just a memory pointer to some sort of information in memory. And so, what we did was we basically created like a superstructure of, of all the types of handles that we might
use and kind of put them in one place. And using that information, we can then just abstract away most of what Windows would expect to have inside the handles. And we can then kind of hand wave and pretend that they're actually there and the malware can, or any sample that we put through it can actually go and, uh, continue forward and we can, we can then build subsystems on top of that. So it's, it's kind of a basic building block for
us to kind of start building subsystems and mocking out the OS. And of course, you can't actually do anything with handles until we've, we've actually made a proper memory manager. So, we've actually started to build a memory manager inside Binny itself that would be kind of separate from the emulator in that we, we, we take, we took a, like a
normal heap implementation and then kind of built it up to, to kind of suit our needs a little bit more. So it does everything you would expect out of a heap, a heap, a heap memory manager and then we kind of built on top of that. Um, the way we kind of handle the heap in this case is anything that references the heap, so say it's malloc or free, some, one of those function calls. Um, what we would do is any library that was,
that was calling some, that some style of memory management, um, we'd partial hook and ultimately what's going to happen is they're going to hit NTDLL. And when we hit NTDLL, then we're actually full hooking that memory management function and then we're passing it over to the Binny memory manager and then doing everything from there. And
from there we can then start doing more things than just, you know, just heap management for example. Everything that's, everything that's not on the stack we're then just throwing into the heap and the, the memory manager's taking everything, care of everything for us. So with that we can actually start putting atomic IDs for our handles which will, which will point to our superstructures outside, outside the
emulator and then we, from there we can actually have inform, have those, those structures filled out and we can then from there build on top of it. So say we want to do file stuff, registry stuff, etc. So that, that's all now handled. Okay, so now I feel like at this point when we were doing the development we, this is where
it kind of switched into where it was a real project and we were actually able, we were confident that we were going to get useful information whereas before it was, it was kind of touch and go. Um, but basically what that means is we've, we've mimicked the, the user land space quite well, right? Uh, so we have, you know, as John was mentioning we have a heap, uh, which is, you know, critical and, and then we have all of the
user land processes and the hooking in place and things like that. So the next thing we want to do is, alright, let's see if we can actually capture some, some files. So if we have a piece of malware that writes a file, can we actually capture that, uh, and then save that and analyze it for later? So the first thing we want to start implementing when we got into, you know, kind of the mocking of the OS was the file system. And the way we did that is we, basically Binny will have, it kind of
operates similar to Windows where it, when you're searching for a DLL when you load something is, Binny will have several different paths where it looks for files. And the first path is its own kind of folder when you, so when you start Binny you can give it a file path and that will be its root directory for where the, you know, where the file system is. And then from within there you can actually copy in your
DLLs or copy in, you know, all the other files that you would want. So when Binny actually does a create file, um, it will actually grab, you know, whatever that file actually is. Um, and coming back to, you know, the hooking again, so what does the malware actually need though? We just need a valid handle. Um, so we have a file, we have a mock file system that can support the, the handles and then the abstractions
that go along with, uh, with interacting with the system. So with that, the first thing that happens is, you know, first of all, all of the file functions like create file, you know, write file, all these things, they're all going to be fully hooked, right? Because eventually these would make a system call and we want to intercept all of those things. So when we fully hook that, what happens is we're going to hit that address, uh, within the, within the emulator, the emulator is going to know we're at some address
that's fully hooked, it's going to pop out, so similar, similar to the transition from, you know, user to kernel space, it's going to pop out to our own file system handler. And then what's going to happen is, it's going to instantiate one of these new handles, uh, it's going to pass in all the parameters from create file, so specifically the path and the permissions. And then with that it's going to, you know, instantiate a file, create a, create a handle, put that handle in Vinnie's lookup table,
um, and then pass, you know, since Vinnie's getting a, you know, a valid handle from the heap, which is just going to be an atomic address, it's going to pass that back as, you know, EAX back into the create file. So now when you run create file, it'll actually get a real handle that then the malware can, can then use, or the file can then use. But the other thing we wanted to do is if we're running multiple samples
within this file system, we want any writes, like we don't want to pollute the system, the file system or the registry or anything that we do, but any writes need to go to our sandbox location. So if the malware is like installing some persistence mechanism or whatever, we want to actually capture that so we can analyze it later. So if there's anything that's created, like a create file with any type of write bit set, uh, Vinnie
will actually understand that, hey, they're trying to write here, so let's, instead of going to the real path that they're trying to write to or the real file that they're opening, let's redirect that into the sandbox location. So, as I said, so write file will get called, it'll get into, it'll get hooked, right, because we know the address, it'll go into the full, the, the Vinnie system handler, grab that handle and then
write anything that we're writing to the, to the file, it'll actually just redirect it to these bits. And then it'll just return however many bytes were written, uh, successfully and then the malware really doesn't know any different. Uh, and here's a little screenshot of that actually happening, so, uh, of course, the two highlighted lines, um, the first one, uh, actually, you know, create file and we're getting,
you know, the actual file and the path that it's located and the permissions. So this is super helpful when we're doing data analysis later because we're capturing all this data. Um, and this is the, more of the human readable form if you're running in, in manual mode, there's also a dash J option where we can calculate, get all this in, in JSON, so that's part of our ingestion pipeline. But the important thing here is we know the path, right, we know the permissions and then we know the return value. And
the return value is the handle, so the malware actually gets a valid handle here, right, it doesn't get negative one. So, the malware is like, okay, yeah, we're good, so we're gonna continue executing, uh, we're not in a sandbox. And then at the end there, um, the last highlighted line is write file, right, so now we're, the first parameter here is our valid handle and then we know when we hit write file, Binney's
gonna execute, uh, or intercept that, that call and then run its implementation, its full hook. And then of course we're gonna return a valid output for that, which is gonna be the number of bytes written. Uh, and then again, the malware, you know, doesn't really know any different. So, just, you know, in the console, you know, you can LS the, the file and everything goes to this temp directory, you know, we
created a mal dot exe, mal file exe, this is not a valid exe of course, uh, and then we just catted the bytes, so we can actually, this was kind of like, when we saw this, we're like alright, yeah, we can definitely, you know, we can definitely do something with this. Uh, and of course this is a very trivial example and we'll show some, some more of the demos of, of real malware. So, you know, we're just
kind of continuing on and this, this whole process is very iterative, we just get a new sample of malware and we kind of execute it, see how far it goes and it's like, oh, now we need to implement the file system, oh, now we need to implement this. Um, so the next one that we needed, that we wanted to implement or we needed to implement was the registry. And similar to the file system, every registry call is eventually going to, you know, drop into system, uh, or into kernel
mode, so we want to full hook all of those. And then when we full hook those, we built a registry within VINI that has a bunch of helper methods for, you know, accessing the, the different keys in the registry. And then one cool thing about this is, we made it, we wanted to mimic being able to load any value from your Windows registry into the VINI registry, we want to make that as seamless as possible. So if you just export, you know, from regedit, you can actually import all of that data, that
file that it exports, that you saved to disk, you can just copy and paste those into our configuration file, and then, um, VINI will just read those and load those up. So this is really useful if you're, if malware is dependent on certain keys or you're trying to, you know, evaluate what's, what it's actually storing in some keys. And then you can toggle these in, in kind of a real time and it's very fast. So, you
know, all registry keys, they're going to, you know, get hooked, it's going to get into the, you know, the VINI subsystem for handling registry, you know, do whatever option or whatever function that that's required, and then just return valid data back to the malware. And again, the malware has no idea. So, the next thing we want to do is, is configuration files. And as I mentioned, you know, these are
directly copied, the registry keys here are directly copied from, from regedit, from the export, and then inside of VINI's registry, there's a handler that converts these to bytes for whatever the proper type is. So we've kind of abstracted that away so you don't really have to worry about that on the hook. And that'll just copy the bytes back into the emulator and it, and it just works, you know, as you would expect. And the other thing to note and kind of one of our requirements was this
configuration file needs to be, you know, very easy to edit and very easy to understand, and kind of all inclusive. So, I've just kind of cherry picked a few values here, but, you know, there's obviously a lot more. The root file system, so this is how you define where the actual files are located, and this is typically where we put all the DLL's in like NLS files and, you know, other, you know, files that we
want, that are supporting the, the execution. And then you can also have like code page identifiers, you know, like process IDs, you can have pretty much anything that would go in the TIB or the PEB, or that would help the, you know, the execution of the, of the sample would go in this one file. And then, of course, the registry, you can just define it like this and it'll parse everything properly and build
the tree, so it's, you know, pretty efficient access. So, again, another quick sample, looking at the registry key, we have three, you know, highlighted rows, you know, we're accessed with the registry key, you know, we get great insight into what's actually happening, and these are kind of the IOC's that we really want when we're doing some of our machine learning. And then, you know, the query, the
values, you know, we can look at the particular, you know, the, the value name, and then next we can see what's actually getting set into those registry keys. And because this is, again, all turning, returning back successfully, the malware doesn't really, doesn't really know. So now that we actually have, you know, a few subsystems, we have file subsystem, registry subsystem, we have configuration files to
kind of back all that up. We actually started running this against more and more samples, and we were finding some interesting results. In the case, in the case of a few samples, we were hitting some, some interesting threading stuff, and in, in some cases we weren't actually doing anything with threading, and we wanted to. Many, you know, by
nature, because it's an emulation, didn't have any sort of thread management, so we actually implemented a thread manager. When we actually implemented this, we kind of treated it as like a global interpretation lock, so it's, it's basically just a round robin scheduler, everything's single threaded, and we time sliced out each of the threads. So, you know, it'll, a certain thread will run for certain instruction times,
so say n instructions, and then it'll move on to the next thread, and we can kind of hand wave away most of the threading issues that we were running into. And from there, we can actually allow malware to run threaded, and when you think about what a malware actually wants, it just cares that there's threads running, and that didn't, it
didn't get an error with a thread, right? It just, as long as it got a successful return value out of create thread, it just assumes the thread is running, and it's probably looking for information to be updated at some point, it doesn't really matter when. Um, so that, that's where this, this round robin scheduler kind of really shined, was because it was something so simple, but we were able to actually get stuff
to, to run through completely, even though it was multi-threaded. And so here's, here's just a quick example of, of that in action. Um, pay mostly attention to the left side of all those highlighted numbers, so in the numbers between the brackets, those are all the thread IDs, and this is like a standard output of any, all the function calls. Um, so as you can see, as time goes on, the, the thread ID will
change, because we're context switching into a different thread, and then from there, it'll just kind of continue forward until it completes. All these threads are really doing, and, and the highlighted lines are just creating threads, and each, each thread is at some point printing something. And, um, you can actually see some of the, the printf stuff with the format strings right there. Um, we have like the, on, on the
first, uh, printf, you can see like the percent D, et cetera, you can kind of see what's going to be put into that line when it's actually written to console. So, another thing that we actually ran into when we were running samples against Binny was, we saw some, some malware actually start dropping files, and, and, and this
case that would cause us to, um, kind of pursue DLL main stuff, was it was dropping DLLs to disk, and then it was loading them up dynamically. And so, we actually weren't doing anything with loading DLLs dynamically up until this point. In fact, we were just, all we were doing was just running a DLL, I'm sorry, parsing a DLL, and then while we were doing the parsing of the PEs, and then from there, it would, we would
just kind of run it. We weren't actually running the DLL main of those, of those, uh, DLLs themselves. Um, so, we actually went about trying to implement DLL main, because that's something that's required for us to actually do the library properly, and probably for, um, implementing more, um, stuff within the TIB and the PEB. Um, in some cases, especially for some system level DLLs, it will actually populate some values for
us for the TIB and the PEB, so we can actually, uh, go through and have those run, and then it will populate most of those fields for us, which is, which is great, we don't actually have to spend time with the fine tooth comb, kind of going through and adding more value to those, and, you know, that would probably drive us crazy at some point. So, what we ended up doing, we actually tried two, two ways of,
of implementing DLL main. So, for any DLL that we were loading up, statically, when the, as if we were pretending to be the loader, um, what we were, what we originally tried to do was just set the stack with the arguments that were required, set the entry point to, to the start of the DLL, DLL main, if it did exist, if it
didn't, we would skip over it, and then the return address from that would, would actually point to somewhere else in Bini's memory, where we had actually put interrupts, and so the interrupts would pause the emulation, and then we would then go and update the stack with the next DLL that needed to be ran, and then from there, if, if,
uh, if it also had a, um, if it also had a DLL main, we would just run through that again, and so on and so forth. But it turns out that when we were actually pausing the DLL main, or we were pausing the emulator, um, it would actually cause, kind of be a little bit more, uh, of an unclean state for the emulator itself. So, we wanted to stick more to the, uh, press the button once when we're ready to go, load up everything
ahead of time, and go. And the way we accomplished that is just through, just through a ROP chain, essentially. Um, so the idea behind this is that we wanted to, uh, set up the stack in a way, in a way such that when we actually started the emulation, um, the first entry point would be the first DLL that we needed to load. Typically this is
NT DLL and then, um, kernel 32, so we would set the stack with the arguments that we needed for that, and then we would actually put a return address onto the stack. But in this case, the return address for the, for the first DLL would be the entry point of the next DLL that needed to run. So we would just kind of keep chaining these together in stacks so that when we hit a return in, in a DLL, it would then pop the, the address of the
next DLL into the instruction pointer, and then from there we can just go through all the DLLs until they're done. And then finally when we hit the last DLL in line, um, the return address for that will just be the entry point of the PE that we're actually testing against. So this is actually quite a great way to do it. We were able to hit the, hit the emulation, uh, start button once, and then it was able to just continue
through, and then, um, we were actually getting some great results, a lot more fidelity, especially since we're having a lot more setup of, of the, of the mock OS done by the D, the DLLs themselves, which was great. And from there we could actually then take the same idea and apply it to, say, load library with like a full, a full hook. We could then just, uh, obviously give it a few different arguments, argument values, and then from
there we can, um, we can do more from that. So, I think that's about it. So, yeah, now we have some demos. Let's switch over. Okay. Alright, so the first, like, half of these demos are just kinda go through some of the, like, how you'd run this, like, at scale, or
how it, how it'd look at scale, I guess. But, um, and then we'll show some, show some real malware. And I'll try and pause it. So, um, in the beginning there's just, you know, there's a bunch of, or a bunch of, uh, parameters. Um, probably the most notable ones are just the dash V, uh, and VV. Um, oh yeah, so first one is, yeah, our
API sets. So, we just thought this was cool, so we just added in there. Uh, it was super helpful when we were doing, when we were building this, cause, you know, we have to be able to resolve those quickly. Um, but, you know, there's a verbose mode, so when you're doing verbose mode, like I said earlier, you'll get the instructions, which is like super helpful for reing things. But then if you do dash 2 V's, you'll also get the registers, uh, in the stack, uh, or at least a subset of the stack. And then
there's another flag, which is like dash D, so you'll get the, the actual DLL that it's in. So, you'll get DLL colon the function, uh, in the name. So, just going through here, so this is a very simple kind of a printf example, basically, of a console application. And we actually, we start at the, you know, at the beginning, at the entry point, and we can go all the way through, and we're getting, you know, nice, you
know, detailed information about the function parameters. So, this is pretty cool where we're getting, you know, human readable stuff from like, as John was mentioning, like printf, you know, create file, write file, you know, we're getting really good data here. So, now we're just showing some of the, the verbose
mode. And again, so, when you're doing the re-ing of a piece of malware, like having obviously the instructions is really helpful, especially when you're trying to manipulate the config file to maybe take a different branch. You can kind of just go through here and see what's actually happening after the function call, change,
modify the configuration file, which changes the environment, and now the binary runs completely differently. And then, uh, the dash VV, uh, sort of the same thing, except, as I mentioned, you now will get the registers, uh, and then a dump of the
stack as well. So, uh, useful, but, uh, not as useful as, as the other one. Uh, but it's interesting information nonetheless, um, when you're particularly debugging by hand. So,
now, um, we'll get to the threads, I think. Oh, yeah, so the dash D. So, now, if you ever need to know what the actual API set was, so this is where we, this is the reason we actually implemented the API set, the dash A and capital A, uh, within BINI, is because we were getting a lot of this and we need to know, alright, what API set is that? Okay, what DLL is that? Alright, what's the function we need to look at to see if
it's a full hook or a partial hook or something like that? And again, just kind of looking at the data, um, you know, create file, write file, you're getting all these IOCs, you're actually seeing what, uh, what the malware is doing, uh, without
actually executing anything. This, okay, so, yeah, so this is the key piece right here. So, the dash J flag, right, it converts all of this to JSON. So, when we put
this into our cluster and we get all of our samples, this is what we're getting back. So, then we go through and we can parse these for all the different interesting functions that we're looking for. Uh, so, in this case, we're looking at write file and we get, let me pause that, the interesting part here is we get the parameters, right, so you get the string value of the parameters and then you also get the values that's being passed to it, right, so you'll know exactly what's happening. So, you know, this
function is slightly less interesting, but the malware that's coming next is a little bit more interesting. Um, but again, you can parse all that data in real time and we can do this, you know, we can actually do this at scale, because this will run, you know, it'll run on Linux, it'll run in Docker, uh, and it'll also run in whatever, you know, your function as a service is for your cloud provider. You know, so
again, threading is, this is, this is actually sort of simple to implement, uh, but it was really cool when we actually got it to work. Um, it was just one of those, those kind of aha moments. Alright, so now for some real malware. Here, quickly. So, uh, this first case is from, from the, I believe it's the orange worm variant, uh, one of
their samples and, you know, this would run all the way through, uh, and this is part of that family, I think there was maybe 30 samples in that family and the interesting thing here is, you know, we get the, you know, we get the IOC, so we know what service is actually trying to start and we can do this without actually even running the sample. So, now we know where to look if we're hunting, you know, in your environment and you're looking for a particular server, you're looking at a particular malware and now you can
see some of these IOCs, so now you can hunt in your environment and figure out, you know, where these things actually are. You know, and additionally, there's this giprock address, so this is useful for getting around like some obfuscation and some packers, you know, if they hide all the, you know, from the imports table, you're not going to get that statically, but you can get that now dynamically and this is a pretty useful feature, uh, for any of your statistics. So, this next one, this is an
interesting sample, uh, because, uh, basically has multiple layers of packing, uh, and, and unpacking and what it does is, you know, effectively, we'll highlight these, so this is particularly interesting because now we're getting, this was hidden previously by all of the, from the static analysis because it wasn't in the import table, but now
we're actually getting this, uh, in real time, so we can add these to our, uh, to our machine learner model and say, hey, this thing actually does use these imports, these are the functions, these are the names, this is the DLL. And then additionally, you can see, like, actually right below it, you know, we're getting registry values, we're getting registry keys, um, but what's interesting about this sample is, you know, it's completely packed and then what it also does is it unpacks, uh, a DLL in memory and then
it writes it to disk, packed, uh, and then it loads itself and then, and then unpacks it again, uh, and that's kind of this part where it's, you read file, so now we're, we're getting all this, so we actually get the DLL that it's, that it's dumping, you know, we get the file name, you know, the naming scheme a little bit and then,
you know, you, again, you know, we can see the load libraries, we get, get proc address, you know, we're getting all of these IOCs, now we're adding these, we're tagging our, this binary in our, in our ingestion pipeline with all of these, these new IOCs, um, and then we're actually be able to collect new ones, so now we have a new DLL, we, this thing was written to disk, but it was written and it was redirected into our temp location, our sandbox location, uh, and now we can look at
it, um, later. So, we're open sourcing it, sorry, uh, quickly we had a couple things that we want to work on next, um, but yeah, we are, we are open sourcing it, so we're more than happy to help, uh, anyone get involved and, and get started, but, so these are some of the things, yeah, so, thank you.