Powered By Blogger

Friday, September 7, 2018

Recon 2018 day 3

This dump is puzzle

The talk is about  the methodology followed by the researcher to extract GSM APN credentials from an eSIM on IOT gateway device (the device bridges LPWAN to GSM/Private APN).
The challenge that had to solve the researcher here after dumping the chip is to construct the fragmented Zip files chunks (J2ME data). 

The researcher considered that a zip file contains a lot of metadata and structures (Ange Albertini ). Then the idea is to find clues to spot these metadata and write a puzzle solver.

So the approach consists in finding within the Zip file the End of the Central Directory. that gives the final record in a zip file, the total size of file headers and data and the total number of file entries.

Some complications were faced during the implementation of this idea as the fact that basing on the signature of the End of the Central Directory (PK\x05\x06), two instances can be found in the dump. That explains the need to classify fragments. For classification automation the researcher decided to apply K-means clustering method.


Slides can be downloaded from here.

Sandbagility - Reverse Engineering Framework for Windows dynamic analysis

The talk was about a malware analysis toolset based on a modified version of virtualbox and fast debugging protocol. The objective of creating this kind of environment is to avoid having an agent (like a driver) on the guest.

So the talk gave

  • an overview on the state of the art of malware analysis and fast debugging protocol 
  • a detailed explanation about Sandbagility 
  • an overview about some techniques implemented by the tool  


Slides are here.

A Code Pirate's Cutlass

The speaker tackled here a serious problem in reverse engineering. The context of his research is vulnerability analysis for embedded devices. Generally, in this context, a reverser has to deal with a single and large binary where there is no distinction between application threads, libraries and operating system. Within this all mess, understanding the software architecture is critical for the reverser.

The researcher defines the CodeCut problem as the result of liking multiple object files (multiple compiled source files) into one huge binary file (concatenation of the object files).

So given a call graph can reverser recover the different regions of the program (identify the boundaries of the different object files) ?

The speaker mentioned here that he blocked when he decided to solve this problem by using graph theory algorithms (scaling problems). So he decided to approach it as a numerical problem and introduced the LFA (Local Function Affinity) concept. And the receipt (As I got it):

  • If we eliminate external calls 
  • Directionality of calls at the beginning of the module is in the positive direction
  • Directionality of calls generally switch to the negative direction towards the end of the module
  • We can detect edges by finding the switch from negative back to positive

I'm not a math guy, if you're interested, you will find a math definition of LFA.

The tool is not  yet published but the speaker noted that he'll open source it as a futur work.

You can check for the slides here.

Taint-based return oriented programming

Sorry but I did not take much notes here and unfortunately the speaker did not published his slides.

After a brief introduction about ROP exploitation techniques, the researchers presented an approach based on taint analysis to identify a ROP chain. T-Brop is a tool that implements this technique.


Modern Linux Malware Exposed

The speakers begun their talk by stating that real life malware analyst does not turn only around Windows malware.
Then all the talk, as far as I'm concerned, a comparison between Windows and Linux malware in terms of stats, protections , obfuscation , packing and analysis techniques?


Slides are here.

Analyzing TRISIS - the first Safety Instrumented System malware

That was one of the talks that I really appreciated.

The talk is about REing an ICS malware code named TRISIS. This latter targeted a gas facility in Saudi Arabia (August 2017). The malware targeted the Safety Controller and caused a system shut down.
The SIS (Safety Instrument System) controller is a programmable logic controller designed to shut down a platform or a reactor safely. In a nutshell, This equipment is designed to protect people from being injured.
Basically, hacking a SIS doesn't mean that you won. You still have to overcome fail safe mechanism.
The attack consisted mainly in compromising a SIS-connected workstation, and then rebound to SIS system.
TRISIS malware components are:

  • SIS rootkit 
  • PC applications : TRilog.exe, py2exe 
  • 3 PowerPC payloads
  • A 4th unknown payload

The researchers introduced then Triconex hardware specifications that help them to start digging into the code. Blocked by some memory offsets located in the malware code they bought a Triconex controller. They explained then how they extracted and disassembled the Triconex firmware.


Slides can be downloaded from here.





Friday, August 31, 2018

Recon 2018 day 2

After a short break (I had to teach the sec 504 in Paris for a week) I had finally the time to carry on parsing my hand written notes taken in recon Montreal 2018.

Tracing Struct accesses with struct stalker
First all let me mention that this tool works only at source code level. Yes, I was bit disappointed when I knew that. As you know C++ reversing is a very time consuming process and the tools that already exist and work at binary level depend on a lot of parameters (compilation chain, compilers, IDA version, etc). The second point that made more disappointed, is that when you read the talk title you guess that you're going to learn a lot about how identifying C++ structures techniques. The talk was more about LLDB internals than the tool itself!

The speaker started his talk by introducing libfuzzer (LLVM project). He pointed out that this tool mainly takes an entry point as an argument, but he underlined the fact that you might encounter some problems when you want to fuzz some arbitrary code that takes complicated structs. That was the main starting point that motivated him to write "Struct Stalker" tool by monitoring accesses to structures fields. To solve this latter problem, the researcher used the techniques of a second tool (Pointer Sequence Reverser)developed by his colleague (Nicholas Collisson).

Before moving to the main part of the talk, which deals with LLDB, he demoed "Struct Stalker" tool. Normally you can get the tool here, but once again I got a 404 error when writing this post.

The main part of this talk , as I said before, was about the lessons learned bout LLDB during the development of the previous tools. So the speaker went trough a lecture about LLDB:

  • OK, at first glance LLDB , LLVM debugger ,seems to be compared to gdb, pretty scriptable and can deal with source and binary code.
  • LLDB uses .lldbinit (as .gdbinit) where you can set your favorite parameters as settings set target.x86-disassembly-flavor intel
  • Most useful LLDB commands : process, handle,status, continue, disassemble, breakpoint, thread, frame,memory, target, expression.
  • LLDP exposes a python API (not very documented) : public API are prefixed by SB: SBBreakpoint, SBDebugger,SBTarget,SBProcess,SBThread,etc.
  • Regarding LLDB python script skeleton(see slides), it should be noted that to setup a breakpoints you should write a callback function which can be sometime magic.  


At this time I stopped taking notes, as far as I'm concerned this kind of content like LLDB internals can be read quietly with a cup of coffee so I won't bother you by these details.

You can check the slides here.


Static instrumentation based on executable formats
The speaker presented a framework called LIEF. The idea behind this framework is to modify an executable structure (PE, ELF, Mach-O,etc) to do static instrumentation.
So modification that can be realized on the executable structure as: changing segment permissions, disabling ASLR, will be then managed by the OS loader and then the kernel.

Here LIEF comes to hand, this library developed in C++ exposes a friendly API and different languages bindings (Python,etc).

Some interesting modification that can be achieved by LIEF are

  • Hooking: by adding for example a trampoline code into the import table
  • Exporting hidden function 
  • Code injection through shared librairies

Finally, the speaker presented how FRIDA can be combined with LIEF to instrument Android applications. This technique consists in adding two files (libgadget.so and libgadget.config.so) into the target APK.


Slides can be downloaded here.

Discovering the iOS Instrument Server
Troy Browman goal's through this talk is to share his experience of reverse engineering Apple Instruments server.

So what is an Instruments server ?  The speaker defines as a set of debugging tools as Time profiling, Leak checking, Tracking file I/O,etc.
The main question that the speaker attempted to answer is : How OSX Xcode side communicates with the iOS instruments server ? For that he started by analyzing how Xcode queries the Instruments server for the processes list.

The first step of the analysis consists in identifying the Service in charge of implementing Instruments server.  That lead to DVTInstrumentsFoundation binary where core functionalities of Instruments server are located.

In that binary, the method DTDeviceInfoService runningProcesses seems to be the one called to list processes. The problem then is no cross call to this method is found.

The speaker introduced at this time the notion of DTXMessage. This latter is a class in charge of  serializing/deserializing Objective-C messages. More interesting fact about this class, is that DTXMessage  is a mechanism for transmitting Objective-C messages over the network.

To create a DTXMessage, the speaker decided to write a tool (dtxmsg)  to log this type of messages and replay them. By the way, he presented the structure of a DTXMessage. The RE of this component helped him to write a second tool called dtxmsg_client to send his own DTXMessage buffers.

Slides can be downloaded here.

Bushwhacking your way around a bootloader

What I remember about this Talk is how the speaker managed to keep calm even if she noticed the she was presenting the wrong version of the slides :).
So I won't bullshit you here I tried to take some notes but I was lost after a while. It is all about an analysis of u-boot.  A great summary of the talk can be found here  and the slides here.


Exploiting User-land vulnerabilities to Get Rogue App Installed Remotely on iOS 11

Yeah, KeenTeam dropped a bomb again in this talk. These guys are really amazing !
In this talk the team presented their methodology used during Pwn2Own 2017 to pawn an iOS 11.
The talk was organized as the following:

  • iOS remote exploitation chain overview 
  • Sandbox bypass and explnation of the used Bug (CVE-2017-7162)
  • Rogue application installation 
  • Demo
  • iOS 12 hardening 

Globally th exploitation scheme that is followed for iOS exploitation can be described as below:



For the Pwn2Own challenge there is no need to go for a Kernel bug to escape the Sandbox, the team said. However, they have to respect the OneClick policy that states that the exploit chain has to disable all the popups and alert messages.

For the Safari code execution:

  • OS sandbox is enforced by process , but some crticial daemons don't have sandbox launched
  • All 3rd webcontent app are applied with Sandbox profile
  • Sandbox configuration is compiled 

The strategy then is :

  • Not use a kernel bug 
  • Find a service/daemon with no sandbox 
  • That service has to be reached from Safari Sandbox 
  • For that purpose, a tool to review each process  and check Sandbox profile has been written (sb profile  =0)

One of the candidate service was Backboardd:

  • No Sandbox 
  • Complex MIG (Mach Interface Generator) interfaces (you can use jtool to list MIG interfaces)
  • reachable from Safari 


Regarding the exploitation the following CVEs were used/explained by the team:

  • CVE-2107-13861 (iOS/MacOS kernel double free due to IOSurfaceRootUserClient not respecting MIG ownership rules)
  • CVE-2017-7162 (Double free in backboardd)

The speakers explained then their techniques to exploit the double free vulnerability ,
a race condition (brute force approach is not stable, user instead OOL serailized messages with a slow parsing using CFAllocCtorAllocate with 0x20000 size instead of CFObject)
and how they bypassed ASLR (iOS share the same dyld_shared_cache_base) .


The last challenge that the team had to solve was code signing . In iOS CodeSign is enforced on code. All code must be signed by Apple, by a developer or by an Entreprise (in this two last cases a user interaction is required which is not compliant with the One Click Policy).

Webclips seems to be the solution. It appears that this not documented technology allows to install an HTML based application. The team then adopted the same approach as Pegasus APT. The technique consists in using a jsc script to trigger the vulnerability. Before that the content of the script into /Library/Webclips/Keelab/Exploit.html with an info.plist file(ULR= Attackerwebsite and fullscreen= TRUE to not open Safari). Exploit.html file will trigger the bug and bypass the SandBox  and install a rogue app.

Finally the team ended their talk with a Demo of iOS 12 jailbreak !


Malware Analysis and Automation using Binary Ninja

Actually, I was a bit disappointed by this talk. Yeah the speaker attempted to promote a potential great tool Binary Ninja, but she (in my point of view) did not present a real case with real challenges that tried to solve using Binary Ninja. Instead she went for a description of the tool. Ok may be 5 slides are sufficient to introduce the tool.  Yeah !In the slides , you'll find some slides about PlugX but it still the tool description took a lot of place in the talk.

Also, I do not agree with people who always try to compare a new tool to IDA pro.  IDA pro is IDA pro full stop.


Slides can be downloaded here.


An Open-Source Machine-Code Decompiler
The talk is about RetDec : a tool for machine-code decompilation based on LLVM.
Actually RetDec is a set of Reversing tools chained together to get a generic code decompilation tool.
The core is based on LLVM and supports mainly 32 bits architecture as x86, ARM, PowerPC and MIPS.


RetDec starts by preprocessing a binary to extract as much information as possible from it. Indeed, this phase calls a set of file format libraries to get a binary representation of the the given file and then process it to identify the use of potential packers (yara signatures). The tool embeds a set of unpackers in addition to Avast unpacker to get the original binary image.

Another layer/tool that is implemented in RetDec is Stacofin which can be useful to detetc statically linked code.

FileInfo, is a tool in RetDec suite that can parse a lot of binary formats (PE, ELF, Mach-O,etc) and returns the results in json format.

RetDec core is based on LLVM and is in charge to transform the binary machine code to LLVM IR (using Capstone engine -Capstone2LLVMIR):

  • hand coded sequences for core instructions
  • Full semantics for only simple instructions

It is interesting to underline that RetDec can be used from IDA pro by adding RetDec plugin.

Slides can be downloaded here.


Unknown Known DLLs and other Code Integrity Trust Violations

No word can be said here to describe this talk. Alex Ionescu and James Forshaw did a great job !
I'll try to describe as much as possible their talk even if the content was very dense regarding the time slot they were given to speak.
Unfortunately, the slides are not available yet, so you have to wait a bit more ...

I put here all my notes, may be they are incomplete or even not accurate.


So the talk was about code integrity technologies in Windows and the flaws in its robustness. For that some notions were firstly explained by the speakers:

  • Background on Windows code Integrity 
  • Protected processes 
  • Signature caching
  • Trust SIDs and Trust ACEs
  • Trust links in Tokens 
  • Known DLLs and mSection Object Mappings 

Code Intergrity technology can be distinguished for:

  • Kernel Mode Code Signing  (KMCS): with x64 an secure boot  windows drivers must be signed to be loaded. And from win 10 an extended validation certification was added  
  • User Mode Code Signing (UMCI) -v1: from windows 8/surface. An application can be 
    • 0->Unchecked, 1->Unsigned, 4->Authenticode, 8->Microsoft, 12->Windows .
  • User Mode Code Signing (UMCI) -v2: Fine grained signed levels (1-15)
    •  6->Store, 7->Anti Malware, 14->Windows TCB 

Protected Processes :

  • Deployed from Windows vista for DRM 
  • From Windows 8.1 Protected Processes Light (PPL) mechanism was deployed (Lsass.exe, Antivirus processes are protected)
  • Hierarchy of process protection levels (Matrix)
  • PP/PPL are used across the system and expanded dramatically by Windows Defender 
  • PP/PPL is not a security feature

When a binary is loaded, CI checks are carried out to specify its context ( if the process is PP/PLL, policy, cache,etc). These checks depends on the machine (Phone, Xbox, Defender,etc) . CI module reads the DLLs on the disk.

Different cache levels exist :

  • First on the disk cache 
  • Second : once the image is proven 
  • Third : once mapped (no checks)

James Forshaw tool (sandbox-attacksurface-analysis-tools)  has Get-NtDirectory cmdlet to get information about KnowDLLs:

$d = Get-NtDirectory \knownDLLs
$d.SecurityDescriptor.ProcessTrustLabel

Unknown DLLs are loaded at boot then mapped.


Here, the question that the speakers will answer is : How to break the code signing a the beginning ?

To create a protected process service  (Admin Only)
CreateProcessW (...,CREATE_PROTECTED_PROCESS,...) and the code ahs to have a correct signature

Trust SID : SID which defines a partial Trust : S-1-19-XXXX(process level)-YYYY(signer level)
(see RTLSidDomainForestTrust)

$p = New-Win32Process -creationFlags suspended,ProtectedProcess "....exe"
$t  = Get-NtToken -Primary -Process $p.process

Trust ACEs:
SYSTEM_PROCESS_TRUST_LABEL=ACE_TYPE, you can read unknown DLLs and write unless you are a PPL process (majority of files on Windows ara catalog files signed).

Kernel Extended attributes (EA):

