read

// This post will be updated regularily. Don’t rely on it, i’m learning.

Working through a new course that encourages WinDBG over other debuggers. I love WinDBG, but i find i forget even the basics because it is so long between drinks.

The unassemble commands:

If you do u on it’s own the debugger will assume you want to unassemble from EIP. If you have a memory address in mind u {address}. If that’s not what you want, and you have a function in mind use:

u Kernel32!GetCurrentThread

The display commands:

If it’s bytes you want:

db esp
db Kernel32!WriteFile

80 bytes is the default amount you’ll get if you don’t specify.

Substitute in w to display words.

For ASCII representations use the dW or dc.

For unicode: du

As an example of dealing with pointers - consider that you are interested in a parameter on the stack esp+4 but you know that it is a pointer. It’d be tempting to do:

0:007> dd esp+4
0:007> u 777be222

But if we already know we’re dealing with the pointer, probably because we are looking at the documents for the function, we can tell the debugger to do the steps for us. Use

u poi(ebp+4)

Breakpoint:

bp Comdlg32!GetOpenFileNameA

Structures:

We use the display type dt commands.

For example:

dt ntdll._teb

You can also pass the r parameter to be recursive since the structure might have child structures inside.

The example command will show the example structure:

0:007> dt ntdll!_teb
   +0x000 NtTib            : _NT_TIB
   +0x038 EnvironmentPointer : Ptr64 Void
   +0x040 ClientId         : _CLIENT_ID
   +0x050 ActiveRpcHandle  : Ptr64 Void
   +0x058 ThreadLocalStoragePointer : Ptr64 Void
   +0x060 ProcessEnvironmentBlock : Ptr64 _PEB
   +0x068 LastErrorValue   : Uint4B
   +0x06c CountOfOwnedCriticalSections : Uint4B
   <snip>

What’s more interesting is to look at the populated structure using a psuedo register like:

dt -r ntdll!_teb @teb
0:007> dt -r ntdll!_teb @$teb
<snip>
         +0x050 DllPath          : _UNICODE_STRING ""
         +0x060 ImagePathName    : _UNICODE_STRING "C:\WINDOWS\system32\notepad.exe"
         +0x070 CommandLine      : _UNICODE_STRING ""C:\WINDOWS\system32\notepad.exe" "
         +0x080 Environment      : 0x00000259`1dc60fe0 Void
         +0x088 StartingX        : 0
         +0x08c StartingY        : 0
         +0x090 CountX           : 0
         +0x094 CountY           : 0
         +0x098 CountCharsX      : 0
         +0x09c CountCharsY      : 0
         +0x0a0 FillAttribute    : 0
         +0x0a4 WindowFlags      : 0xc01
         +0x0a8 ShowWindowFlags  : 1
         +0x0b0 WindowTitle      : _UNICODE_STRING "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk"
         +0x0c0 DesktopInfo      : _UNICODE_STRING "Winsta0\Default"
</snip>

Size of Structures:

To inspect the size of a structure (which will often be a parameter passed to a function):

0:000> ?? sizeof(ntdll!_PEB)
unsigned int 0x468

Writing memory:

We use the e (edit?) commands. For example:

0:000> r
eax=00000000 ebx=00000000 ecx=029ff258 edx=77791670 esi=02b5a000 edi=777136cc
eip=777cbb62 esp=029ff274 ebp=029ff2a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
777cbb62 cc              int     3

0:000> dd esp L1
029ff274  f136b9fa

0:000> ed esp 41414141

0:000> dd esp L1
029ff274  41414141

The size modifiers are the same as with the display commands.

We can work with Ascii using the a version of the e command, or the u version for unicode.

0:000> da esp L5
029ff274  "Yikes"

0:000> ea esp "Rainy"

0:000> da esp L5
029ff274  "Rainy"

While writing exploits we can drop the ascii version straight into memory, and then pull it back out with the db command, giving us the bytes we need for shellcode.

0:000> ea esp "c:\\users\\chad\\payload.exe"

0:000> da esp L19
029ff274  "c:\users\chad\payload.exe"

0:000> db esp L19
029ff274  63 3a 5c 75 73 65 72 73-5c 63 68 61 64 5c 70 61  c:\users\chad\pa
029ff284  79 6c 6f 61 64 2e 65 78-65                       yload.exe

Searching Memory:

The search commands are s -

As an example, we’ll put a unique pattern in the process address space, then search:

0:000> ed esp 41424344

0:000> s -d 0 L?80000000 41424344
0229f994  41424344 777136cc 024b0000 00000000  DCBA.6qw..K.....

The example uses a DWORD -d as the type we want to search; it starts at address 0 and goes up 8000000 - we use the L? modifer for the top of the range.

To search for ascii we use -a instead:

0:000> s -a 0 L?80000000 "Microsoft Corporation"
0005357c  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
6b75bb78  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
6bd2b6fc  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
7094322c  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
70945412  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
74b4224c  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
754f6ecc  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
76b470ec  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
772611cc  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor
776abf9c  4d 69 63 72 6f 73 6f 66-74 20 43 6f 72 70 6f 72  Microsoft Corpor

The example above shows us that many of the binaries loaded by notepad.exe contain the ascii string “Microsoft Corporation”

Or unicode - u

0:000> s -u 0 L?80000000 "Microsoft Corporation"
0006c8d8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
0006ca00  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
689d97e8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
689d9934  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6b8cb168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6b8cb2dc  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6bd2ba60  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6bd2bbb8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6fec11c8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
6fec131c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
70943738  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
70943888  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
738fd168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
738fd2a8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
73c88118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
73c88274  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
73d591c8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
73d5933c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7417a7f8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7417a948  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
741c2118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
741c2268  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
741ec118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
741ec26c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
743a0168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
743a02d0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74455118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74455270  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7456b118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7456b278  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
745d4118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
745d42a0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74b42760  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74b428c0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74de8118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74de8240  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74f381b8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74f382ec  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74fd6118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
74fd6278  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
754f73d0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
754f751c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
765311c8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7653131c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7665f168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7665f2c4  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76b47878  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76b479cc  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76bd9778  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76bd98e0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76d4b168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76d4b2a8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76d4b428  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
76d4b540  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
770921a8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
77092308  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
772616d0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
77261830  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
772df168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
772df2cc  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7736f118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7736f24c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
773fe168  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
773fe290  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
77528118  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
7752825c  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
775eb1c8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
775eb324  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
776eb030  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
776eb174  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
778201a8  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.
778202e0  004d 0069 0063 0072 006f 0073 006f 0066  M.i.c.r.o.s.o.f.

Registers:

We can inspect registers with r

We can manipulate them by passing the register we are interested in, with the assignment operator:

0:000> r edi
edi=777136cc

0:000> r edi=00000001

0:000> r edi
edi=00000001

0:000> r
eax=00000000 ebx=00000000 ecx=0229f978 edx=77791670 esi=024b0000 edi=00000001
eip=777cbb62 esp=0229f994 ebp=0229f9c0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
777cbb62 cc              int     3

Breakpoints:

b family :)

bp kernel32!WriteFile for example. But you might have an unresolved symbol you want to nab: bu ole32!WriteStringStream.

bl to list, bd to disable one, be to re-enable, bc to clear.

The really powerful stuff is the automated actions:

bp kernel32!WriteFile ".printf \"WriteFile has just written is: %p\", poi(esp + 0x0C);.echo;g"

or, with a conditional (like, only tell me if it’s an 8 byte write):

bp kernel32!WriteFile ".if (poi(esp + 0x0C) != 8) {gc} .else {.printf \"WriteFile just did the 8 byte write\";.echo;}"

Hardware breakpoint can help monitor access or changes to memory:

//search for the string we've saved in notepad
s -a 0x0 L?80000000 chadchad
093d7718  63 68 61 64 63 68 61 64-00 00 00 00 00 00 00 00  chadchad........

// Set breakpoint
ba w 2 093d7718

// now if it's modified or accessed we will break. 

Hardware breakpoints don’t need to software breakpoint (INT 3) inserted: ba e 1 Kernel32!WriteFile where e is execute access (could have been read or write) and 1 is the number of bytes.

A very handy example is the winsock receive:

bp wsock32!recv

Stepping:

p steps over a function. t steps into a function pt will step to the next return instruction. ph will continue to the next branch.

Examine Symbols:

x KernelBase!CreateNamed*

Formats:

Handy, it’ll show you the formated values of an input (decimal, hex etc).

.formats 41414141

SEH Work !exchain is very handy to inspect the SEH chain.

Heap

Overview - get the current Heap addresses for the process:

0:001> !heap
NtGlobalFlag enables following debugging aids for new heaps:    tail checking
    free checking
    validate parameters
Index   Address  Name      Debugging options enabled
  1:   00450000                 tail checking free checking validate parameters
  2:   006b0000                 tail checking free checking validate parameters
0:001> !heap stat
Index   Address  Name      Debugging options enabled
  1:   00450000 
    Segment at 00450000 to 00550000 (00100000 bytes committed)
    Segment at 00550000 to 00650000 (00100000 bytes committed)
    Segment at 006c0000 to 008c0000 (00023000 bytes committed)
  2:   006b0000 
    Segment at 006b0000 to 006c0000 (00005000 bytes committed)
!heap -h 00450000 or ->
0:001> !heap -stat -h 00450000
 heap @ 00450000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    5000 64 - 1f4000  (99.12)
    1534 1 - 1534  (0.26)
    cbc 1 - cbc  (0.16)
    500 1 - 500  (0.06)
    440 1 - 440  (0.05)
    400 1 - 400  (0.05)
    200 2 - 400  (0.05)
    78 6 - 2d0  (0.03)
    284 1 - 284  (0.03)
    220 1 - 220  (0.03)
    208 1 - 208  (0.03)
    1f0 1 - 1f0  (0.02)
    20 c - 180  (0.02)
    ce 1 - ce  (0.01)
    64 2 - c8  (0.01)
    3e 3 - ba  (0.01)
    10 b - b0  (0.01)
    90 1 - 90  (0.01)
    80 1 - 80  (0.01)
    40 2 - 80  (0.01)

When we have an address to inspect:

0:001> !heap -p -a 0x45e900
    address 0045e900 found in
    _HEAP @ 450000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0045e8f8 0a03 0000  [00]   0045e900    05000 - (busy)
0:001> !heap -x 0x45e900
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
0045e8f8  0045e900  00450000  00450000      5018      5018        18  busy extra fill 

The header, showing the fill baadf00d after the header values when in the debugger.

0:001> dp 0045e8f8
0045e8f8  517a25a5 1800c607 baadf00d baadf00d
0045e908  baadf00d baadf00d baadf00d baadf00d
0045e918  baadf00d baadf00d baadf00d baadf00d
0045e928  baadf00d baadf00d baadf00d baadf00d
0045e938  baadf00d baadf00d baadf00d baadf00d
0045e948  baadf00d baadf00d baadf00d baadf00d
0045e958  baadf00d baadf00d baadf00d baadf00d
0045e968  baadf00d baadf00d baadf00d baadf00d
0:001> dp 0045e8f8 - 0x10
0045e8e8  abababab abababab 00000000 00000000
0045e8f8  517a25a5 1800c607 baadf00d baadf00d
0045e908  baadf00d baadf00d baadf00d baadf00d
0045e918  baadf00d baadf00d baadf00d baadf00d
0045e928  baadf00d baadf00d baadf00d baadf00d
0045e938  baadf00d baadf00d baadf00d baadf00d
0045e948  baadf00d baadf00d baadf00d baadf00d
0045e958  baadf00d baadf00d baadf00d baadf00d

You can start windbg with -hd “hide debugger” to remove the gflags resposible for this.

If we attach to the binary after it is already running we get different gflag behaviour.

For example:

0:001> !gflag
Current NtGlobalFlag contents: 0x00000000

dp {chunk} with debugger attached after exectution shows none of the baadf00d fill:

0:001> dp 0x53b1c0
0053b1c0  007b00c4 008a9380 00000000 00000000
0053b1d0  00000000 00000000 00000000 00000000
0053b1e0  00000000 00000000 00000000 00000000
0053b1f0  00000000 00000000 00000000 00000000
0053b200  00000000 00000000 00000000 00000000
0053b210  00000000 00000000 00000000 00000000
0053b220  00000000 00000000 00000000 00000000
0053b230  00000000 00000000 00000000 00000000

Same with the tail -

0:001> dp 0x53b1c0 - 0x10
0053b1b0  00000000 00000000 02db8bc3 080f30c7
0053b1c0  007b00c4 008a9380 00000000 00000000
0053b1d0  00000000 00000000 00000000 00000000
0053b1e0  00000000 00000000 00000000 00000000
Blog Logo

Chad Duffey


Published

Image

Chad Duffey

Blue Team -> Exploit Development & things in-between

Back to Overview