Archive for the ‘Random Tidbits’ Category

Building the Lego Millennium Falcon: A Lesson in Security?

Friday, January 25th, 2008

Not all of a reverse engineer’s life has to be about undoing — sometimes it is equally as fun to build something from scratch, whether that means a new tool… or the Star Wars 30 Year Anniversary Lego Ultimate Collector’s Millennium Falcon! Over the course of the last three weeks, my best friend and myself have spent countless hours building this magnificent model, which has over 5000 pieces, 91 “major” construction steps (with each step taking up to 30 sub-steps, sometimes 2x’d or 4x’d) and a landscape, 8×14″, 310 page instruction manual.

Late last night, we completed the final pieces of the hull, the radar dish, and the commemorative plaque (itself made of Lego). We had previously built the Imperial Star Destroyer (ISD) last year, but nothing in our Lego-building lives had ever quite come close to the work we put into this set. Complete full-size pictures after the entry.

Along the way, we both learnt some important facts about the Lego manufacturing process — for example, we had already noticed that in our ISD set had some extra pieces, and that other people’s sets had different extra pieces, however, we weren’t too sure what to make of it. This year however, due to the fact we were missing exactly half the number of lever pieces and 1×2 “zit” pieces, we did some extra digging.

The first that boggles many Lego builders of such large sets, is the arrangement of pieces within the bags. These pieces are not arranged in construction order. If you break all the bags and sort the pieces, there is nothing wrong with doing so! Whether or not that will save you time however, is up for discussion. We did do a small sorting, mostly to separate hull pieces from thick pieces from greebling pieces, and that did seem to help a lot. However, I wouldn’t recommend spending 5 hours sorting the pieces as was done on Gizmodo.

By step 21 unfortunately, we noticed we were missing a piece — something that Lego says should never happen (more on this shortly). Step 22 also required that piece, and the next few steps required even more. I came up with an interesting idea — a missing bag. We counted the number of pieces we’d still need, and it came up to be exactly the number of pieces we had used. In other words, half of the pieces were missing. Those pieces were in the same bag as the level-looking pieces, and those too, after calculations, were missing half their number. By this point, we were sure that we were missing a bag, and went to check Lego’s site for help.

It turns out that Lego’s site does have a facility available for ordering missing set pieces, and for free! After putting in the appropriate information, including the set number, and piece number, I filled out my address… and received a “Thank you”. Unfortunately, we never got any further confirmation, and the missing pieces have yet to arrive. Most interesting however, was a notice on Lego’s website, claiming that missing pieces are quite rare, because each set is precision-weighted, so missing sets get flagged for extra, human QA. At first sight, this makes it very unlikely for a set to be missing a piece — so how did we end up missing nearly 60 pieces? (Note to readers: the missing pieces are all hull greeblin (decorative, not structural), and we dully marked down the steps at which they were required, so we can add them once we receive them).

The answer to that question only came to us once we completed construction of the Falcon. There it was, on our workshop table (my kitchen table): an opened bag, full of Lego pieces… which we had already used up, and which weren’t required! It then became pretty obvious to us that Lego has a major flaw in their weight-based reasoning: replacement! We couldn’t scientifically verify it, but the extra bag we had was of similar size and weight (being small pieces) to the second bag of levels and 1×2 pieces we needed. Evidently, a machine error (most probably) or human error caused an incorrect bag of pieces to be added to the set. At the QA phase, the set passed the weight tests, because this bag was of the same (or nearly the same) weight as the missing bag!

Furthermore, due to the fact both the ISD and the Falcon had pieces that were not included in the Appendix of piece counts (again, probably due to machine error while composing the set), their combined weight may have even pushed the weight of our set past the expected weight. It is unlikely that Lego would flag heavier sets for QA — at worst, the customer would get some free pieces of Lego. However, when that weight helps offset the weight of missing pieces, it can certainly become a problem. And when a bag of pieces is accidentally replaced by a similar bag, then weight measuring doesn’t do much at all.

Granted, a lot of our analysis is based on assumptions, but they certainly do check out. Lego says their primary method of checking sets is to weigh them, and we have an extra bag, and a missing bag, both of similar size and composure. The hypothesis seems valid, and perhaps a phone call to Lego will confirm it (if I don’t get the pieces soon, I certainly plan on doing that).

Ironically, this breakage of a QA test through replacement was similar to an interesting security question I received by mail recently: why is it a bad idea to use the Owner SID of an object as a way to authenticate the object, or its creator? It turns out this can leave you vulnerable to rename operations, such as on a file with write and delete access, allowing someone to impersonate the Owner SID but have their own data in the object. Breaking a security test by renaming an object, or breaking a quality assurance test by replacing a bag — the two stem from the same problem: bad design and simplistic assumptions.

And now, without further ado, here’s a link to our construction pictures.

Behind Windows x64’s 44-bit Virtual Memory Addressing Limit

Saturday, November 3rd, 2007

The era of 64-bit computing is finally upon the consumer market, and what was once a rare hardware architecture has become the latest commodity in today’s processors. 64-bit processors promise not only a larger amount of registers and internal optimizations, but, perhaps most importantly, access to a full 64-bit address space, increasing the maximum number of addressable memory from 32-bits to 64-bits, or from 4GB to 16EB (Exabytes, about 17 billion GBs). Although previous solutions such as PAE enlarged the physically addressable limit to 36-bits, they were architectural “patches” and not real solutions for increasing the memory capabilities of hungry workloads or applications.

Although 16EB is a copious amount of memory, today’s computers, as well as tomorrow’s foreseeable machines (at least in the consumer market) are not yet close to requiring support for that much memory. For these reasons, as well as to simplify current chip architecture, the AMD64 specification (which Intel used for its own implementation of x64 processors, but not Itanium) currently only supports 48 bits of virtual address space — requiring all other 16 bits to be set to the same value as the “valid” or “implemented” bits, resulting in canonical addresses: the bottom half of the address space starts at 0×0000000000000000 with only 12 of those zeroes being part of an actual address (resulting in an end at 0×00007FFFFFFFFFFF), while the top half of the address space starts at 0xFFFF800000000000, ending at 0xFFFFFFFFFFFFFFFF.

As you can realize, as newer processors support more of the addressing bits, the lower-half of memory will expand upward, towards 0×7FFFFFFFFFFFFFFF, while the upper-half of memory will expand downward, toward 0×8000000000000000 (a similar split to today’s memory space, but with 32 more bits). Anyone working with 64-bit code ought to be very familiar with this implementation, since it can have subtle effects on code when the number of implemented bits will grow. Even in the 32-bit world, a number of Windows applications (including system code in Windows itself) assume the most significant bit is zero and use it as a flag — clearly the address would become kernel-mode, so the application would mask this bit off when using it as an address. Now developers get a shot at 16 bits to abuse as flags, sequence numbers and other optimizations that the CPU won’t even know about (on current x64 processors), on top of the usual bits that can be assumed due to alignment or user vs kernel-mode code location. Compiling the 64-bit application for Itanium and testing it would reveal such bugs, but this is beyond the testing capabilities of most developers.

Examples within Microsoft’s Windows are prevalent — pushlocks, fast references, Patchguard DPC contexts, and singly-linked lists are only some of the common Windows mechanisms which utilize bits within a pointer for non-addressing purposes. It is the latter of these which is of interest to us, due to the memory addressing limit it imposed on Windows x64 due to a lack of a CPU instruction (in the initial x64 processors) that the implementation required. First, let’s have a look at the data structure and functionality on 32-bits. If you’re unsure on what exactly a singly-linked list is, I suggest a quick read in an algorithm book or Google.

Here is the SLIST_HEADER, the data structure Windows uses to represent an entry inside the list:

typedef union _SLIST_HEADER {
    ULONGLONG Alignment;
    struct {
        SLIST_ENTRY Next;
        USHORT Depth;
        USHORT Sequence;
    } DUMMYSTRUCTNAME;
} SLIST_HEADER, *PSLIST_HEADER;

Here we have an 8-byte structure, guaranteed to be aligned as such, composed of three elements: the pointer to the next entry (32-bits, or 4 bytes), and depth and sequence numbers, each 16-bits (or 2 bytes). Striving to create lock-free push and pop operations, the developers realized that they could make use of an instruction present on Pentium processors or higher — CMPXCHG8B (Compare and Exchange 8 bytes). This instruction allows the atomic modification of 8 bytes of data, which typically, on a 486, would’ve required two operations (and thus subjected these operations to race conditions requiring a spinlock). By using this native CPU instruction, which also supports the LOCK prefix (guaranteeing atomicity on a multi-processor system), the need for a spinlock is eliminated, and all operations on the list become lock-free (increasing speed).

On 64-bit computers, addresses are 64-bits, so the pointer to the next entry must be 64-bits. If we keep the depth and sequence numbers within the same parameters, we require a way to modify at minimum 64+32 bits of data — or better yet, 128. Unfortunately, the first processors did not implement the essential CMPXCHG16B instruction to allow this. The developers had to find a variety of clever ways to squeeze as much information as possible into only 64-bits, which was the most they could modify atomically at once. The 64-bit SLIST_HEADER was born:

struct {  // 8-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:9;
        ULONGLONG NextEntry:39;
} Header8;

The first sacrifice to make was to reduce the space for the sequence number to 9 bits instead of 16 bits, reducing the maximum sequence number the list could achieve. This still only left 39 bits for the pointer — a mediocre improvement over 32 bits. By forcing the structure to be 16-byte aligned when allocated, 4 more bits could be won, since the bottom bits could now always be assumed to be 0. This gives us 43-bits for addresses — we can still do better. Because the implementation of linked-lists is used *either* in kernel-mode or user-mode, but cannot be used across address spaces, the top bit can be ignored, just as on 32-bit machines: the code will assume the address to be kernel-mode if called in kernel-mode, and vice-versa. This allows us to address up to 44-bits of memory in the NextEntry pointer, and is the defining constraint of Windows’ addressing limit.

44 bits is nothing to laugh at — they allow 16TB of memory to be described, and thus splits Windows into somewhat two even chunks of 8TB for user-mode and kernel-mode memory. Nevertheless, this is still 16 times smaller then the CPU’s own limit (48 bits is 256TB), and even farther still from the maximum 64-bits. So, with scalability in mind, there do exist some other bits in the SLIST_HEADER which define the type of header that is being dealt with — because yes, there is an official 16-bit header, written for the day when x64 CPUs would support 128-bit Compare and Exchange (which they now do). First, a look at the full 8-byte header:

 struct {  // 8-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:9;
        ULONGLONG NextEntry:39;
        ULONGLONG HeaderType:1; // 0: 8-byte; 1: 16-byte
        ULONGLONG Init:1;       // 0: uninitialized; 1: initialized
        ULONGLONG Reserved:59;
        ULONGLONG Region:3;
 } Header8;

Notice how the “HeaderType” bit is overlaid with the Depth bits, and allows the implementation and developers to deal with 16-byte headers whenever they will be put into use. This is what they look like:

 struct {  // 16-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:48;
        ULONGLONG HeaderType:1; // 0: 8-byte; 1: 16-byte
        ULONGLONG Init:1;       // 0: uninitialized; 1: initialized
        ULONGLONG Reserved:2;
        ULONGLONG NextEntry:60; // last 4 bits are always 0’s
 } Header16;

Note how the NextEntry pointer has now become 60-bits, and because the structure is still 16-byte aligned, with the 4 free bits, leads to the full 64-bits being addressable. As for supporting both these headers and giving the full address-space to compatible CPUs, one could probably expect Windows to use a runtime “hack” similar to the “486 Compatibility Spinlock” used in the old days of NT, when CMPXCHG8B couldn’t always be assumed to be present (although Intel implemented it on the 586 Pentium, Cyrix did not). As of now, I’m not aware of this 16-byte header being used.

So there you have it — an important lesson not only on Windows 64-bit programming, but also on the importance of thinking ahead when making potentially non-scalable design decisions. Windows did a good job at maintaining capability and still allowing expansion, but the consequences of attempting to use parts of the non-implemented bits in current CPUs as secondary data may be hard to detect once your software evolves to those platforms — tread carefully.

Some Vista Tips & Tricks

Friday, September 21st, 2007

Here’s a couple of various useful tips I’ve discovered (as I’m sure others have) which make my life easier on Vista, and saved me a lot of trouble.

Fix that debugger!

I had done everything right to get local kernel debugging to work: I added /DEBUG with bcdedit. I used WinDBG in Administrator mode, I even turned off UAC. I made sure that all the debugging permissions were correct for admin accounts (SeDebugPrivilege). I made sure the driver WinDBG uses was extracted. Nothing worked! For some reason, the system was declaring itself as not having a kernel debugger enabled. I searched Google for answers, and found other people were experiencing the same problem, including a certain “Unable to enable kernel debugger, NTSTATUS 0xC0000354 An attempt to do an operation on a debug port failed because the port is in the process of being deleted” error message.

Here’s what I did to fix it:

  1. I used bcdedit to remove and re-add the /debug command: bcdedit /debug off then bcdedit /debug on
  2. I used bcdedit to force the debugger to be active and to listen on the Firewire port: bcdedit /dbgsettings 1394 /start active
  3. I used bcdedit to enable boot debugging: bcdedit /bootdebug
  4. I rebooted, and voila! I was now able to use WinDBG in local kernel debugging mode.

Get the debugger state

In Vista, one must boot with /DEBUG in order to do any local kernel debugging work, and as we all know, this disables DVD and high-def support to “ensure a reliable and secure playback environment”. After a couple of days work, I find myself sometimes forgetting if I had booted in debug mode or not, and I don’t want to start WinDBG all the time to check — or maybe you’re in a non-administrative environment and don’t want to use WinDBG. It’s even possible a new class of malware may soon start adding /DEBUG to systems in order to better infiltrate kernel-mode. Here’s two ways to check the state:

  1. Navigate to HKLM\System\CurrentControlSet\Config and look at the SystemStartOptions. If you see /DEBUG, the system was booted in debugging mode. However, because it may have been booted in “auto-enable” mode, or in “block enable” mode (in which the user can then enable/disable the debugger at his will), this may not tell you the whole story.
  2. Use kdbgctrl, which ships with the Debugging Tools for Windows. kdbgctrl -c will tell you whether or not the kernel debugger is active right now.

What would be really worthwhile, is to see if DVD playback works with /DEBUG on, but kernel debugging disabled with kdbgctrl, and if it stops playing (but debugging works) if kdbgctrl is used to enable it.

Access those 64-bit system binaries from your 32-bit app

I regularly have to use IDA 64 to look at binaries on my Vista system, since I’m using the 64-bit edition. Unfortunately, IDA 64 itself is still a 32-bit binary, which was great when I had a 32-bit system, but not so great anymore. The reason is WOW64’s file redirection, which changes every access to “System32″ to “SysWOW64″, the directory containing 32-bit DLLs. But IDA 64 is perfectly able (and has to!) handle 64-bit binaries, so there wasn’t an easy way to access those DLLs. Unfortunately, it looks like the IDA developers haven’t heard of Wow64DisableFsRedirection, so I resorted to copying the binaries I needed out of the directory manually.

However, after reverse engineering some parts of WOW64 to figure out where the WOW64 context is saved, I came across a strange string — “sysnative”. It turns out that after creating (with a 64-bit app, such as Explorer) a “sysnative” directory in my Windows path, any 32-bit application navigating to it will now get the “real” (native) contents of the System32 directory! Problem solved!

So there you have it! I hope at least one of these was useful (or will be), and feel free to share your own!

Introducing Haute Secure

Friday, July 6th, 2007

For the last couple of months I’ve had the chance to meet and work with some of the brightest developers and people behind what I think is a pretty revolutionary way to secure the online experience of users: the team behind Haute Secure.

In short, Haute Secure is a Malware Filter, much like a Phishing or Spam Filter in existing applications. It provides a beautiful (you really have to see it!) interface and toolbar to IE (and soon Firefox) which protects users from incoming malware on a variety of levels, starting from the site level to the execution level. If cnn.com were to be hacked tomorrow with an unreleased exploit that would attempt to download a worm or other malware on visitors’ machines, Haute would be able to detect that, and block the exploit from happening. When this happens, Haute will communicate with its servers and post a notification, so a site becomes known “bad” as users stumble upon it. But Haute doesn’t only rely on its users; it also ships with a very large database of malicious sites out there. Haute is also smart enough to avoid tagging an entire domain as “bad”. Many sites such as MySpace, Yahoo and others can host individual user content, and don’t deserve to be blacklisted due to certain sub-sites. Haute can blacklist only certain parts of a domain, such as a user’s site, and will also tag the site with a warning, to let users know that -some- pages may be dangerous.

Sandi did a pretty good review of the product on her blog, but as someone whose actually worked on the product and had intimate knowledge of its behavior (as well as having worked on similar products in the past), I’d like to give my own technical review and why I think Haute is way ahead of the pack when it comes to this market.