$Kernel (can only set by the Kernel)
$kernel-purge (don't look at it again)

EA.bin : EA cache format : _CI_ESB_EA_V3 / _CI_DATA_BLOB


Who sets the cake ?
NtSetCachedSigningLevel (undocumented API). The API allows a caller to set "validated" level ("Trust me") as long as the caller is PPL. Flag 0x02 and flag 0x40.

For driver signing the cache is not trusted at all.

Section creation bugs:

NtSatus NtSetCacheSigningLevel {
Flags --> 0 (needs ppl)
               4 : to cache the signature
}

CVE 2017-11830


PPL cache attack:

Win the race as we are PPL (flag 0x02), write  flag 0x40.

The USN Zero change journal Rebirth
Attempt to change USN journal before a change (CI does not check USN0 assumes it is signed) --> need physical attack.
Once you delete USN journal (USN has unique 64 bit ID however they are not randomly generated) , create a new one.
This case has been patched, you can not delet USN Journal.


The cached signing level duality
CVE 2018-8142

Section Mapping bugs
Abusing Known DLLs : write in KnownDLLs?

In conclusion , that was interesting to see how CI can be bypassed.




Monday, June 25, 2018

Recon 2018 day 1

Recon the con ! 

Recon is a very famous Reverse engineering oriented conference held  in Montreal. This year I had the opportunity to attend this year Bruce Dang training training and the conference.
My first feedback is that this conference is an amazing one for those interested by computer security in general and in reverse engineering in special. And Let me tell you that this year the conference materials was extremely mind blowing !

Before I go for a summary of the main notes that I took, here are the best talks in my point of view. I put them following their  given slot in the the conference:
  • Day 1 
    • Reverse Engineering Windows Defender Part II (Alexei Bulazel)
    • PreVice: Static Detection of Hooking Capabilities in Machine Code (Andy Wortman,Claudiu Teodorescu,Derek Soeder)
    • Meet Salinas, the first ever SMS-commanded Car Infotainment RAT (Daniel Regalado,Ken Hsu, Gerardo Iglesias)
    • Pwning Intel PIN(Julian Kirsch,Zhechko Zhechev)
  • Day 2 
    • Static instrumentation based on executable file formats (Romain Thomas)
    • Discovering the iOS Instruments Server (Troy Bowman)
    • Exploiting User-land vulnerabilities to Get Rogue App Installed Remotely on iOS 11 (Liang Chen, Marco Grassi)
    • Unknown Known DLLs and other Code Integrity Trust Violations (Alex Ionescu, James Forshaw)
  • Day 3 
    • Analyzing TRISIS - the first Safety Instrumented System malware (K. Reid Wightman, Jimmy Wylie)
    • SiliVaccine: North Korea's weapon of Mass Detection (Mark Lechtik, Michael Kajiloti)
    • PWN Flash with Reflection and HashTables (Tao Yan, Bo Qu)

Reverse Engineering Windows Defender Part II
You might go and start following this guy on Twitter, his talk is one of the best that I can recommend.  His previous studies concern inner working of antivirus engines. The talk, which can be considered a second part of a fist talk.

The speaker explains in his talk the methodology that he adopted to reverse Windows Defender Antivirus engine and sheds light on all the challenges where he struggled during his analysis. The cool thing that I appreciate in his talk is the fact that he went through the talk smoothly by insisting on the process itself and not throwing technical details ont the face of the attendees. 

Windows defender is a the builtin Windows antivirus engine, that run with SYSTEM privileges in an unsandboxed process. Alexei's research focuses this time on reing the binary emulator in charge to scan malicious code.
The Antivirus engine is an emulator (not virtualization) that loads an unknown binary, run it from its entrypoint and collect observations basing on various heuristics. For that the emulator has to manage to emulate the cpu, OS, OS Api and the environnement (filesystem, processes, settings,etc).
Alexei's used his previous works about antivirus engine that allowed him to develop techniques for introspecting the antivirus engine and leaking his internal structures and functions. 

The main targets of the research are:
  • Microsoft Malware Protection Engine: mpam-fe.exe 
  • Microsoft Malware Protection: mpengine.dll
  • Signature Update Stub: MPSigStub.exe
  • Signature databases
    • mpasbase.vdm
    • mpasdlta.vdm
    • mpavbase.vdm
    • mpavdlta.vdm 
The analysis process as for each reing project consisted in :
  • Static analysis phase : using IDa pro, public MS Pdbs and bindiffs basing on Google Project 0 findings. Some other tools were used especially for code coverage as Lighthouse IDA plugin  and Taviso's Coverage tool.
  • Dynamic phase: this one seemed to be complicated knowing the defender components run in a protected Windows process and the scanning process may not be triggered on demand and that could reduce the code reachability.  That where Taviso's tool comes in hand, LoadLibrary and especially mpclient.exe allows load Defender engine and exposes its interfaces. Alexei's demoed this tool the main workflow was : mpclient.exe Eicar.com --> WinApi emulation --> _rsignal(Defender engine interface)  --> Engine emulator. 
Reing the engine components allowed to make some observations: When a malware is getting emulated, _rsignal (main entrypoint) function is called, it takes a buffer as an argument. The emulation initialization step starts then to allocate memory, init various objects, load the binary, init emulated DLLs and start recording heuristics. The cpu emulation consists in a dynamic translation of instructions (IL lifting : IL-tox-86 Jit translation). 

For emulator instrumentation task, the idea was writing a custom malware that can install a hook in an internal engine structure called g_syscalls (Winexec). And for mapping emulator adresses a hook has been installed on OutputDebugStringA. However, a binary might not be emulated if it has some characteristics(low entropy, linking against unknown DLLs).
Alexei's then explained how he dumped the virtual file system and virtual processes (apparently using the same trick as OutputDebugStringA).

Windows API emulation seems to be based on two DLL types: 
  • Emulated ones : VDLL, that stay inside the emulator, and complex ones are coded to return hard coded valus
  • Normal ones: triggers a syscall outside the emulator.
The UM-KM emulator communication is carried out using an internal emulator instraction function called api_call that takes as arguments : crc32(Dll_name) ^ crc32(dll_function). The disaseembky of api_call still a challenge and may be presented in a future GTFO || POC paper. 
api_call links emulator Apis to the outside world.

Kernel emulator functions are embedded in native code. This kernel has its own Object manager but the managed objects are fewer than a normal kernel, there are aonly : File, Thread, Event, Mutant and semaphore objects (dt mpengine!objectmanager.FileObject). Objects are stored in a map 

Last but not least, Alexei exposes some intersing Defender engine functions : MpaddToScanqueue, MpCreateMemeryEngine and MpReportEvent.

Finally, Alexei pointed out that mpengine.dll embeds also other components as unpackers, parsers, scanning engines,etc. And It might be interesting to bootstrap a research project on that. Main developed code will be published at BH.

NB: Emulator IL was not dumped but it can be doable.

Cloudy With a Chance of Malware
I was not very excited by talk may be because I'm not interested by Threat Intelligence field. However, I'll try to stay partial when writing my notes.

Marika Chauvin presented a comparison between two malwares KasperAgent and  Cloudy in order to highlight their differences and similarities.
The story begins with KasperAgent which seemed linked to Micropsia Android malware. The first campaign was in May 2017, one of the main indicator related to this malware was the use of a specific User Agent : OPAER. This malware targeted Palestinian authorities using fake administrative documents. Some pdb strings seem to be used by this malware.
The analysis of KasperAgent allowed to spot a second variety called Cloudy, however the attack vector used by this malware consisted in fake document used to be exchanged between inter-nation relation states.
At the opposite of KasperAgent, Cloudy malware target other countries as : Israel, India and UAE.
Both malware were attributed UAE.

SiliVaccine: North Korea's weapon of Mass Detection 
That was an interesting talk where the speakers shed light on some shady zones inside a north Korean antivirus known as Silivaccine.

First of all, Checkpoint resarchers said that they obtained the antivirus from Martyn Wiliams who's a journalist specialized in North Korea.
After its installation, the speakers presented the general picture of the antivirus architecture. The antivirus components can be splitted into:

  • UM components: SVshell.dll, SVkernel.dll (file scanning engine), SVregsrv.dll, SV2Tray.exe, SVupdate.exe, SVDiffUpd.exe (integrity checker), SVMain.exe and SVdealer.exe
  • KM components: SVhook.sys, SVstdi2.sys (supposed to hook tcp communication but it does nothing), SVFiltmsg.sys

During their investigation, the researcher stumbled from surprise to surprise. Looking at the strings, allows them to spot a DLL name (vspai32.dll) which belongs to Trend Micro Antivirus. In addition to that the bindiffing between Silivaccine and Trend Micro dlls resulted in 100% match and similar call graphs. The only differences concern inlining some functions in Sillivaccine (that might let suppose that Silivvacine has access to some source code) .

As Silivaccine has potentially the same antivirus engine as TrendMicro, Checkpoint researchers wondered if it has the same database signature format.  Hence, they find that Silivaccine has added an encryption layer to Trend Micro signature databases (using "Pattern Encryption" as an encryption key in Korean keyboard). Moreover, Silivaccine authors modified the naming convention of the virus  and malwares that can be identified (TM : MAL_NUCRP_5 becomes mal.nucrp.f in SV) . By the way they discovered that this malware is white-listed by SV even this specimen is a generic one. They did not come across about the reason of this exception.

 Regarding KM drivers, it seems that they were packed using an old Russian packer (simple xor with 0x42):

  • SVFilter is loaded by SVdealer.exe and it's in charge of real time scanning and protection of SV binaries
  • SVhook.sys: loaded by SVMain.exe and only query kernel objects without any hooking techniques and contains a lot of code that is never used.

Some coding styles made the analysis funnier. For example, the researchers spotted that in a UM component the length of a buffer can be set to a fixed value (0x12) and when the KM module receives the buffer it checks its length as : if ( len(buffer) == 0x12 return ERROR). Maybe the two modules were written by two different person who does not communicate.
Another joke concerns the use of  debugging message with IDA pro names : Dbgprint (" sub_xxxx bah"), which may indicate that SV authors dumped a lot of code from their TrendMicro reversing sessions.

The last part of the talk  focused on Silivaccine origins. Different hypothesis were emitted here (STS tech service: a ghost company, a collaboration with a Japanese company).
In all cases, it seems that Silivaccine is distributed with a MS patch signed by Kaspersky and that latter corresponds to Jaku malware first stage (may be because it targeted Martyn Wiliams).


Building a Damned Good Watch
Actually, this field is not my cup of tea. However  Travis Goodspeed is a passionate security researcher and he's able to communicate his passion. So let's see if I picked up something or not !

So yeah Travis one day dreamed about "a nifty wristwatch. It would have years of battery life, with an MSP430 microcontroller and RPN calculator. It would be able to receive and transmit on amateur radio frequencies, in a variety of digital modes. It would look spiffy."

I suspect that you guess it, it's better for you to go to his blog and read the article, either I'll confuse with my notes.


PreVice: Static Detection of Hooking Capabilities in Machine Code
The main idea if PreVice tool is to detect hooking capabilities in Windows PE before it happens. The speakers began their talk by a demo of the tool. Then the went through a brief introduction of the different hooking (Unsanctioned interception of execution, unofficial, no contract) techniques. They distinguished between:

  • Code hooking (detours): export and import table
  • System Call  : SYSCALL, SYSENTER, MSR, IDT and SSDT

Before presenting the internals of PreVice tool, the speakers gave an overview of existent tools:


The static analysis approach exposed by the speaker consists in considering a program as a set of functions that gives a state instead of taking it as state that changes during the execution. The main challenges that they fixed are performance and accuracy.

So, Previce inner working includes:

  • Code machine to instructions translation 
  • Constraint propagation 
  • Symbolic execution
  • Type information propagation  
  • Static Single Assignment (SSA)  

Having a code view of the code they can apply a set of signature to identify potential hooking regions  (ex: FS → TEB → PEB → ImageBase → ImortTable).

Meet Salinas, the first ever SMS-commanded Car Infotainment RAT
This talk was just amazing, the speakers were very enthusiastic and engaged in their explanations.
The idea here is to find a way to compromise a car infotainment system by targeting the car driver (especially his phone) instead of the car directly.

The first challenge that they had to overcome was to find an Infotainment system and its wiring diagram. Moreover, the infotainment ideally has to be an ARM architecture with a bluetooth stack, a CAN bus, USB and ethernet  plug.

The first step that they achieve, once they got their Infotainment system (201B 0920-201B) is they got a shell access (after a port scan that pops up a SSH access and a password brute force attack).

To have a persistant access to the Infotainment system, the researchers exploited similar to Windows Service management (SCM) based on a configuration file (sm.conf) to add a new service after remounting system partition in read/write. This service will be used a component in the RAT design.

Before introducing how the RAT actually was developed, it is interesting to know that some Infotainment internal architecture. This latter is organized around the MMUI -Multi Medi User Interface (an opera browser + local webserver + websocket) . The MMUI is linked to other components (Service manager, Radio, GPS, Bluetooth stack, CAN bus,etc) over DBUS.

To interact with these different component, the speakers discovered a test application left by the vendor that can be configured using a xml file to trigger specific tests. Thus reversing this application allowed them to understand how to communicate with these components. By the way they crashed at this stage their infotainment 3 weeks before recon CFP closing. Hopefully they got a second access through an UART port.

Analyzing the communication between MMUI and a linked phone via Bluetooth, it was possible for them to understand how a SMS is handled by the Infotainment system.

Infotainment --> MMUI --> MSG interface/DBUS --> BDS (Bluetooth Developer Studio) --> Phone

  • Receiving a SMS triggers an event in BDS 
  • BDS sends a notification over DBUSto MSG interface (service)
  • At the other hand  the MMUI usi MSG interface apis to to respond to an incoming SMS 
  • The SMS is stored then in a local sqlite DB (not encrypted)
The last that they have to resolve before completing the RAT is to identify the phone number linked to the car. For that they opted to sniffing DBUS communication (use dbus_monitor and dbus_send).

Finally, the attack demo consisted in:
  • connecting a USB key with Salinas RAT to be installed on the Infotainment system
  • Disconnecting the paired phone 
  • Intercepting the new pairing session 
  • grab the phone number by sniffing DBUS communication 
  • send SMS commands to the paired phone that will transfer it to the RAT.
I hope that I did  not missed a point ! 




Monday, July 21, 2014

Challenge SSTIC 2014

[ En mode Draft ... relecture en cours]
Introduction:

Cette année j'ai pu me pencher sur le challenge SSTIC (http://communaute.sstic.org/ChallengeSSTIC2014) et ce dernier n'a pas failli à sa réputation ...Merci à l'équipe QuarksLab pour cette souffrance :)

Etape1: usbmon

La première partie correspond à une capture USB apparemment réalisée entre un device 'Android' et une machine utilisant le protocole ADB.

Pour avoir une idée sur le contenu de ce fichier l'outil usb-analyzer a été utilisé.Un autre outil (voir "usbmon_helper.py") permet de visualiser le contenu d'une capture usbmon en HTML.

Une première analyse a vite révélé que la capture contient un transfert de fichier entre le device Android et une machine cible.

Le protocole ADB indique que pour un transfert de fichier les commandes suivantes doivent être enchaînées selon le format suivant:

Send → AdbMessage(A_OPEN, local_id, 0, "sync:");
Receive ← AdbMessage(A_OKAY, remote_id, local_id, NULL);
Query File Attributes. If file exists, then proceed.
Send → AdbMessage(A_WRTE, local_id, remote_id, "RECVnnnn");
Receive ← AdbMessage(A_OKAY, remote_id, local_id, NULL);
Send → AdbMessage(A_WRTE, local_id, remote_id, "remote file name");
Receive ← AdbMessage(A_OKAY, remote_id, local_id, NULL);
Receive ← AdbMessage(A_WRTE, remote_id, local_id, "DATAnnnn......");
Send → AdbMessage(A_OKAY, local_id, remote_id, NULL);
Receive ← AdbMessage(A_WRTE, remote_id, local_id, data);
Send → AdbMessage(A_OKAY, local_id, remote_id, NULL);
...
Receive ← AdbMessage(A_WRTE, remote_id, local_id, "DONEnnnn");
Send → AdbMessage(A_WRTE, local_id, remote_id, "QUITnnnn");
Receive ← AdbMessage(A_CLSE, remote_id, local_id, NULL);
Send → AdbMessage(A_CLSE, local_id, remote_id, NULL);

L'outil "usbmon_helper.py" a été légèrement modifié pour récupérer le contenu binaire du fichier transféré par le protocole ADB (voire stage1.bin)

Le fichier idb produit est stage1.i64


Etape 2: premier binaire ARM 64 bit

Environnement de travail
Afin d'avoir un environnement d'analyse les composants suivants ont été utilisés:


  • Une machine virtuelle basée sur l'outil "Foundation Model v8" qui offre un environnement de virtualisation d'un cpu ARMv8 et qui pemet de démarrer un système Linux.
  • Un système Linux (ubuntu) pour ARM 64 bits.


Donc en gros on dispose d'une machine virtuelle ubuntu ARM 64 bits. Cela permet de compiler les outils nécessaires à l'analyse de notre binaire.

L'idée est d'analyser le binaire récupéré de l'étape précédente en combinant une analyse dynamique avec gdb et une analyse statique avec IDA.

Pour coller les deux morceaux, l'outil Qbsync de QuarksLab a été utilisé, ce dernier permet de visualiser les étapes de débogage sur IDA d'ou la nécessité d'avoir un gdb compilé avec python (possible avec la machine virtuelle):

L’exécution du binaire permet de comprendre l'objectif de cette étape, ce dernier demande la saisie d'une clé permettant de récupérer un fichier nommé 'payload.bin'.

(Pour plus de détails sur l'analyse suivante, s’appuyer le fichier idb)

En déboguant pas à pas le binaire, on arrive à identifier le flux suivant:
Au niveau du point d'entrée, on retrouve un appel vers sub_1010C:

loc_102E0               ; Store Pair
FD 7B BF A9                                  STP             X29, X30, [SP,#var_10]!
FD 03 00 91                                  MOV             X29, SP ; Rd = Op2
89 FF FF 97                                  BL              sub_1010C ; Branch with Link
01 7C 40 93                                  SBFM            X1, X0, #0, #0x1F ; Signed Bitfield Move
E0 03 01 AA                                  MOV             X0, X1  ; Rd = Op2
C8 0B 80 D2                                  MOV             X8, #0x5E ; Rd = Op2
01 00 00 D4                                  SVC             0       ; Supervisor Call
E1 03 00 AA                                  MOV             X1, X0


Après plusieurs itérations, le binaire arrive à la section du code suivante:

.text:00000000000102A8                 LDRSW           X24, [X29,#arg_58] ; Load from Memory
.text:00000000000102AC                 LDR             X1, [X29,#arg_50] ; Load from Memory
.text:00000000000102B0                 MOV             SP, X25 ; Rd = Op2
.text:00000000000102B4                 SUB             SP, SP, #8 ; Rd = Op1 - Op2
.text:00000000000102B8                 STR             X24, [SP,#0x68+var_68] ; Store to Memory
.text:00000000000102BC                 MOV             X2, X1  ; Rd = Op2
.text:00000000000102C0                 BLR             X2      ; x2             0x400514 4195604
.text:00000000000102C4                 MOV             X23, X0 ; Rd = Op2
.text:00000000000102C8                 B               loc_10198 ; Branch
.text:00000000000102C8 ; End of function sub_1010C
.text:00000000000102C8

La suite d'itérations réalisées avant d'arriver à ce stade correspondent à la décompression d'une nouvelle section.
L'instruction BLR x2 permet à la première section du binaire de sauter vers une section nouvellement créée.

Ensuite avec gdb il est possible de dumper cette section (0x4000) quand peut aussi voir avec  la commande "cat /proc/mem/pid".

.text:00000000000102A8                 LDRSW           X24, [X29,#arg_58] ; Load from Memory
.text:00000000000102AC                 LDR             X1, [X29,#arg_50] ; Load from Memory
.text:00000000000102B0                 MOV             SP, X25 ; Rd = Op2
.text:00000000000102B4                 SUB             SP, SP, #8 ; Rd = Op1 - Op2
.text:00000000000102B8                 STR             X24, [SP,#0x68+var_68] ; Store to Memory
.text:00000000000102BC                 MOV             X2, X1  ; Rd = Op2
.text:00000000000102C0                 BLR             X2      ; x2             0x400514 4195604
.text:00000000000102C4                 MOV             X23, X0 ; Rd = Op2
.text:00000000000102C8                 B               loc_10198 ; Branch
.text:00000000000102C8 ; End of function sub_1010C
.text:00000000000102C8


Une fois cette section dumpée, il a été possible de l'ajouter au niveau de l'idb (IDA) courant afin de faciliter la suite de l'analyse. une attention a été portée sur l'ajout de la section au niveau de l'idb d'IDA afin que le mapping dynamique correspond au sections statique.

On continue l'analyse dynamique/statique avec la combinaison gdb/qbsync/IDA.
Cette deuxième partie du binaire est 'obfusquée' en utilisant une machine virtuelle. Par conséquence, l'objectif de cette étape consiste à comprendre le fonctionnement de la machine virtuelle. Pour cela il faut:
+ Identifier et récupérer le byte code de la machine virtuelle
+ Identifier l'ensemble des instruction de la machine virtuelle
+ Identifier la mémoire, la pile et les registres utilisés par la mémoire virtuelle.

Une fois l'ensemble de ces élements, un décodeur sera écrit afin de désassembler le Byte code de la VM. Pour cela l'outil AMOCO a été utilisé.

(une lecture du chapitre obfuscation par la virtualisation Practical Reverse Engineering a aidé à connaitre la notion de VM Hanlder/Dispatcher, fonction de récupération de registre, fonction de récupération de valeur de registres, boucle principale).
La partie suivante essayera de mettre en évidence ces élements (même si je ne me rapelle plus de l'ordre que j'ai suivi pour mettre en évidence ces élements)

Une fois décompressée, le binaire saute à la section 0x400000 (à l'adresse 0x400514), il enchaîne l’exécution de plusieurs instructions(brève description) :

1. Appel de la fonction 0x4000524:
text:0000000000400524                 B               Call_svc_exit_group ; Branch

2.Appel de la fonction 0x04004F8 que je qualifie de VM Main Entry:

             X2, X2, #unk_510018@PAGEOFF ; x2             0x510018
             STR             X3, [X2] ; Store to Memory
            BL              Main_Entry ; Branch with Link                                        SBFM            X1, X0, #0, #0x1F

3.Appel de la fonction 0x04000C8 que je que qualifie de 'VM set context' car elle permet de mettre en place les composants de la VM (sections mémoires, context crypto):

.text:00000000004000C0                 ADD             X0, X0, #unk_500000@PAGEOFF ; Rd = Op1 + Op2
.text:00000000004000C4                 ADD             X2, X29, #0x10 ; Rd = Op1 + Op2
.text:00000000004000C8                 BL              VM_set_context ; x0             0x500000 5242880
.text:00000000004000C8                                         ; x1             0x10000  65536
.text:00000000004000C8                                         ; x2    

En effet le syscall présents au niveau de cette fonction  permettent de répérer les sections mémoires utilisé par la VM.

La section 0x500000 attire notre attention, aprés avoir dumpé le contenu de cette dernière, elle semble obfusquée (voir vm_bytecode.bin) .


Toutefois en arrivant à la section du code suivant:
.text:0000000000402A88                 BL              Func_Ecrypt_init ; Branch with Link
.text:0000000000402A8C                 ADD             X22, X19, #0x10 ; Rd = Op1 + Op2
.text:0000000000402A90                 ADRP            X1, #unk_510000@PAGE ; x1             0x510000 5308416
.text:0000000000402A94                 MOV             X0, X22 ; Rd = Op2
.text:0000000000402A98                 ADD             X1, X1, #unk_510000@PAGEOFF ; Rd = Op1 + Op2
.text:0000000000402A9C                 MOV             W2, #128 ; le parametere kbits
.text:0000000000402AA0                 MOV             W3, #0  ; Rd = Op2
.text:0000000000402AA4                 BL              Func_KEy_setup ; void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
.text:0000000000402AA8                 ADRP            X1, #unk_510020@PAGE ; Address of Page
.text:0000000000402AAC                 MOV             X0, X22 ; Rd = Op2
.text:0000000000402AB0                 ADD             X1, X1, #unk_510020@PAGEOFF ; x1             0x510020 5308448
.text:0000000000402AB4                 BL              func_Ecrypt_ivsetup ; Branch with Link
.text:0000000000402AB8                 LDRB            W0, [X19] ; Load from Memory

En inspectant le contenu de la mémoire , on retrouve la chaine ""expand 16-byte k" qui en recherchant sur Internet permet de d'identifier en premier lieu l'algorithme de chiffrement Salsa puis dans un deuxième temps sa version Chacha.

En comparant le code C des différentes fonctions de cet algorithme, comme
void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv)
{
  int i = 0 ;
  x->input[12] = 0;
  x->input[13] = 0;
  x->input[14] = U8TO32_LITTLE(iv + 0);
  x->input[15] = U8TO32_LITTLE(iv + 4);
  //Printing the context
  printf("[ECRYPT_ivsetup] The Chacha context:\n");
   for (i=0; i<16 i="" p="">     printf("0x%x\n", x->input[i]);
}

et le code assembleur à l'offset 0x402AB4 on retrouve rapidement des similitudes.

La comparaison a permis de s'orienter plutôt vers la variante chacha que salsa. Ce qui est intéressant à ce satade est d'identifier la clé utilisée par cet algorithme. Cette information peut être obtenue en mettant un breakpoint à l'appel de la fonction 'ECRYPT_keysetup' qui reçoit en second paramètre la clé de chiffrement.


- Chiffrement Salsa/Chacha
-------------------------------------

Il se trouve que la section 0x500000 est chiffré avec l'algorithme de chiffrement chacha. le code chacha_test.c a permis de récupérer le contenu de cette section en clair
(voir VM_bytecode_dec.bin).

A ce stade on dispose du Byte code de la VM:

00000030   00 00 00 00  00 20 00 00  00 00 00 00  40 00 00 00  ..... ......@...
00000040   00 01 00 00  01 21 00 00  00 02 00 00  01 12 00 00  .....!..........
00000050   00 03 00 00  01 E3 32 00  00 04 00 00  01 44 02 00  ......2......D..
00000060   1D 00 00 01  00 00 01 11  00 00 0A 22  00 03 00 00  .

la fin du byte code contient les chaines de carctères affichés lors de l'exécution de notre binaire
20 50 6C 65  61 73 65 20  65 6E 74 65  72 20 74 68   Please enter th
00000340   65 20 64 65  63 72 79 70  74 69 6F 6E  20 6B 65 79  e decryption key
00000350   3A 20 00 00  3A 3A 20 54  72 79 69 6E  67 20 74 6F  : ..:: Trying to
00000360   20 64 65 63  72 79 70 74  20 70 61 79  6C 6F 61 64   decrypt payload
00000370   2E 2E 2E 0A  20 20 20 57  72 6F 6E 67  20 6B 65 79  ....   Wrong key
00000380   20 66 6F 72  6D 61 74 2E  0A 00 20 20  20 49 6E 76   format...   Inv
00000390   61 6C 69 64  20 70 61 64  64 69 6E 67  2E 0A 00 00  alid padding....
000003A0   20 20 20 43  61 6E 6E 6F  74 20 6F 70  65 6E 20 66     Cannot open f
000003B0   69 6C 65 20  70 61 79 6C  6F 61 64 2E  62 69 6E 2E  ile payload.bin.
000003C0   0A 00 3A 3A  20 44 65 63  72 79 70 74  65 64 20 70  ..:: Decrypted p
000003D0   61 79 6C 6F  61 64 20 77  72 69 74 74  65 6E 20 74  ayload written t
000003E0   6F 20 70 61  79 6C 6F 61  64 2E 62 69  6E 2E 0A 00  o payload.bin...
000003F0   70 61 79 6C  6F 61 64 2E  62 69 6E 00  58 58 58 58  payload.bin.XXXX


Ce qui permet de valider notre hypothèse sur le chiffrement utilisé.

- Le VM Dispatcher
----------------------------

L'analyse dynamique du code a révelé la présence du code suivant:
(La copie d'IDA n'est pas propre):
                                     MOV  X0, X19 ; param1
.text:0000000000402844                 BL              VM_Dispatcher ; x0             0x7fb7ffe000 --> la table des handlers + context (encryption key)
.text:0000000000402844                                         ; x1             0x3c 60
.text:0000000000402844                                         ; x2             0x7ffffff6f0
.text:0000000000402844                                         ; x/40xw $x2
.text:0000000000402844                                         ; 0x7ffffff6f0:0x00000048 0x00000000 0x00002101 0x00000001
.text:0000000000402844                                         ;
.text:0000000000402844                                         ; x3             0x4  4
.text:0000000000402848                 LDRB            W0, [X29,#0x5C] ; Load from Memory
.text:000000000040284C                 LDR             W1, [X29,#0x58] ; Load from Memory
.text:0000000000402850                 ADD             X0, X0, #0x6C ; x0             0x6d 109
.text:0000000000402854                 LDR             X2, [X19,X0,LSL#3] ; Load from Memory
.text:0000000000402858                 MOV             X0, X19 ; Rd = Op2
.text:000000000040285C                 BLR             X2      ; à la sortie du 9ème appel
.text:000000000040285C                                         ; x2 0x401490
.text:000000000040285C                                         ;
.text:000000000040285C                                         ; 0x400d9c
.text:000000000040285C                                         ; 0x401580
.text:000000000040285C                                         ;
.text:000000000040285C                                         ; après le message Wrong Key
.text:000000000040285C                                         ; 0x401794
.text:000000000040285C                                         ; 0x4005fc

Ce qu'il faut reteir ici à ce stade, est que cette fonction est appelée à l'exécution de chaque instruction de la VM. Cette dernière reçoit l'instruction de la VM àéxecuter et retourne l'adresse du 'Handler" qui permet de traduire le code de la VM vers le code de l'architecture arm 64 bits.


Les VM Handlers
----------------------------
(Par manque de temps je n'arriverai pas à détailler tout les handler voir l'idb IDA pour l'ensemble, je présente ici un seul mais la méthode reste la même)

exemple pour le Handler ADD
text:0000000000400934                 ORR             X19, X0, X0 ; Rd = Op1 | Op2
.text:0000000000400938                 BL              Fetch_Register_value ; Branch with Link
.text:000000000040093C                 MOV             W22, W0 ; Rd = Op2
.text:0000000000400940                 MVN             X0, X19 ; Rd = ~Op2
.text:0000000000400944                 UBFM            X1, X21, #0xC, #0xF ; Unsigned Bitfield Move
.text:0000000000400948                 MVN             X0, X0  ; param1
.text:000000000040094C                 BL              Fetch_Register_value ; Branch with Link
.text:0000000000400950                 ADD             W2, W0, W22 ; Rd = Op1 + Op2
.text:0000000000400954                 EOR             X0, X0, X19 ; Rd = Op1 ^ Op2
.text:0000000000400958                 MOV             W1, W20 ; Rd = Op2
.text:000000000040095C                 EOR             X19, X19, X0 ; Rd = Op1 ^ Op2
.text:0000000000400960                 EOR             X0, X19, X0 ; Rd = Op1 ^ Op2
.text:0000000000400964                 LDP             X21, X22, [SP,#0x20+var_s0] ; Load Pair
.text:0000000000400968                 ORR             X19, X0, X0 ; Rd = Op1 | Op2
.text:000000000040096C                 LDP             X19, X20, [SP,#0x20+var_10] ; Load Pair
.text:0000000000400970                 LDP             X29, X30, [SP+0x20+var_20],#0x30 ; Load Pair
.text:0000000000400974                 B               VM_update_register ; Branch

Pour l'opération ADD, la fonction nommée Fetch_Resgister récupère la valeur du premier registre dans W0 puis le deuxième appel de cette même fonction permet de récupérer la deuxième valeur. à l'offset .0000000000400950 indique la nature de l'opéreation (ADD). Enfin l'appel à la fonction VM_update_register permet de mettre à jour le registre résultat. On sait alors que l'instruction ADD a besoin d'un registre résultat  et deux registre opérandes.

Il est à noter que le début de chaque handler des opération de shift (UBFM à l'offset 400944) permettent à chaque fois de récupérer l'opcode de l'instruction puis les opérandes.

Les registres
------------------

L'analyse dynamique et l'étude la fonction précédente met en évidence l'utilisation de l'adresse mémoire 0x7fb7fed000. En effet cette dernière correpond au premier registre de la VM (nommé dans le decodeur reg0).


Pour déboguer la VM, un petit script gdb aidant à afficher le contenu des registres de la VM à chaque exécution:

define vv
cont
printf "Instruction --> %0.8x\n", *(0x7ffffff6f8)
printf "----------\n"
printf "Registers:\n"
printf "----------\n"
printf "reg1 : 0x%x ,  \t" , *(0x7fb7fed000)
printf "reg2 : 0x%x ,  \t" , *(0x7fb7fed004)
printf "reg3 : 0x%x ,  \t" , *(0x7fb7fed008)
printf "reg4 : 0x%x ,  \n" , *(0x7fb7fed00c)
printf "reg5 : 0x%x ,  \t" , *(0x7fb7fed010)
printf "reg6 : 0x%x ,  \t" , *(0x7fb7fed014)
printf "reg7 : 0x%x ,  \t" , *(0x7fb7fed018)


Ce qui donne comme sortie à chaque passage par le VM Dispatcher:

Registers:
----------
reg1 : 0x14 ,   reg2 : 0x2 ,    reg3 : 0x38a ,          reg4 : 0x14 ,
reg5 : 0x46 ,   reg6 : 0x0 ,    reg7 : 0x9fff ,         reg8 : 0x0 ,
reg9 : 0x8 ,    regA : 0x0 ,    regB : 0x80 ,   regC : 0x1fff ,
regD : 0x8000 ,         regE : 0x40c ,          regF : 0x0 ,    regF/PC : 2b4 ,
(gdb)

Breakpoint 5, 0x0000000000402860 in ?? ()
Instruction --> 0000001c
----------
Registers:
----------
reg1 : 0x14 ,   reg2 : 0x2 ,    reg3 : 0x38a ,          reg4 : 0x14 ,
reg5 : 0x46 ,   reg6 : 0x0 ,    reg7 : 0x9fff ,         reg8 : 0x0 ,
reg9 : 0x8 ,    regA : 0x0 ,    regB : 0x80 ,   regC : 0x1fff ,
regD : 0x8000 ,         regE : 0x40c ,          regF : 0x0 ,    regF/PC : 2b4 ,
[Inferior 1 (process 478) exited normally]
[sync] exit, sync finished


Le désassemblage du code de la VM
------------------------------------------------

Disposant des handlers(et implicitement les instructions) , le nombre des registres il est possible de s'attaquer au décodeur.
En utilisant l'outil AMOCO il a été possible de décoder le Byte code de la VM. Cet outil permet en autre de définir une nouvelle architecture. Dans le répertoire arch de l'outil amoco, on peut décrire l'architecture de la VM (voir vm.zip):

Le fichier env.py permet de décrire les registre de notre VM:
reg0   = reg('reg0',32)
reg1   = reg('reg1',32)
reg2   = reg('reg2',32)
reg3   = reg('reg3',32)
reg4   = reg('reg4',32)
reg5   = reg('reg5',32)
reg6   = reg('reg6',32)
reg7   = reg('reg7',32)
reg8   = reg('reg8',32)
reg9   = reg('reg9',32)

...

Le fichier spec_vm.py permet de décrire le décodage des instructions, ci-dessous le décodage des instructions nommées MOVh et MOVl:


@ispec("32[ IMM(20)  REG(4) {00} ]", mnemonic="MOVh")
@ispec("32[ IMM(20)  REG(4) {01} ]", mnemonic="MOVl")
def VM_MOV(obj,IMM,REG):
    src = env.cst(IMM,20)
    dst = env.R[REG]
    obj.operands = [dst,src]
    obj.type = type_data_processing

Et enfin le fichier "asm.py" permet de décrire le comportement de l'instruction, exemple pour 'MOVh':

def i_MOVh(i,fmap):
  fmap[pc] = fmap[pc]+i.length
  dst,src = i.operands
  fmap[dst[16:32]] = fmap(src)



Il est à noter que la taille des instructions des VMs est de 16 et 32 bits.
le fichier (test_vmbytecode.py) permet de décoder le byte code de la VM. le fichier (VM_disassembly.txt) correspond au fichier sortie.

- Analyse du code de la VM
--------------------------------------

On retrouve des informations cohérentes comme le code qui demande d'entrer la clé:
[0x40] 00 01 00 00  : MOVh reg1,0x0                                                
[0x44] 01 21 00 00  : MOVl reg1,0x2 //syscall number 2
[0x48] 00 02 00 00  : MOVh reg2,0x0
[0x4c] 01 12 00 00  : MOVl reg2,0x1 //file descriptor
[0x50] 00 03 00 00  : MOVh reg3,0x0
[0x54] 01 e3 32 00  : MOVl reg3,0x32e //(32e offset of str: : Please enter the decryption key: ) (len 0x24)

La vérification de la taille:
[0x7e] 02 05 00 00  : LDR reg5,0x0,0x0 // get value at @adr+disp (len of buffer read)
[0x82] 00 03 00 00  : MOVh reg3,0x0
[0x86] 01 03 01 00  : MOVl reg3,0x10
[0x88] 13 35        : SUB reg5,reg3 // compare len of buffer read with 0x10
[0x8c] 08 6a b4 02  : JMPNE reg5,reg3,0x2b4 // Jump at offset 0x2B4 if reg5 != reg3 @dispaly Wrong key format
la clé doit faire 16 caractères.

Le code suivant permet de verifier que la clé ne contient que les caractères hexadécimlmaux:
[0x90] 00 0f 00 00  : MOVh regF,0x0
[0x94] 01 0f 01 00  : MOVl regF,0x10 //16 len of the key
[0x98] 00 0e 00 00  : MOVh regE,0x0
[0x9c] 01 ce 3f 00  : MOVl regE,0x3fc //offset of str: XXXXXXXXXXXXXXXX)len :0x10
[0xa0] 00 0d 00 00  : MOVh regD,0x0
[0xa4] 01 6d 32 00  : MOVl regD,0x326
[0xa6] 17 0d        : DEC regD
[0xaa] 00 02 00 00  : MOVh reg2,0x0
[0xae] 01 02 03 00  : MOVl reg2,0x30 '0'
[0xb2] 00 03 00 00  : MOVh reg3,0x0
[0xb6] 01 93 03 00  : MOVl reg3,0x39 '9'
[0xba] 00 04 00 00  : MOVh reg4,0x0
[0xbe] 01 14 04 00  : MOVl reg4,0x41 'A'
[0xc2] 00 05 00 00  : MOVh reg5,0x0
[0xc6] 01 65 04 00  : MOVl reg5,0x46 'F'
[0xca] 04 ec 00 00  : LOADB regC, [regE] //RegC vaut 0x41,0x31,0x32 //c'est plutôt un load
[0xce] 02 01 2c 00  : LDR reg1,0x2c,0x0 //Load character by charcter


[0xd2] 13 21        : SUB reg1,reg2 '0'
[0xd4] 08 82 b4 02  : JMPL reg1,reg4,0x2b4 //Display Wrong key format
......
et  la partie suivante est la partie la plus intéressante car elle permet de déchiffrer le payload.bin avec la clé fourni (juste après le syswrite:

[0x15e] 1d 00        : INT 0x0 (sys_write)

:: Trying to decrypt payload..
-------------------------------------

[0x160] 00 01 00 00  : MOVh reg1,0x0
[0x164] 01 61 32 00  : MOVl reg1,0x326 //806
[0x168] 02 1a 00 00  : LDR regA,0x0,
.........
L'approche adoptée à ce stade pour comprendre ce code de prime à bord illisible et de produire un code équivalent mais dans un langage plus lisible (python c'est bon!):
(lfsr_crypto.py)
while (payload_len != 0):
    #print"key_part1 : 0x%x - key_part2 0x%x"%(key_part1,key_part2)
    #LFSR PRNG
    tmp1 = key_part1 & 0xb0000000
    tmp2 = key_part2 & 0x1
    tmp1 = tmp1 ^ tmp2

    print "tmp1 is %x"%tmp1  
    parity = Parity(tmp1)
    print"Parity is %x"%parity

    #Right Rotate
    tmp1 = (key_part1 & 0x1) << 0x1f
    key_part2 = (key_part2 >> 0x1) | tmp1

    tmp1 = key_part1  >> 0x1
    parity  = parity << 0x1f
    key_part1 = tmp1 | parity

    print"Keypart %x%x"%(key_part2,key_part1)
 
    compteur = compteur -1
    #print"Compteur is %x"%compteur
    tmp = (key_part2 & 0x1) << compteur
    #print"key_part2 :  %x "%tmp
    x  = x | tmp

puis une optimisation pour un registre 64 bits:
(voir lfsr_crypto_64.py)
while (payload_len != 0):
    #print"key_part1 : 0x%x - key_part2 0x%x"%(key_part1,key_part2)
    #LFSR PRNG
    tmp1 = key_part & 0xb000000000000001
    #tmp1  =  (tmp1 | (tmp1 >> 32)) & 0xffffffff
    print"tmp1 is %x"%tmp1
    parity = Parity(tmp1)
    print"Parity is %x"%parity
    #Left Rotate
    #tmp1 = (key_part & 0x1) << 0x3f
    #key_part = (key_part >> 0x1) | tmp1
    key_part = key_part >> 0x1
    parity  = parity << 0x3f
    key_part = key_part | parity
    print "Keypart %x"%key_part
    compteur = compteur -1
    #print"Compteur is %x"%compteur



Cette vue macro nous indique l’utilisation d'un algo de type LFSR à un seul état. Pour récupérer la clé de chiffrement il suffit de partir de l'état finale (récupéré depuis la section mémoire, retrouvé à la fin, déchiffré précedement à l'aide de l'algo chahcha).

le fichier lfsr_crypto_64_inverse.py permet de réaliser cette opération et récupérer la clé de chiffrement 0BADB10515DEAD11


Etape 3

A ce niveau on dispose d'un fichier upload.py qui permet d'envoyer un firmware (fw.hex) vers un microcontrôleur à distance.

Le format du microcontrôleur fournit correspond au format Intel Hex.

Sachant que le code du microcontrôleur n'a pas été fourni avec une documentation, il est souhaitable à ce stade de produire le décodeur qui permet de désassembler le code du firmware.
Cette analyse s'est déroulée en boite noire en utilisant la démarche suivante.
Modifier un octet du firmware et l'envoyer au serveur. Ce dernier retourne à chaque fois le message d'erreur suivant:

-- Exception occurred at 07D4: Invalid instruction.\n   r0:07D4     r1:0000    r2:0100    r3:00D4\n   r4:0700     r5:0000    r6:0000    r7:0000\n   r8:0000     r9:0000   r10:0000   r11:0000\n  r12:0000    r13:EFFE   r14:0000   r15:FD1C\n   pc:07D4 fault_addr:0000 [S:0 Z:0] Mode:kernel\nCLOSING: Invalid instruction.\n'

Le message est très clair permet d’identifier le nombre de registre (15 + le program counter).

En utilisant AMOCO, il a été possible de produire un décodeur (voir decodeur_fw.py).

Ci-dessous, un extrait du code désassemble (voir fw.code pour la totalité du code):
: [0x0000] 21 00  : movh r1,0x0
2: [0x0002] 11 1b  : movl r1,0x1b //
4: [0x0004] 20 01  : movh r0,0x1
6: [0x0006] 10 8c  : movl r0,0x8c //0x18C Firmware v1.33.7 starting.
8: [0x0008] c0 d2  : jmpl [ 0x8 + 0x0d2 + 2 : 0x dc] // jmp to syscall print

une attention à l’instruction jmpl (pour laquelle j'mis du temps à comprendre) comme certain contrôleur c'st un jmp link qui permet de stocker l’instruction de retour dans le regsitre r15.
Le code ci-dessus fait un apppel à la section du code 0xdc:
220: [0x00 dc ] c8 02  : jmpl 0x2,0x8 //syscall print
222: [0x00de] d0 0f  : Ret (jmp r15)

Les différents tests ont démontré que l'appel c8 02 correspond au syscall print (hypothèse) qui sera confirmée avec l'analyse du code kernel.

D'autre syscall vont être identifiées (comme le syscall exit et syscall write).

Pour le moment intéressons nous au syscall sys read. Des tests ont été effectués en remplaçant le code firmware correspondant au code désassemblé (ci-dessus) par les adresses et la taille des différents sections mémoires (Firmware, ummapped, RAM, secret memory HW registers et le kernel.

Ce test a permis de déterminer que toutes les sections sont en lecture sauf la section ummaped (ce qui est normal) et la secret memory.
Cependant, on dispose du code kernel (kernel.hex). En réutilisant le décodeur (écrit avec AMOCO) on arrive à désassembler le code du kernel (kernel.code).

La première vulnérabilité permet d'accéder en lecture à toutes les sections mémoires sauf la mémoire secrète:

Lorsqu'on demande la lecture de la mémoire secrète, on reçoit le message suivant:
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00[ERROR] Printing at unallowed address. CPU halted.\n'
Traceback (most recent call last):
  File "upload.py", line 56, in
    print(resp.decode("utf-8"))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 40: invalid start byte

Le message ci-dessus nous permet de localiser le code kernel produisant ce comportement:
65050: [0xfe1a] 21 00  : movh r1,0x0
65052: [0xfe1c] 11 33  : movl r1,0x33 //len of str
65054: [0xfe1e] 20 fe  : movh r0,0xfe
65056: [0xfe20] 10 26  : movl r0,0x26 // adr of str : [ERROR] Printing at unallowed address. CPU halted.\n
65058: [0xfe22] c3 c2  : jmpl 0xc2,0x3 [0xfde6] //fonction de printing
65060: [0xfe24] b3 02  : None

Cette fonction est appelée par une fonction un peu plus haut:
65018: [0xfdfa] 51 11  : and r1,r1,r1
65020: [0xfdfc] a0 1a  : None
65022: [0xfdfe] 69 e8  : add r9,r14,r8
65024: [0xfe00] 79 9c  : sub r9,r9,r12
65026: [0xfe02] a8 08  : None
65028: [0xfe04] 69 e8  : add r9,r14,r8
65030: [0xfe06] 79 9d  : sub r9,r9,r13
65032: [0xfe08] ac 02  : None
65034: [0xfe0a] b0 0e  : branch [0xfe1a]  if
65036: [0xfe0c] 39 99  : xor r9,r9,r9
65038: [0xfe0e] e9 e8  : loadb r9,r14,r8
65040: [0xfe10] f9 db  : storeb r9,r13,r11 //store dans HW registers
65042: [0xfe12] 68 8a  : add r8,r8,r10
65044: [0xfe14] 71 1a  : sub r1,r1,r10
65046: [0xfe16] b3 e2  : branch 0xfdfa if not zero
65048: [0xfe18] d0 0f  : ret r0

(note: il me reste quelque opcode que je n'ai pas écrit :)).
Le code ci-dessus (correspond au code du syswrite) vérifie à chaque l'adresse source avant de copier son contenu vers un HW registre (FC00), ce qui permet l'affichage.
Si l'adresse vaut F000 un saut vers le message d'erreur est alors enclenché.

Le deuxième syscall est celui du sys write
8: [0x0026] 20 11  : movh r0,0x11
40: [0x0028] 10 00  : movl r0,0x00
42: [0x002a] c0 b4  : jmpl [ 0x2a  + 0x0b4 + 2 : 0x e0] //syscall 03 syswrite
            //syswrite écrite 2093 (8339 cpu cycles) à l'adresse donnée
44: [0x002c] c0 b6  : jmpl [  0x2c + 0x0b6 + 2 : 0x e4]

Des tests visant à modifier l'adresse passée en paramètre à cette fonction permet d'avoir des erreurs indiquant des valeurs du pc différentes à chaque fois.

En analysant le code kernel de cette fonction elle s'est avéré qu'elle se charge d'écrire la valeur 0x2093 (8339) qui est le nombre de cycles d’exécution

Donc, la deuxième vulnérabilité quant à elle permet de rediriger le flux d’exécution du code kernel en contrôlant le paramètre en entrée du syscall 'write'

En manipulant le code du firmware on arrive à réduire le nombre de cycles


0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00-- Exception occurred at 07D4: Invalid instruction.\n   r0:07D4     r1:0000    r2:0100    r3:00D4\n   r4:0700     r5:0000    r6:0000    r7:0000\n   r8:0000     r9:0000   r10:0000   r11:0000\n  r12:0000    r13:EFFE   r14:0000   r15:FD1C\n   pc:07D4 fault_addr:0000 [S:0 Z:0] Mode:kernel\nCLOSING: Invalid instruction.\n'
Traceback (most recent call last):
  File "change_fw.py", line 75, in
    print(resp.decode("utf-8"))
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 46: invalid start byte

Le code suivant permet ansi de récupérer le contenu de la mémoire secrète
(voir fw_vuln.hex)

:1007C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA89
:1007D000AAAAAAAA210B11FF20F010002DFC1D00CF
:1007E0002CF02A001A013BBB388859885111E908BE
:1007F000F9DB688A711AB3F4000000000000000001

 VERY CHALLENGING\n\xe2\x94\x80\xe2\x96\x8c\xe2\x96\x80\xe2\x96\x90\xe2\x96\x84\xe2\x96\x88\xe2\x96\x84\xe2\x96\x88\xe2\x96\x8c\xe2\x96\x84\xe2\x96\x92\xe2\x96\x80\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x90\n\xe2\x96\x90\xe2\x96\x92\xe2\x96\x80\xe2\x96\x90\xe2\x96\x80\xe2\x96\x90\xe2\x96\x80\xe2\x96\x92\xe2\x96\x92\xe2\x96\x84\xe2\x96\x84\xe2\x96\x92\xe2\x96\x84\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x91\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x8c   SO OPERATIONAL\n\xe2\x96\x90\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x80\xe2\x96\x80\xe2\x96\x84\xe2\x96\x84\xe2\x96\x92



\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x84\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x8c <66a65dc050ec0c84cf1dd5b3bbb75c8c challenge.sstic.org="">\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x96\x80\xe2\x96\x84\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2



Game over

Sunday, April 15, 2012

HES 2012 the end !



Really, HES was just awesome, very technical with hot topics ...thanks a lot to the crew :) 

For those who want to see the video stream you can get it from here

Just get a glance time to time on HES web site to download the slides.

A french summary has been submitted by my team at this address:
http://www.devoteamblog.com/

HES 2012 day 3



Sorry, but I missed the keynote of the 3rd day. You can get the slides directly from HES web site.

Easy local Windows Kernel exploitation  by Cesar Cerrudo.


The goal of this presentation as expressed by Cerrudo is to show some simple tricks for windows exploitation vulnerability.
     
Before that, Cerrudo underlines that Windows exploitation still a dark art and there still few and good reliable kernel exploitation techniques.
Generally, for a specific vulnerability it can be possible to choose a specific value to write at a specific controlled kernel address.However, few techniques are generic and work across Windows Versions. 
Cerrudo pointed out that running code on kernel mode looking for and elevation of privilege could generates errors that cannot be caught for further analysis.

The current work of Cerrudo was inspired form  J00ru's paper "GDT and LDT In Windows Kernel".  This paper sheds lights on the following Windows API:
NtQuerySystemInformation (used by explorer to get information about process) allows to get the Kernel address of KPROCESS and returns  the 
struct_SYSTEM_HANDLE_TABLE_ENTRY_INFO {
   USHORT ProcessId
   ....

   PVOID Object // Kernel address
   } 
In Some wayss this structure helps to get Kernel information on any Windows in order to to execute an exploit. So what could be done then:

What if we can remove ACLs of almost Windows Object ?
What if we can set any privilges on a process token ? 
What if we can replace a process token ?

In all these cases, it is possible to do any of te above action with just one write. Indeed, Cerrudo stress on the fact that attackers are always looking for a system shell.
However, we don't need system shell for privilege escalation exploitation and that makes the exploitation easier.

The different techniques presented by Cerrudo could be summarized as below:
#1: Windows Object ACL 
kd> dt nt!_Object_HEADER
    0x000 PoinbterCount : INT 4B
     .....
    0x014 SecurityDescriptor : Prt32 information about the ACL (if you null out the field the object has no ACL any more )
    0x018 Body 
For that:
Get the target object (process....) kernel address using NtQuerySystemInformation 
Write NULL to [Object adr -0x14]
Manipulate the target object    

#2:Token privileges (Windows >Vista)
Typdef struct_TOKEN
 {
    typedef strruct_SEP_TOKEN_PRIVILEGES
  {
     UINT64 Present  
     UINT64 ENABLED; // all ones -- all privileges enabled 


...

#3:Token privileges (Windows XP et WINodws 2003) 
k>dt_TOKEN
+0x000 TokenSource      : _TOKEN_SOURCE

   +0x010 TokenId          : _LUID
   ...

If we can modify the Token it is possible to get powerful privileges as:
  • Debug programs
  • Take onwbership
  • Restore files and dir
  • Impersonate a client after auth
  • Load ad drivers
  • Create a token object
  • Act as part of the OS

    
So for Enabling privileges:
  • Get process primary token and then search its kernel address using NTquerySystemInormation
  • Write 0xFFFFFFFF (or the wanted value for the corresponding privileges) to TOKEN at +0x48 (0x14 Win XP)


to illustrate this technique, Cerrudo uses the exploit for Tarjei Mandt Kernel vulnerability(use after free) as below: 
dec dword ptr [eax +4]
    
if we can control only eax then is to hard to exploit , However in:
Windows XP  the default value is : TOKEN +0x48 == 0x80000000  
Win7 ==> 1000000000000 only one privilges i enabled by def SeChangeNotifyPrivileges

0x8000000-0x1 == 0x7FFFFFF ==> 1111111111111b lots of privileges 

#4:Process primary token
Typdef struct_EPROCESS (Win 7)
      { 
             Struct_EX_FAST_REF Token;

 kd>dt nt!_Object_HEADER

+x000 PointerCont   : Int4B

The goal here is to Replace  the process token by the system identity token by hooking NtOpenThreadToken and calling MsiInstallProduct then get the object kernel address using NtQuerySystemInfdo.
If multiple writes 
Increase reference count with first write to PinterCount [_TOKEN -0X18] (on 32) and the second write to replace Token on _EPROCESS with system token.
If one write
replace TOKEN on _EPROCESS, and after elevation and before exploit finishes duplicate the system token.

Conclusions
Exploiting some kernel vulnerabilities are made more easier using NTquerySystemInformation 
this API helps to build more reliable exploits
You don't need system shells to elevate our privileges

Just awesome ! thanks Cerrudo for this presentation ... 

Follow Cerrudo at @cesarcer



Yo Dawg I heard you like reversing by Aaron Portnoy & Brandon Edwards



All I could say concerning this talk is : ZDI team are just amazing. Indeed, in this talk they presented to us their IDA Toolbag.
So I won't give technical details about the tools for the simple reason that this latter contains a lot of features...


The speakers pointed out that during their job at ZDI they face a lot of problems due to some limitations in IDA Pro.
In consequence they decides to develop a  tool to mitigate these problems. For that, their tool include features into the following IDA modules: 


Data storage
Querying 
Navigation
Collaboration
...  




A demo of the ToolBag has been introduced by the speakers.


I suggest you to go and get a glance on the project : http://thunkers.net/~deft/code/toolbag/