Welcome to the new Woodmann RCE Messageboards Regroupment
Please be patient while the rest of the site is restored.

To all Members of the old RCE Forums:
In order to log in, it will be necessary to reset your forum login password ("I forgot my password") using the original email address you registered with. You will be sent an email with a link to reset your password for that member account.

The old vBulletin forum was converted to phpBB format, requiring the passwords to be reset. If this is a problem for some because of a forgotten email address, please feel free to re-register with a new username. We are happy to welcome old and new members back to the forums! Thanks.

All new accounts are manually activated before you can post. Any questions can be PM'ed to Kayaker.

Windbg Syntax

All-in-one reversing related discussions
Post Reply
User avatar
Kayaker
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Windbg Syntax

Post by Kayaker »

I've been trying to make use of the Windbg 'dx' command and some of the fancy Natvis/LINQ stuff. There are a couple of recent examples of the types of output you can get, along with the regular docs:

https://medium.com/@yardenshafir2/windb ... 4978791f9b
https://medium.com/@yardenshafir2/windb ... 904cba5435

As a practical example I'm trying to print out information from call instructions in the disassembly window. The following code is hit several times, with a different value in Call EAX. I'd like to get a list of all the function addresses that the register points to each time the breakpoint is hit.

In the disassembly window the function address is resolved (68e085)

0069038c call dword ptr [eax] ds:002b:0070c098=0068e085

Now I'm trying to find a command that will let me print out that address, ultimately to be written to a log file or a formatted grid using 'dx -g'.

If I simply use the "u" command I don't get the same output from the disassembly window and wouldn't be able to parse out the function address.

0:000> u $ip L1
0069038c call dword ptr [eax]


I suppose one could probably use 'poi(@eax)' or similar to reference this type of addressing, if the function can't be parsed directly from the disassembly text. I thought there might be something more generic than referencing individual registers +/- possible offsets ([ebp-8], [ecx+4], etc).


Similarly, a call that resolves a symbol name in the disassembly window doesn't show in the command window.

00683d20 call dword ptr [..+0x2b618c (006b618c)] ds:002b:006b618c={KERNEL32!GetVersionStub (76eb2cb0)}

0:000> u $ip L1
00683d20 call dword ptr [..+0x2b618c (006b618c)]


According to the search command '#' there are up to 4 parts of the disassembly display. Not all 'details' seem to be available outside of the disassembly window.

# You can view disassembly instructions by using the u (Unassemble) command or by using the Disassembly window in WinDbg. The disassembly display contains up to four parts: Address offset, Binary code, Assembly language mnemonic, and Assembly language details.


I was trying to find a 'dx' command that might give better results, but can't find anything directly. Possibly using this one along with breakpoints, but can't figure out what debugger command would be best to print out correct and useful function addresses.

dx Debugger.Utility.Control.ExecuteCommand [ExecuteCommand(command) - Method which executes a debugger command and returns a collection of strings representing the lines of output of the command execution]
blabberer
Senior Member
Posts: 1535
Joined: Wed Dec 08, 2004 11:12 am

Post by blabberer »

windbg provides two Pseudo Register ea and ea2 that corresponds to effective address 1 and effective address 2


if you have broken on some rip / eip and if the instruction has an effective address you can use these PseudoVariables

like

? @$ea
? @$ea2

or you can print the annotated Disassembly with rM0

or you can use

dps @$ea l1

I don't think dx provides an address to symbol resolution format character but I may be wrong I haven't used the preview much where these dx fancies are rolled out faster than the classic windbg

here is a small example


Code: Select all

0:000> u . l1
aswhook+0x395d:
00007ffe`652d395d ff15954b0000    call    qword ptr [aswhook+0x84f8 (00007ffe`652d84f8)]
0:000> rM0
aswhook+0x395d:
00007ffe`652d395d ff15954b0000    call    qword ptr [aswhook+0x84f8 (00007ffe`652d84f8)] ds:00007ffe`652d84f8={ntdll!LdrpDispatchUserCallTarget (00007ffe`7e0cc510)}
0:000> dps @$ea l1
00007ffe`652d84f8  00007ffe`7e0cc510 ntdll!LdrpDispatchUserCallTarget

btw you can rip the rip relative offsets and get the resolved address manually

lets say its an ff 15 call in x64 which has a rip relative offset 0f 4b95 in the above example

Code: Select all

python -c "print (hex(0x7ffe652d395d+0x6+0x4b95))"
0x7ffe652d84f8
you can get the rip relative offset with dwo(.+2)

so the absolute address is

. + 6 + dwo(.+2)

Code: Select all