The first reason I love this product so much is because unlike almost all anti-virus products, firewalls and IPS software, it’s actually written to properly interface with the OS. It’s fully compatible with Vista, even 64-bits, and co-exists with PatchGuard and other integrity mechanisms. The driver behind Haute Secure (and yes, it’s a driver, not a collection of user-mode hooking DLLs!) makes use of all the filtering technology available in NT without sacrificing functionality.

The second thing that I think is exciting about Haute is the fact that it strongly relies on a community of users, and not on hard-coded rules or filters (although, like I said, it does come with a large database already). I used to work on a product called SPAMfighter ages ago, and I saw how filtering spam became much more powerful when it was driven by people’s reponses, and not by AI. Of course, Haute also must implement some smart algorithms if it thinks a site is legitimate, to perform correctly in the case where malware is being installed through an exploit. Finally, Haute also has the ability to allow users to report false positives. Because of this user input, which even includes an entire community site where users can compete against each others in terms of number of bad sites reported, Haute can respond much quicker to malicious websites, and de-blacklist fixed sites much quicker as well.

Last but not least, Haute is being worked on and designed by some very bright people with extensive experience in this area. As I said earlier, I’ve also had the chance to contribute some knowledge and code into the product, and I felt that the design was very solid and ready to be extended to other products if that path will ever open. It’s one of the reasons why Firefox support is something being worked on, and shows that Haute isn’t in any way hacked around IE.

While some of the ideas and concepts behind Haute may have been attempted by other companies and products before, I really feel that Haute has all the right stuff it needs to be user friendly, powerful, and pro-active in protecting its users. The community-centric approach will also surely pay off into making an even better product. In many ways, I see it as the iPhone of its kind (if you agree with me that the iPhone is a success story).

A New Direction

Tuesday, June 5th, 2007

It is with great excitement (and a certain amount of nostalgia) that I would like to announce two important changes in my professional life and in the direction in which I will pursue my knowledge and work on Windows Internals. The first of these changes is my debut as an instructor for David Solomon’s Expert Seminars, and the second is my departure from ReactOS, effective immediately. These plans do not change in any way my internship at Apple which will take place during the summer.

Some time ago, I had the great privilege of being approached by David Solomon, a well-known and highly regarded computer expert, teacher, consultant and co-author of Windows Internals 4th Edition (and Inside Windows 2000, 3rd Edition). For the last couple of years, David had been working with Mark Russinovich, another respected figure in the world of Windows Internals, and co-founder of Winternals and Sysinternals as well as developer of some of the most useful Windows system tools available today. Apart from working on the two books (which Mark was a co-author of), they both provided trainings and seminars on Windows internals under the “David Solomon Expert Seminars” banner. As is widely known, Microsoft realized that Mark’s experience and amazing work on the NT platform through his articles and tools could provide a highly beneficial new addition to the company. The company bought Winternals last year, and hired Mark at the highest technical level in the company, Technical Fellow. 

All this is history of course, and back to the matter at hand, Mark’s recent new employment made him unavailable for teaching new classes, which made David Solomon start the search for a new instructor which could take on the responsibility of teaching new classes. I was highly honoured to have been chosen as this person, and accepted this unique opportunity to bring my knowledge out to many more people and to work with one of my most admired Windows experts

With this new job as an added task on top of my already busy life, as well as with the imminent Apple internship, I was already planning to cut back on my involvement with ReactOS. However, since it became clear that my level of contact with Microsoft employees and resources would be in conflict with my work at ReactOS, I made the difficult choice of amicably severing my ties with the project. This decision took some time for me to finalize, but the various motivations behind it had started cropping up since early this year

When I first joined ReactOS 3 years ago, the kernel was – in my opinion – highly disorganized and hodgepodge of Linux, NT 4, Wine and Windows 9x code which was very far from its actual goal of NT Driver compatibility. In fact, the development model seemed to focus on hacking NT drivers to work on ReactOS, and not vice-versa. Coincidentally, I joined the project just as the lead kernel developer, David Welch, had just burnt out and moved to other projects and goals. For the last three years, I rewrote key subsystems such as the thread scheduler, dispatcher, locking and IRQL mechanisms, HAL, executive support, object manager, process manager, I/O manager, basic VDM and 8086 support, and much more, as well as switched the project goals from NT4 to NT 5.2. 

