0xEditbox – enforcing hex input

•2009/07/17 • Leave a Comment

For editboxes there’s a style ES_NUMBER which only allows decimal digits as input. Recently I needed that sort of functionality for hex digits. I also wanted the editbox to control text being posted from the clipboard and limit its size automatically according to the size of the variable it holds.

I ended up coding my own class template which subclasses the editbox to a window procedure that monitors all WM_CHAR, WM_PASTE and WM_SETTEXT messages. If the user tries to enter an invalid character it beeps and immediately returns without passing the message to the old window procedure.

Values are retrieved/updated using the member functions Get which returns a value of the type specified in the template instance and Set which takes a value of this type. You can additionally specify if output is zerofilled, which can be used to temporarily override the flag set in the constructor.

Usually you would declare it in your window/dialog procedure and create an instance once the edit box was created (e.g. WM_INITDIALOG or WM_CREATE after creating all child windows):

INT_PTR CALLBACK DlgHandler(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam)
{
static cHexEdit<DWORD> * AwesomeEdit, * AmazingEdit;
  switch(Message)
  {
  case WM_INITDIALOG:
    AwesomeEdit = new cHexEdit<DWORD>(GetDlgItem(Window, EdAwesome));
    AmazingEdit = new cHexEdit<DWORD>(GetDlgItem(Window, EdAmazing), true);
    break;
  case WM_COMMAND:
    switch(HIWORD(wParam))
    {
    case BTN_DOIT:
      DWORD Input, Output;
      Input = AwesomeEdit->Get();
      Output = Superfunkshun(Input);
      AmazingEdit->Set(Output);
      break;
    }
    break;
  case WM_DESTROY:
    delete AwesomeEdit;
    delete AmazingEdit;
    break;
  }
}

The maximum input size is limited by the type used in the template instance. If you specify BYTE, it allows up to 2 digits, 4 for WORD, 8 for DWORD, etc.

I wrote the conversion functions myself as didn’t want to deal with having to fiddle with format specifiers for sprintf and sscanf. Theoretically there’s no limit to the variable size. However, you can’t use floating point types. The conversion would probably work but the digit calculation is wrong, nothing that can’t be fixed though I guess ;)

I figured I’d put this here in case someone else needs something similar. WordPress.com doesn’t allow .h/.cpp/.txt files so I stuffed the code into a .doc file. Putting the code into this entry is not a good idea either since most of it wouldn’t be visible :|

Anyway, here’s the .doc:

cHexEdit.h.doc

SetThreadContext Fail on x64

•2009/07/02 • Leave a Comment

On all 64-bit versions of Windows I have been experiencing weird crashes with apps running in a debugger, caused by all sorts of access violations in ntdll. I figured it must have been my code doing something incorrectly which works on x86 but breaks on 64-bit Windows.

The exceptions would usually happen after the break at ntdll!DbgBreakPoint, somewhere around RtlUserThreadBase on Vista SP2. I even got DEP access violations at random memory addresses outside of ntdll. This behaviour seemed to be consistent on all 64-bit Windows versions. I got similar exceptions on XP SP2, Vista SP2 and Win7 RC1.

I was able to nail it down to a call to SetThreadContext which was responsible for setting the DRX registers. The code did nothing more than call GetThreadContext, set DR0 to DR3 + DR7 and call SetThreadContext. I suspected the DRX values to be corrupted, so I removed everything between the two APIs. Surprisingly, the error remained. When I just removed SetThreadContext, it worked flawlessly.

Since I didn’t need to read and update anything other than the debug registers, I set the context flags to CONTEXT_DEBUG_REGISTERS. Because I lacked any logical solutions I played around with the flags and tried CONTEXT_ALL. All of a sudden the exceptions were gone and the debuggee started up normally. Wow.

Turns out that combining CONTEXT_DEBUG_REGISTERS with any other valid flag fixes this problem.

Just to be sure, I added this piece of code to the CREATE_PROCESS_DEBUG_EVENT handler:

CONTEXT Context;
Context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
HANDLE Thread = Event.u.CreateProcessInfo.hThread;
GetThreadContext(Thread, &Context);
SetThreadContext(Thread, &Context);

This perfectly reproduced all the crashes I was experiencing before. Changing the second line to:

Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_DEBUG_REGISTERS;

made it work like a charm.

I had another bunch of DEP violations after every INT1 but didn’t realize it was the same problem. I forgot to adapt the flags for one piece of code which read and updated the debug registers after a hardware breakpoint or single step. After fixing that, I had a perfectly working debugger.

I can’t remember how much time I spent finding that stupid bug. Bill, you owe me big-time.

Hardware breakpoints on Windows

•2009/06/23 • 4 Comments

The Intel documentation on DRX breakpoints is at times confusing and complicated and (obviously) doesn’t really give a clue what the implementation on Windows looks like. This article hopefully clears up some of the issues you might be faced with while implementing hardware breakpoints in your debugger/application.

Note: this is not an introduction to the topic, nor to be used as a reference. For solid information get a copy of the “Intel 64 and IA-32 Architectures Software Developer’s Manual“, specifically Volume 3B (“System Programming Guide, Part 2″), Chapter 18 (“Debugging and Performance Monitoring”).

Local only

On Windows, only local hardware breakpoints work, ie. they only exist in a thread’s context, not system wide. Kinda makes sense considering each thread has its own set of registers. Global hardware breakpoints aren’t global to the process, but global to the whole system.

Windows will make sure you don’t enable system-wide breakpoints, at least more recent versions.

Basics

When a hardware breakpoint is hit, an EXCEPTION_SINGLE_STEP exception is raised. This is kind of confusing at first, but since both DRX breakpoints and single step are so called “debug exceptions” (which translates to INT1) it is the same type of exception.

You differentiate between the two by examining DR6. It’s possible for both to be reported in one event.

According to the Intel manual you have to clear DR6 after every debug exception. However, it looks like Windows does that for us. I would recommend clearing DR6 yourself though, because I’m not sure that this is guaranteed on all Windows versions (at least XP SP3 and Vista SP2 do clear it).

If the conditions specified in DR7 are fullfilled and one the breakpoints is triggered, you receive an EXCEPTION_SINGLE_STEP_EVENT. It’s possible that the exception is raised because of several simultaneous breakpoints. You will get seperate events for single step and hardware breakpoints on execution. This is not the case for single step and breakpoint on read/write and with breakpoints of the same type. The safe way is to examine all bits in DR6 and act accordingly. If 2 breakpoints are identical, DR6 reports both. Be aware that the bits for a breakpoint are set in DR6 even if the breakpoint is not enabled in DR7. To be perfectly sure, also check if the enable bit is set in DR7.

Since breakpoints on read/write are trap exceptions (ie. they break after the exception that caused the breakpoint to trigger) you can just continue execution. Breakpoints on execution are faults, they break before the instruction is executed. If you would just continue to execute, the breakpoint would trigger again as it executes the same address again and cause the breakpoint to trigger.

The fairly easy solution is to set the resume flag in the EFlags register (bit 16). It temporarily disables breakpoints on execution for one instruction. It doesn’t affect any other type of breakpoints.

If only it was that easy…

There is only one drawback which made me avoid this. VMWare (Workstation 6.5) seems to ignore or disable the trap flag so that you’ll never get past this instruction. This might be a minor issue to some people but many use VMWare for reverse engineering or just for running stuff you don’t necessarily want to run on your normal box.

I’m not sure if Virtual Box or other VMs are affected though.

Single step to the rescue!

Now, what else can we do? The only feasible solution is to disable the breakpoint in DR7, set the trap flag to break on the next instruction and re-enable it after the single step exception.

However, be aware that there might be more than 1 breakpoint you have to re-enable after a single step event.

Okay, summarizing, here’s some pseudo code:

// ... Awesome debug loop goes here ...
switch(Info->ExceptionRecord.ExceptionCode)
{
case EXCEPTION_SINGLE_STEP:
{
  GetContext(CONTEXT_DEBUG_REGISTERS);
  cDR6 DR6(Context.Dr6);
  cDR7 DR7(Context.Dr7);
  Context.Dr6 = DR6.Clear();
  SetContext();

  // Singlestep after last breakpoint(s)
  if(DR6.SingleStep)
  {
    if(CurBreaks.size()) // Re-enable breakpoints
    {
      do{
        CurBreaks.top()->Enable();
        CurBreaks.pop();
      }
      while(CurBreaks.size());
      Handled = true;
    }
  }
  // DRX breakpoints
  for(int i = 0; i < 4; i++)
  {
    if(DR6.DRX[i] && DR7.DRX[i].Enabled)
    {
      // You might want to check if this is a breakpoint you actually set
      CurBreak = cHardwareBreakpoints::Find(i);

      // ... Do whatever notification here ...

      if(DR7.DRX[i].Type == BpHwOnExec)
      {
        //SetResumeFlag(true); // Doesn't work in VMWare
        CurBreak->Disable();
        CurBreaks.push(CurBreak);
        SetSingleStep(true);
      }
      Handled = true;
    }
  }
}
break;
}