0:000> ? .+6+dwo(.+2)
Evaluate expression: 140730595902712 = 00007ffe`652d84f8
just .printf the underlying pointer as symbol

Code: Select all

0:000> .printf "%y\n" , poi( .+6+dwo(.+2))
ntdll!LdrpDispatchUserCallTarget (00007ffe`7e0cc510)
User avatar
Kayaker
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »

Thanks Blabberer, that's some good useful info.

Unfortunately there's a bit of weird behaviour to deal with. If I step or break on a Call instruction @$ea fails the first time, unless I first use rM0, which seems to "initialize" the command to work:

Code: Select all

0:000> dps @$ea l1
Bad register error at '@$ea '

0:000> rM0
..+0x283d20:
00683d20 ff158c616b00    call    dword ptr [..+0x2b618c (006b618c)] ds:002b:006b618c={KERNEL32!GetVersionStub (76eb2cb0)}

0:000> dps @$ea l1 // now it works
006b618c  76eb2cb0 KERNEL32!GetVersionStub
I can use those instructions separately or together in a 'dx' command and get a bunch of output. -r2 level gives the length of the return string, which could be useful for parsing.

Code: Select all

0:000> dx -r1 Debugger.Utility.Control.ExecuteCommand("rM0")
Debugger.Utility.Control.ExecuteCommand("rM0")                
    [0x0]            : ..+0x29038c:
    [0x1]            : 0069038c ff10            call    dword ptr [eax]      ds:002b:0070c098=0068e085
    
0:000> dx -r2 Debugger.Utility.Control.ExecuteCommand("dps @$ea l1")
Debugger.Utility.Control.ExecuteCommand("dps @$ea l1")                
    [0x0]            : 0070c098  0068e085 ..+0x28e085
        Length           : 0x23

After realizing you need to escape inner quotes as \" I was able to combine a bp with dx-ExecuteCommand. At the moment it gives a messy output that I need to figure out how to parse to get the useful list of function addresses that I want.

Code: Select all

bp 69038C "dx -r1 Debugger.Utility.Control.ExecuteCommand(\"rM0;dps @$ea l1\")"

0:000> g
Debugger.Utility.Control.ExecuteCommand("rM0;dps @$ea l1")                
    [0x0]            : ..+0x29038c:
    [0x1]            : 0069038c ff10            call    dword ptr [eax]      ds:002b:0070c09c=0068e0a8
    [0x2]            : 0070c09c  0068e0a8 ..+0x28e0a8
eax=0070c09c ebx=00014b01 ecx=027064e0 edx=02b8a0b0 esi=02704320 edi=027068c0
eip=0069038c esp=02b8a08c ebp=02b8a0b8 iopl=0         nv up ei ng nz ac pe cy
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000297
..+0x29038c:
0069038c ff10            call    dword ptr [eax]      ds:002b:0070c09c=0068e0a8
 


Yeah, I've thought about trying Windbg Preview, but not really wanting to get it from the Store or using an MS account.
blabberer
Senior Member
Posts: 1535
Joined: Wed Dec 08, 2004 11:12 am

Post by blabberer »

I understand you want to use dx

but for the last example you posted where you escape quotes etc you don't need the dx at all

in fact you don't need dps also if you are just interested in the resolved function name

(yes dps will fail unless the expression was evaluated prior rM0 forces the execution and filling up of those pseudo registers )

if you need finetuning you may need to write a windbg extension and get everything as you wish using DEBUG_DISASM_EFFECTIVE_ADDRESS


or instead of extension write a JavaScript and stick it as a conditional as below

javascript

Code: Select all

function dps()
{
   var ln = host.namespace.Debugger.Utility.Control.ExecuteCommand("rM0").Last()
   host.diagnostics.debugLog( ln.substring( ln.indexOf("{") ) + "\n")
}
execution

Code: Select all

0:000> .scriptload fptr.js

JavaScript script successfully loaded 

0:000> bp fptr+10f0 "dx @$scriptContents.dps();gc"   <<<<<<<<<<<<< bp + conditional

0:000> g
@$scriptContents.dps() : {fptr!a (00007ff6`56511000)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!b (00007ff6`56511010)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!c (00007ff6`56511020)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!d (00007ff6`56511030)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!e (00007ff6`56511040)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!f (00007ff6`56511050)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!g (00007ff6`56511060)}
    Length           : 0x1c
@$scriptContents.dps() : {fptr!h (00007ff6`56511070)}
    Length           : 0x1c

code used for above

Code: Select all