My ability to do this came from my extensive reverse engineering of the kernel in the past, reading internals books, access to the DDK/IFS, as well as using WinDBG and .pdb type information. In return for all the code and guidance I provided, the project gave me a lot in return as well, including a unique perspective of working on such a project, the ability to work in large and distributed teams, and using open source tools for Windows NT kernel development. With millions of lines of code, ReactOS is the kind of project that an 18 year old could’ve only dreamt work ing on. I became adept in source control repositories, regression testing, unit testing, team management, IRC administration, as well as a much better coder in C. I also made friendships of all levels with various developers, testers and users, and had a chance to mentor two students during last year’s Google Summer of Code. I was able to attend and give talks on ReactOS, exhibit it, and make connections with other people in the industry, and in the open source world. Overall, it’s been an exhilarating adventure.

After three years however, and with the many new responsibilities that had kept growing, my free time grew short. Additionally, my work in the kernel had almost reached completion. The parts that still need major work, in my opinion, require extremely skilled developers in those areas to ever be as close to NT as needed. They are also some of the most critical: the memory manager, the cache manager, the Power/PnP Manager, the configuration manager and the file system runtime library. With the current differences that exist, most modern WDM drivers as well as IFS drivers can only dream of running properly. Unfortunately, my knowledge in those areas was limited. I had never reverse engineered them as extensively as parts of the executive, and documentation on their guts is limited.  In all honesty, they’re also not parts of the system that interest me much. I could, of course, have continued working on user-mode parts of the system where my help would still bring a lot of the system forward, such as ntdll, csrss, smss, winsock and kernel32, but my interest in teaching with David Solomon and getting in touch with the developers behind NT outweighed that desire.

After three years, I learned a tremendous amount of knowledge and skills while working on ReactOS, now the time has come for me to learn even more by expanding my horizons. In many ways, I had already outgrown the project, focusing more on security research, utilities and tools, articles and non-ReactOS related talks and conferences. It was time for me to step outside and take on a new opportunity with a larger audience and which would bring me many new experiences and teachings. I wish the ReactOS Project all the luck and I know that some significant new changes are on the horizon for them. I will keep watching from a distance, and I thank them for the most fun years of my life.

This blog will continue as usual, and I am currently working on the fourth part of the SDB series. Thank you for your continued readership and support!

New Object Manager Filtering APIs

Tuesday, May 8th, 2007

The new bits of the WDK have been released, and it seems that finally, we are starting to see a glimpse of some of the new filtering technologies that were promised in Vista SP1 to help with incompatibilities due to PatchGuard. Although Vista added powerful Registry filtering support on top of the existing File filtering architecture, hooking some native calls would still have been necessary in order to filter other kinds of system behaviour. The first which seems to have been addressed are handles, and Vista SP1 now supports Object Manager Filters.

Currently, only create and duplicate can be filtered, but the ability for both pre and post notifications exist. As with the new filter model, Object Manager Filters also support Altitudes, and are fully versionned. Unfortunately, this new set of APIs seems rather disappointing to me. For starters, this functionality was already available, even behind Patchguard’s back, through native Object Manager callbacks present in the OBJECT_TYPE’s ObjectTypeInitializer structure which contains all the callbacks for the object type. This interface seems to do nothing more but expose in a more public and accessible way the same ObCreateMethod interface that has existed since NT4, except that it only works for create and duplicate (while the internal interface allows for open and inherit as well).

Nevertheless, this new filtering mechanism is clearly written to be extensible for other Object Manager actions, so hopefully we’ll see some new improvements before SP1 actually ships. For the curious, here are some of the new toys to play with:

//
// Registration version for Vista SP1 and Windows Server 2007
//
#define OB_FLT_REGISTRATION_VERSION_0100  0×0100

//
// This value should be used by filters for registration
//
#define OB_FLT_REGISTRATION_VERSION OB_FLT_REGISTRATION_VERSION_0100

typedef ULONG OB_OPERATION;

#define OB_OPERATION_HANDLE_CREATE              0×00000001
#define OB_OPERATION_HANDLE_DUPLICATE           0×00000002

typedef struct _OB_PRE_CREATE_HANDLE_INFORMATION {
    __inout ACCESS_MASK         DesiredAccess;
    __in ACCESS_MASK            OriginalDesiredAccess;
} OB_PRE_CREATE_HANDLE_INFORMATION, *POB_PRE_CREATE_HANDLE_INFORMATION;

typedef struct _OB_PRE_DUPLICATE_HANDLE_INFORMATION {
    __inout ACCESS_MASK         DesiredAccess;
    __in ACCESS_MASK            OriginalDesiredAccess;
    __in PVOID                  SourceProcess;
    __in PVOID                  TargetProcess;
} OB_PRE_DUPLICATE_HANDLE_INFORMATION, * POB_PRE_DUPLICATE_HANDLE_INFORMATION;

typedef union _OB_PRE_OPERATION_PARAMETERS {
    __inout OB_PRE_CREATE_HANDLE_INFORMATION        CreateHandleInformation;
    __inout OB_PRE_DUPLICATE_HANDLE_INFORMATION     DuplicateHandleInformation;
} OB_PRE_OPERATION_PARAMETERS, *POB_PRE_OPERATION_PARAMETERS;

typedef struct _OB_PRE_OPERATION_INFORMATION {
    __in OB_OPERATION           Operation;
    union {
        __in ULONG Flags;
        struct {
            __in ULONG KernelHandle:1;
            __in ULONG Reserved:31;
        };
    };
    __in PVOID                         Object;
    __in POBJECT_TYPE                  ObjectType;
    __out PVOID                        CallContext;
    __in POB_PRE_OPERATION_PARAMETERS  Parameters;
} OB_PRE_OPERATION_INFORMATION, *POB_PRE_OPERATION_INFORMATION;

typedef struct _OB_POST_CREATE_HANDLE_INFORMATION {
    __in ACCESS_MASK            GrantedAccess;
} OB_POST_CREATE_HANDLE_INFORMATION, *POB_POST_CREATE_HANDLE_INFORMATION;

typedef struct _OB_POST_DUPLICATE_HANDLE_INFORMATION {
    __in ACCESS_MASK            GrantedAccess;
} OB_POST_DUPLICATE_HANDLE_INFORMATION, * POB_POST_DUPLICATE_HANDLE_INFORMATION;

typedef union _OB_POST_OPERATION_PARAMETERS {
    __in OB_POST_CREATE_HANDLE_INFORMATION       CreateHandleInformation;
    __in OB_POST_DUPLICATE_HANDLE_INFORMATION    DuplicateHandleInformation;
} OB_POST_OPERATION_PARAMETERS, *POB_POST_OPERATION_PARAMETERS;

typedef struct _OB_POST_OPERATION_INFORMATION {
    __in OB_OPERATION  Operation;
    union {
        __in ULONG Flags;
        struct {
            __in ULONG KernelHandle:1;
            __in ULONG Reserved:31;
        };
    };
    __in PVOID                          Object;
    __in POBJECT_TYPE                   ObjectType;
    __in PVOID                          CallContext;
    __in NTSTATUS                       ReturnStatus;
    __in POB_POST_OPERATION_PARAMETERS  Parameters;
} OB_POST_OPERATION_INFORMATION,*POB_POST_OPERATION_INFORMATION;

typedef enum _OB_PREOP_CALLBACK_STATUS {
    OB_PREOP_SUCCESS
} OB_PREOP_CALLBACK_STATUS, *POB_PREOP_CALLBACK_STATUS;

typedef OB_PREOP_CALLBACK_STATUS
(*POB_PRE_OPERATION_CALLBACK) (
    __in PVOID RegistrationContext,
    __inout POB_PRE_OPERATION_INFORMATION OperationInformation
    );

typedef VOID
(*POB_POST_OPERATION_CALLBACK) (
    __in PVOID RegistrationContext,
    __in POB_POST_OPERATION_INFORMATION OperationInformation
    );

typedef struct _OB_OPERATION_REGISTRATION {
    __in POBJECT_TYPE                *ObjectType;
    __in OB_OPERATION                Operations;
    __in POB_PRE_OPERATION_CALLBACK  PreOperation;
    __in POB_POST_OPERATION_CALLBACK PostOperation;
} OB_OPERATION_REGISTRATION, *POB_OPERATION_REGISTRATION;

typedef struct _OB_CALLBACK_REGISTRATION {
    __in USHORT                     Version;
    __in USHORT                     OperationRegistrationCount;
    __in UNICODE_STRING             Altitude;
    __in PVOID                      RegistrationContext;
    __in OB_OPERATION_REGISTRATION  *OperationRegistration;
} OB_CALLBACK_REGISTRATION, *POB_CALLBACK_REGISTRATION;

#if (NTDDI_VERSION >= NTDDI_VISTASP1)
NTKERNELAPI
NTSTATUS
ObRegisterCallbacks (
    __in POB_CALLBACK_REGISTRATION CallbackRegistration,
    __deref_out PVOID *RegistrationHandle
    );

NTKERNELAPI
VOID
ObUnRegisterCallbacks (
    __in PVOID RegistrationHandle
    );

NTKERNELAPI
USHORT
ObGetFilterVersion ();
#endif

Interviewing at Apple, Google and Microsoft

Friday, March 16th, 2007

As some of you may or may not know, I’ve spent the last few weeks interviewing with the big three, and drove myself crazy choosing which offer to select (to be fair, I just finished interviewing with MSFT today; the offer, if any, will only come on Monday, when I make my big choice).

For the benefit of everyone, I decided that once my decision is made, I’d post more information about the process at all the three companies. How were the recruiters, the interviewers, the kind of perks to expect (yes we all know Google has free food), and more. I hope it’ll be a good write-up and perhaps end up with a chart, much like the Google/Yahoo/Windows Live(MSFT) blog post ended up.

It’s been great interviewing with all three though, and if anyone from there is reading this, thank you for everything!

Vista DRM Issue Aftermath

Tuesday, March 6th, 2007

I received word from Microsoft today on the status of the Vista DRM Issue that I talked about earlier. It seems that the final consensus from their internal investigation is that my method does not constitute a viable means of exploting the driver signing/DRM model. In other words, the theory I came up with that might allow PMP to be subverted seems to have been proven false.

My original idea was to use boot Vista with the /DEBUG flag and then use the internal, undocumented Kernel-Mode Debug API to load executable code in kernel-memory or to overwrite existing code (as well as to disable PatchGuard). My rationale was that PMP wouldn’t detect any issues, since no unsigned code was running in the kernel, instead, you would have code hidden in Non Paged Pool or as part of \Driver\Null’s IOCTL routine (similarly to how Johanna loaded code using the pagefile.sys). However, it seems this won’t work, I’m assuming because PMP will actually detect that you’ve booted in Debug Mode, and it will enter reduced functionality mode (Which was the hypothesis on which the entire idea depended on). Since I don’t know more about PMP, I’m not sure if this is what happens, but that’s my personal guess. Either ways, it seems DRM is here to stay for now.

Speaking of reduced functionality mode, if you turn of the Secured Licensing Service (SLsvc) in Vista, the Control Panel and Windows Update stop working. I was disabling services to get a minimalstic Vista desktop (I don’t like booting with 50 processes on startup), and I didn’t care about this service, disabling it and assuming PMP would block me from playing BluRay/HDDVD (Which I don’t have)… but I never guessed it would kill the Control Panel. Seems kinda weird.

When I get back home, I”ll post a list of the only services that I’m running on Vista. It’s got all the functionality I need (Internet, Printing, Audio). I’m getting a new hard drive for my server tonight, as well as ugprading my main desktop CPU from an AMD64 X2 3800+ to an Opteron 185. That’s a jump from 2×2GHz, 1MB Cache to 2×2.6GHz, 2MB cache. I’m hoping to overclock to 2.8GHz. Do NOT get an FX-60. They’re the exact same chip, but they cost twice as more.

Rebooting from Kernel Mode

Friday, February 16th, 2007

I see this question posted on OSR Online a lot: “How do I force a reboot of the computer from kernel mode?”. The clean solution always being recommended is to have a user-mode service that talks to the driver and does the appropriate ExitWindowsEx API call. But what if you really want to do it from kernel-mode? Well, you could use HalReturnToFirmware or NtShutdownSystem, but those functions are undocumented, and you probably won’t get WHQLed if you try using them. So I’ll show you a sneaky way that does the same, but uses a fully documented kernel API. Don’t use it unless you really know what you’re doing; I personally recommend using a service as well.

Rebooting a machine from kernel mode:

KeBugCheck(POWER_FAILURE_SIMULATE);

Now, I know what you’re thinking, but you’re wrong. This will *not* bugcheck the machine. It will actually call HalReturnToFirmware(HalRebootMachine), right after processing bugcheck callbacks. No BSOD, no crash dump, just a clean, simple, immediate reboot.

Enjoy ;)

WordPress 2.1 Server Upgrade

Tuesday, February 6th, 2007

I’ve just updated the server to WordPress 2.1, so please let me know if you see any weird errors or unexpected behavior!