If you don’t mind breaking VMWare compatibility, you can remove the whole

if(DR6.SingleStep)

block, uncomment

SetResumeFlag(true);

and remove anything else inside that block.

What else?

A few things worth noting:

To enable a hardware breakpoint process-wide, you have to set the debug registers in every spawned thread.

If you temproarily disable the breakpoint, you only have to disable it in the current thread. Other threads still have their breakpoints enabled and break. This is different from, say, INT3 breakpoints which are enabled or disabled in the whole process (they require changed code after all).

I guess that’s it for the moment. I didn’t want to blow this up by showing how to enable breakpoints in DR7 or parsing DR6. I might post some source for doing that if I get round to cleaning up the code. For the time being, the Intel manual is your best friend :)

OutputDebugString awesomeness

•2009/06/22 • Leave a Comment

A program can communicate with a debugger by sending strings to it through the OutputDebugString API.

What happens then is that a ring3 debugger using the Windows Debug API will receive an OUTPUT_DEBUG_STRING_EVENT. Along with it, it receives relevant information about the debug string inside an OUTPUT_DEBUG_STRING_INFO struct.

First of all, some trivia:

Unicode? Yes? No?

OUTPUT_DEBUG_STRING_INFO contains a member called fUnicode:

fUnicode

The format of the debugging string. If this member is zero, the debugging string is ANSI; if it is nonzero, the string is Unicode.

Let’s look at what MSDN says about OutputDebugString:

OutputDebugStringW converts the specified string based on the current system locale information and passes it to OutputDebugStringA to be displayed. As a result, some Unicode characters may not be displayed correctly.

So we can’t actually receive any unicode debug strings. I assume this is a remainder from pre NT times as it’s officially unused according to the quote above.

Now back to the Debug API:

Exception? Yes? No?

To continue debugging, the debugger calls ContinueDebugEvent for that event. You additionally have to specify the continue status which can be either DBG_CONTINUE or DBG_EXCEPTION_NOT_HANDLED.

According to MSDN there is no difference between the two for events other than EXCEPTION_DEBUG_EVENT. Unfortunately that’s not right. There is another debug event for which it does make a difference. Yes you guessed correctly, a debug string event :D

OUTPUT_DEBUG_STRING_EVENT behaves just like an exception event, so that if you continue with DBG_EXCEPTION_NOT_HANDLED, it sends the event a second time, just like a second chance exception.

Recently I’ve been wondering why I got 2 debug string events for each call to OutputDebugString from the debuggee. I was looking for all sorts of weird solutions until I found out that returning DBG_CONTINUE did the trick.

Reason? Yes? No?

Internally, a debug string is handled as an exception. OutputDebugString calls RaiseException with DBG_PRINTEXCEPTION_C (defined as 0×40010006) and the string address and size as the exception parameters. To keep this transparent to the debugger, Windows effectively swallows the exception and notifies the debugger of it through the debug string notification.

All this is done inside DbgUiConvertStateChangeStructure inside the debugger which sets up and translates all the debug notification stuff.

This is even used as anti-debug code. You just set up an exception handler and call RaiseException with DBG_PRINTEXCEPTION_C. If a debugger is present the exception is swallowed, ie. if your exception handler does not get called, you’re being debugged.

As to why this is not affected by the continue status, I have no clue. It can, however, be fixed by patching DbgUiConvertStateChangeStructure to handle it like any other exception.

For pseudo source code for DbgUiConvertStateChangeStructure, you can take a look at OpenRCE. You can also see how the fUnicode member is set to false by default.

Bottom line, always continue with DBG_CONTINUE and ignore the fUnicode member :)