#include <stdio.h>
void a(int a) { printf(" %d\n", a); }
void b(int a) { printf(" %d\n", a); }
void c(int a) { printf(" %d\n", a); }
void d(int a) { printf(" %d\n", a); }
void e(int a) { printf(" %d\n", a); }
void f(int a) { printf(" %d\n", a); }
void g(int a) { printf(" %d\n", a); }
void h(int a) { printf(" %d\n", a); }
void (*foo[8])(int){&a, &b, &c, &d, &e, &f, &g, &h};

void main(void)
{
    for (int i = 0; i < 8; i++)
    {
        (*foo[i])(10 + i);
    }
}

disassembly of main

Code: Select all

0:000> uf fptr!main

   13 00007ff6`565110d8 48895c2408      mov     qword ptr [rsp+8],rbx
   13 00007ff6`565110dd 57              push    rdi
   13 00007ff6`565110de 4883ec20        sub     rsp,20h
   14 00007ff6`565110e2 bf0a000000      mov     edi,0Ah
   14 00007ff6`565110e7 488d1d12cf0500  lea     rbx,[fptr!foo (00007ff6`5656e000)]
   16 00007ff6`565110ee 8bcf            mov     ecx,edi
   16 00007ff6`565110f0 ff13            call    qword ptr [rbx]   <<<<< bp on this address
   16 00007ff6`565110f2 488d0547cf0500  lea     rax,[fptr!__scrt_native_dllmain_reason (00007ff6`5656e040)]
   16 00007ff6`565110f9 ffc7            inc     edi
   16 00007ff6`565110fb 4883c308        add     rbx,8
   16 00007ff6`565110ff 483bd8          cmp     rbx,rax
   16 00007ff6`56511102 7cea            jl      fptr!main+0x16 (00007ff6`565110ee)  Branch
   18 00007ff6`56511104 488b5c2430      mov     rbx,qword ptr [rsp+30h]
   18 00007ff6`56511109 33c0            xor     eax,eax
   18 00007ff6`5651110b 4883c420        add     rsp,20h
   18 00007ff6`5651110f 5f              pop     rdi
   18 00007ff6`56511110 c3              ret
and btw most of the times you know the registers / absolute address / stack pointers etc as you have a fixed address to breakpoint you can simply
use them instead of rM0 , dx , ea etc

for the code above you can use rbx and .printf it conditional

Code: Select all

0:000> bp fptr + 10f0 ".printf \"%y\\n\" , poi(@rbx);gc";bl;g

     0 e Disable Clear  00007ff6`565110f0     0001 (0001)  0:**** fptr!main+0x18 ".printf \"%y\\n\" , poi(@rbx);gc"

fptr!a (00007ff6`56511000)
fptr!b (00007ff6`56511010)
fptr!c (00007ff6`56511020)
fptr!d (00007ff6`56511030)
fptr!e (00007ff6`56511040)
fptr!f (00007ff6`56511050)
fptr!g (00007ff6`56511060)
fptr!h (00007ff6`56511070)
User avatar
Kayaker
Posts: 4169
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »

Well, after hours mucking around with Windbg scripting I came up with this monstrosity that worked to extract the function name.
I wasn't able to combine the .shell command with a breakpoint, syntactically it just seemed to never work.
Yay Windbg scripting :cry:

Code: Select all

00683d20 ff158c616b00    call    dword ptr [proc+0x2b618c (006b618c)] ds:002b:006b618c={KERNEL32!GetVersionStub (76eb2cb0)}

.shell -ci "dx -r0 Debugger.Utility.Control.ExecuteCommand(\"rM0;dps @$ea l1\")[2].Remove(0,10)" findstr "^" | [B]powershell.exe[/B] -command "$input.split(" ")[5]" >> out.txt

>>KERNEL32!GetVersionStub
At this point I realized doing this with the Javascript model would make so much more sense. Your first example works perfectly for the purpose, though I had to access the namespace a little differently.

Code: Select all

  dx -r0 @$scriptContents.exec("rM0")

>>Function: {KERNEL32!GetVersionStub (76eb2cb0)}

function exec(cmdstr)
{
    var ln = host.namespace.Debugger.Utility.Control.ExecuteCommand(cmdstr);  
    var ln2 = ln.Last().substring(ln.Last().indexOf("{"));    
    return logme("Function: " + ln2);
 }
 
 function logme(toprint)
{
    return host.diagnostics.debugLog(toprint + "\n");
}
Unfortunately I don't believe I have access to Debugger.Utility.FileSystem with this version of Windbg, so I'm not sure how to write to a text file. I might be able to go through Powershell again, but there should be another way. I'll try fs.open fs.writeFile.

(yes dps will fail unless the expression was evaluated prior rM0 forces the execution and filling up of those pseudo registers )
Good explanation btw
Post Reply