Results 1 to 5 of 5

Thread: Windbg Syntax

  1. #1
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,157
    Blog Entries
    5

    Windbg Syntax

    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/windbg-the-fun-way-part-1-2e4978791f9b
    https://medium.com/@yardenshafir2/windbg-the-fun-way-part-2-7a904cba5435

    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]

  2. #2
    Super Moderator
    Join Date
    Dec 2004
    Posts
    1,529
    Blog Entries
    15
    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:
    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:
    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:
    0:000> ? .+6+dwo(.+2)
    Evaluate expression: 140730595902712 = 00007ffe`652d84f8
    just .printf the underlying pointer as symbol

    Code:
    0:000> .printf "%y\n" , poi( .+6+dwo(.+2))
    ntdll!LdrpDispatchUserCallTarget (00007ffe`7e0cc510)
    Last edited by blabberer; June 22nd, 2020 at 10:04.

  3. #3
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,157
    Blog Entries
    5
    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:
    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:
    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:
    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.

  4. #4
    Super Moderator
    Join Date
    Dec 2004
    Posts
    1,529
    Blog Entries
    15
    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:
    function dps()
    {
       var ln = host.namespace.Debugger.Utility.Control.ExecuteCommand("rM0").Last()
       host.diagnostics.debugLog( ln.substring( ln.indexOf("{") ) + "\n")
    }
    execution


    Code:
    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:
    #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:
    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:
    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)
    Last edited by blabberer; June 24th, 2020 at 08:02.

  5. #5
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,157
    Blog Entries
    5
    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

    Code:
    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 "^" | powershell.exe -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:
      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

Similar Threads

  1. Dumping memory with Windbg
    By AttonRand in forum The Newbie Forum
    Replies: 0
    Last Post: July 9th, 2012, 15:27
  2. Windbg breakpoint with condition
    By rxxxxxx333 in forum The Newbie Forum
    Replies: 0
    Last Post: January 12th, 2011, 01:19
  3. MASM Syntax.
    By Innocent in forum The Newbie Forum
    Replies: 3
    Last Post: September 27th, 2004, 11:16
  4. Log data: Syntax error; cause of source code issue
    By casterle in forum OllyDbg Support Forums
    Replies: 10
    Last Post: September 12th, 2004, 14:38
  5. Syntax Highlighting for OllyScript in UltraEdit
    By TQN in forum OllyScript Plugin
    Replies: 3
    Last Post: July 13th, 2004, 11:34

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •