September 9, 2012

Using Windbg as Hex Editor

This blog post discusses the idea to use Windbg as hex editor. It consists of the followings: the advantage of using this approach, and the initial steps to getting started. Possible risks are discussed at the end of the post.

I often use hex editor to examine binaries. Even though some of them have rich feature set built-in sometimes there is a need to use special functionality that goes beyond the capability of any hex editor. Some hex editors have plugin interface so for them it's possible to write special functionality that accounts people needs. Although this is true, I have some plugin commands already written for Windbg, and there should not be a reason to code them again to work with some hex-editor, too. That would mean I should maintain both code base in the future which is not what I want.

In the recent days, I was thinking about what if I give it a try to tentatively use Windbg as a static hex editor. I was thinking about that I could use my plugin commands, and many built-in Windbg commands. It sounds very good because those commands are powerful. My second thought was if there was anything that I can achieve in hex editor but cannot in Windbg. I can't name anything so far. Beyond that, I don't even miss the graphical interface.

To use Windbg as hex editor the first things that needs to be done is to open an application (say notepad.exe) to get Windbg prompt. In the further steps, there is nothing to do with the application. Once the prompt is given it waits for command to execute. .dvalloc command is used to allocate memory. .readmem command is to copy the the content of the file to the allocated memory area. There is a script called LoadFile.wds [SkyDrive] that does the job so it's enough to execute this with the correct parameters. Below is the script.
$$ Load file to memory.
$$ 
$$ It reads binary data from the specified file and copies the data to the pre-allocated memory area.
$$
$$ Example Usage: $$>a< e:/LoadFile.wds e:/test.exe 1000
$$
$$ Created: 8/September/2012

.if ( ${/d:$arg1} & ${/d:$arg2} )
{
  $$ Get the 5th token of .dvalloc (i.e Address)
  .foreach /pS 5 (Address {.dvalloc ${$arg2}})
  {
    .readmem ${$arg1} Address L?${$arg2}
    db Address L180
  }
}
.else
{
  .echo "Usage     : LoadFile.wds <file> <size>";
  .echo "Parameters: <file> - File to be loaded"
  .echo "            <size> - Size of the file"
  .echo "Example   : $$>a< e:/LoadFile.wds e:/test.exe 1000";
}
The following demonstrates when a file being loaded using LoadFile.wds script.
0:000> $$>a< c:/work/LoadFile.wds c:/work/test.exe 1800
Reading 1800 bytes...
007e0000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............
007e0010  b8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00  ........@.......
007e0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
007e0030  00 00 00 00 00 00 00 00-00 00 00 00 f0 00 00 00  ................
007e0040  0e 1f ba 0e 00 b4 09 cd-21 b8 01 4c cd 21 54 68  ........!..L.!Th
007e0050  69 73 20 70 72 6f 67 72-61 6d 20 63 61 6e 6e 6f  is program canno
007e0060  74 20 62 65 20 72 75 6e-20 69 6e 20 44 4f 53 20  t be run in DOS 
007e0070  6d 6f 64 65 2e 0d 0d 0a-24 00 00 00 00 00 00 00  mode....$.......
007e0080  f1 3e 51 d1 b5 5f 3f 82-b5 5f 3f 82 b5 5f 3f 82  .>Q.._?.._?.._?.
007e0090  ae c2 a3 82 b6 5f 3f 82-ae c2 a1 82 b4 5f 3f 82  ....._?......_?.
007e00a0  ae c2 95 82 a6 5f 3f 82-ae c2 94 82 b7 5f 3f 82  ....._?......_?.
007e00b0  bc 27 ac 82 b7 5f 3f 82-b5 5f 3e 82 9c 5f 3f 82  .'..._?.._>.._?.
007e00c0  ae c2 90 82 b7 5f 3f 82-ae c2 a2 82 b4 5f 3f 82  ....._?......_?.
007e00d0  52 69 63 68 b5 5f 3f 82-00 00 00 00 00 00 00 00  Rich._?.........
007e00e0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
007e00f0  50 45 00 00 4c 01 04 00-6f c2 38 50 00 00 00 00  PE..L...o.8P....
007e0100  00 00 00 00 e0 00 03 01-0b 01 0a 00 00 0a 00 00  ................
007e0110  00 0a 00 00 00 00 00 00-df 12 00 00 00 10 00 00  ................
007e0120  00 20 00 00 00 00 40 00-00 10 00 00 00 02 00 00  . ....@.........
007e0130  05 00 01 00 00 00 00 00-05 00 01 00 00 00 00 00  ................
007e0140  00 50 00 00 00 04 00 00-03 74 00 00 03 00 00 81  .P.......t......
007e0150  00 00 10 00 00 10 00 00-00 00 10 00 00 10 00 00  ................
007e0160  00 00 00 00 10 00 00 00-00 00 00 00 00 00 00 00  ................
007e0170  24 22 00 00 3c 00 00 00-00 40 00 00 b4 01 00 00  $"..<....@......
Important safety note is that the script uses .dvalloc command to allocate the memory for the data. As a consequence, the memory area has the protection flag of PAGE_EXECUTE_READWRITE. Therefore code execution from the memory page is possible even though it requires series of mistakes to make.
  This blog is written and maintained by Attila Suszter. Read in Feed Reader.