1

在跟进一些windbg教程时,我注意到一些使用k命令的调用堆栈采用这种格式,特别是我的

Child-SP          RetAddr           Call Site

而像CodeProject这样的其他在线资源有k命令以这种格式吐出信息

Child-EBP          RetAddr           Call Site

我对为什么我的输出和他们的输出之间存在差异以及这真正意味着什么感到困惑。

4

1 回答 1

0

这取决于正在使用什么调用约定。一些函数分配局部变量和参数,它将传递给它使用基指针调用的函数,例如 cdecl,但 Windows x64 调用约定使用rsp.

Child-SP 是该帧的堆栈指针的值,它将是除帧 0 之外的所有帧的返回地址之前的字节,帧 0 可能在序言之前或期间有一个断点。如果断点在第一条指令上,那么rsp在前一帧的 Child-SP 上只会减少 8;该rsp值是从陷阱帧中读取的。如果您不认为被调用者的返回地址是帧的一部分,则 Child-SP 是帧号处的帧地址(这在这种情况下是有意义的,因为帧的返回地址列显示返回前一帧的地址成为该帧的一部分)。

ChildEBP 是该ebp帧中 when 的值(不是ebp被推送到帧的值,而是 的新值ebp

RetAddr 是属于该帧的返回地址,所以是它会返回的地址

调用站点是被调用的结束帧的调用指令之后的指令地址(基本上就是被调用者返回地址 -- call instruction + call instruction length),或者是断点的地址或导致它闯入调试器的其他异常(注意:异常的地址,而不是它之后的指令,所以这将rip在陷阱帧中)在第 0 帧(堆栈顶部的帧)的情况下。只要该函数不包含标签,这将指示拥有该行上的框架的函数的名称,并且子项的参数是传递给它的参数。实际上,调用点是它调用的框架(它上面的框架)的返回地址。

子参数是传递给拥有当前行堆栈帧的函数的参数,而不是传递给它在序言分配的空间中调用的被调用函数的参数。这在 x64 上几乎是不准确的,它显示了 homespace 的前 3 个四字,因为前 4 个参数可以在寄存器中传递,如果是,被调用函数可能不会将这些参数归位(将它们保存在 homespace 中)-O0或不是 varargs 函数,或者可能将其他东西完全放在 homespace 中。'Args to child' 和 'Child-SP' 中的 'Child' 是一个错误且具有误导性的名称,它暗示了框架调用的函数,但它实际上指的是当前函数。

这个站点上有一个示例堆栈跟踪,它显示了一个断点notepad!ShowOpenSaveDialog,这将是第一条指令。

0:011> bp notepad!ShowOpenSaveDialog
0:011> g
Breakpoint 0 hit
notepad!ShowOpenSaveDialog:
00007ff7`0307182c 48895c2408      mov     qword ptr [rsp+8],
           rbx ss:00000073`74d2f310=0000000000000000
0:000> k
 # Child-SP          RetAddr           Call Site
00 00000073`74d2f308 00007ff7`03071aeb notepad!ShowOpenSaveDialog
01 00000073`74d2f310 00007ff7`030721fa notepad!InvokeOpenDialog+0x14f
02 00000073`74d2f370 00007ff7`030738d6 notepad!NPCommand+0x4a2
03 00000073`74d2f6f0 00007fff`664b6d41 notepad!NPWndProc+0x726
04 00000073`74d2f9f0 00007fff`664b6713 USER32!UserCallWinProcCheckWow+0x2c1
05 00000073`74d2fb80 00007ff7`03073bdb USER32!DispatchMessageWorker+0x1c3
06 00000073`74d2fc10 00007ff7`03089333 notepad!WinMain+0x27f
07 00000073`74d2fd10 00007fff`68ea3034 notepad!__mainCRTStartup+0x19f
08 00000073`74d2fdd0 00007fff`69073691 KERNEL32!BaseThreadInitThunk+0x14
09 00000073`74d2fe00 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:000> r @rcx=0
0:000> r
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000000
rdx=00000213f5020968 rsi=000000499cb1f338 rdi=00000213f5021c20
rip=00007ff70307182c rsp=000000499cb1f288 rbp=000000499cb1f2d0
 r8=00000213f4ffe9d6  r9=000000499cb1f338 r10=00000ffee060e246
r11=0000000000014140 r12=0000000000000000 r13=0000000000000001
r14=000000000004094e r15=00000000ffffffff
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
notepad!ShowOpenSaveDialog:
00007ff7`0307182c 48895c2408      mov     qword ptr [rsp+8],
rbx ss:00000049`9cb1f290=0000000000000000
0:000> ub notepad!InvokeOpenDialog+0x14f
notepad!InvokeOpenDialog+0x133:
00007ff7`03071acf 8bd8            mov     ebx,eax
00007ff7`03071ad1 85c0            test    eax,eax
00007ff7`03071ad3 782c            js      notepad!InvokeOpenDialog+0x165 (00007ff7`03071b01)
00007ff7`03071ad5 4c8b05fc080200  mov     r8,qword ptr [notepad!szOpenCaption (00007ff7`030923d8)]
00007ff7`03071adc 4c8bce          mov     r9,rsi
00007ff7`03071adf 488b5538        mov     rdx,qword ptr [rbp+38h]
00007ff7`03071ae3 498bce          mov     rcx,r14
00007ff7`03071ae6 e841fdffff      call    notepad!ShowOpenSaveDialog (00007ff7`0307182c)

创建的陷阱帧nt!KiBreakpointTrap不是堆栈跟踪的一部分,因为陷阱帧被推送到线程的内核堆栈而不是用户堆栈。

如果您正在调试内核,那么如果存在陷阱帧并且进程地址空间可访问,您将看到用户和内核堆栈的融合:

lkd> .process /P fffffa80723296f0
lkd> .reload
lkd> ld *
lkd> !process 3490                                                                                                                             
Searching for Process with Cid == 3490                                                                                                         
Cid handle table at fffff8a00195f000 with 4126 entries in use                                                                                  
                                                                                                                                               
PROCESS fffffa80723296f0                                                                                                                       
    SessionId: 1  Cid: 3490    Peb: 7fffffdf000  ParentCid: 1470                                                                               
    DirBase: 403874000  ObjectTable: fffff8a02b3a2ce0  HandleCount: 293.                                                                       
    Image: chrome.exe                                                                                                                          
    VadRoot fffffa805fc816e0 Vads 295 Clone 0 Private 16586. Modified 1536. Locked 0.                                                          
    DeviceMap fffff8a00208d0b0                                                                                                                 
    Token                             fffff8a03466d9e0                                                                                         
    ElapsedTime                       00:23:43.376                                                                                             
    UserTime                          00:00:00.717                                                                                             
    KernelTime                        00:00:00.000                                                                                             
    QuotaPoolUsage[PagedPool]         0                                                                                                        
    QuotaPoolUsage[NonPagedPool]      0                                                                                                        
    Working Set Sizes (now,min,max)  (27282, 50, 345) (109128KB, 200KB, 1380KB)                                                                
    PeakWorkingSetSize                33917                                                                                                    
    VirtualSize                       870 Mb                                                                                                   
    PeakVirtualSize                   891 Mb                                                                                                   
    PageFaultCount                    81452                                                                                                    
    MemoryPriority                    BACKGROUND                                                                                               
    BasePriority                      4                                                                                                        
    CommitCharge                      19316                                                                                                    
    Job                               fffffa805f9f46d0                                                                                         
        THREAD fffffa802e890b50  Cid 3490.469c  Teb: 000007fffffdd000 Win32Thread: fffff900c53a48c0 WAIT: (UserRequest) UserMode Non-Alertable 
            fffffa8062daf060  SynchronizationEvent                                                                                             
        Not impersonating                                                                                                                      
        DeviceMap                 fffff8a00208d0b0                                                                                             
        Owning Process            fffffa80723296f0       Image:         chrome.exe                                                             
        Attached Process          N/A            Image:         N/A                                                                            
        Wait Start TickCount      45844297       Ticks: 42 (0:00:00:00.655)                                                                    
        Context Switch Count      21234                 LargeStack                                                                             
        UserTime                  00:00:07.300                                                                                                 
        KernelTime                00:00:00.234                                                                                                 
        Win32 Start Address chrome!IsSandboxedProcess (0x000000013fbcbe90)                                                                     
        Stack Init fffff8802d5bec70 Current fffff8802d5be7c0                                                                                   
        Base fffff8802d5bf000 Limit fffff8802d5b7000 Call 0                                                                                    
        Priority 4 BasePriority 4 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5 
        Child-SP          RetAddr           Call Site                                                                                          
        fffff880`2d5be800 fffff800`0367ec32 nt!KiSwapContext+0x7a                                                                              
        fffff880`2d5be940 fffff800`0368145f nt!KiCommitThreadWait+0x1d2                                                                        
        fffff880`2d5be9d0 fffff800`0397602e nt!KeWaitForSingleObject+0x19f                                                                     
        fffff880`2d5bea70 fffff800`03678c13 nt!NtWaitForSingleObject+0xde                                                                      
        fffff880`2d5beae0 00000000`7782bd7a nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ fffff880`2d5beae0)                                     
        00000000`002eec08 000007fe`fd6110ac ntdll!NtWaitForSingleObject+0xa                                                                    
        00000000`002eec10 000007fe`d97c2107 KERNELBASE!WaitForSingleObjectEx+0x79                                                              
        00000000`002eecb0 000007fe`d858aeab chrome_child!GetHandleVerifier+0x15d8417                                                           
        00000000`002eed40 000007fe`d823004d chrome_child!GetHandleVerifier+0x3a11bb                                                            
        00000000`002eedb0 000007fe`d822fc91 chrome_child!GetHandleVerifier+0x4635d                                                             
        00000000`002eee10 000007fe`d8217c59 chrome_child!GetHandleVerifier+0x45fa1                                                             
        00000000`002eee40 000007fe`d82176de chrome_child!GetHandleVerifier+0x2df69                                                             
        00000000`002ef040 000007fe`d82105d1 chrome_child!GetHandleVerifier+0x2d9ee                                                             
        00000000`002ef1b0 000007fe`d81e518b chrome_child!GetHandleVerifier+0x268e1                                                             
        00000000`002ef250 000007fe`d81e4c58 chrome_child!ChromeMain+0x377d                                                                     
        00000000`002ef570 000007fe`d81e1b2e chrome_child!ChromeMain+0x324a                                                                     
        00000000`002ef600 00000001`3faf354c chrome_child!ChromeMain+0x120                                                                      
        00000000`002ef6d0 00000001`3faf1699 chrome+0x354c                                                                                      
        00000000`002ef7c0 00000001`3fbcbe33 chrome+0x1699                                                                                      
        00000000`002efba0 00000000`775d59cd chrome!IsSandboxedProcess+0x61483                                                                  
        00000000`002efbe0 00000000`7780a561 kernel32!BaseThreadInitThunk+0xd                                                                   
        00000000`002efc10 00000000`00000000 ntdll!RtlUserThreadStart+0x1d                                                                      

陷阱帧由 制作nt!KiSystemCall64,其中有一个名为 的标签nt!KiSystemServiceCopyEnd,在这种情况下,它会调用系统服务nt!NtWaitForSingleObject。陷阱帧是第一个堆栈帧,因此是内核堆栈上rsp的函数,从函数的 (Child-SP)nt!KiSystemCall64开始,并从它为下一个函数分配的主空间开始。的第一条指令nt!KiSystemCall64是和inswapgs交换,然后存入KPCR 中的字段,再存入KPRCB中的字段,这明显是用户与内核的交换gsgsIA32_KERNEL_GS_BASErspgs:10hUserRspgs:1A8hrspRspBasersprsp对于线程,该线程缓存在当前运行该线程的 KPRCB 的超线程中。然后它开始构建陷阱帧,根据定义,rsp当前指向0x190陷阱帧中的偏移量(帧结束后的字节),从 push 开始,因为当您使用而不是SS时 CPU 不会执行此操作。syscallint 0x2e

当使用基指针时,陷阱帧将比ebp它上面的帧少 8 (减去ebp和返回地址,每个 4 个字节),所以帧nt!NtWaitForSingleObject

异常有一个异常帧,它使用 来存储非易失性寄存器nt!KiExceptionDispatchnt!KiBreakpointTrap例如在创建陷阱帧(以及由于处理器将和SS:RSP RFLAGS推送到堆栈以用于用户模式异常和到堆栈以获取内核模式异常,并且不从 KPCR / KPRCB 保存/加载任何内容)。创建一个异常帧,从堆栈跟踪中的下一个开始,紧接着在堆栈上,总组合大小为,因此您会看到堆栈指针之间的差异和CS:RIPErrorCodeRFLAGSCS:RIPErrorCoderspnt!KiExceptionDispatchKEXCEPTION_FRAMErspEXCEPTION_RECORD1D81E0nt!KiExceptionDispatchnt!KiBreakpointTrap当您将退货地址包含在nt!KiBreakpointTrap.

陷阱帧存储在内核中调用的函数数组期间内核可以破坏的所有寄存器,称为易失性寄存器,因为易失性寄存器保证在系统调用或异常期间不会更改。它不保存非易失性寄存器,因为在内核中调用的函数会保存它们使用的任何非易失性寄存器,因此当它返回此函数执行 asysret时,所有非易失性寄存器将是它们之前的值. 您需要一个用于异常的异常框架,因为它需要在执行堆栈展开的函数中知道异常发生时非易失性寄存器包含的内容,以便可以展开堆栈。在堆栈上创建一个CONTEXT结构nt!KiDispatchException表示异常发生时的完整上下文,它是非易失性和易失性寄存器状态的组合。

在交换线程上下文时,您还需要另一个异常帧,以便在线程切换出时保存非易失性寄存器的状态,因此这将是状态 in nt!KiSwapContext,因此可以在线程切换回时恢复。不需要保存易失性状态,因为假设调用SwapContext丢弃所有易失性寄存器。首先进入内核模式时创建的陷阱帧将用于在线程返回用户模式时将易失性寄存器上下文恢复到线程。

有趣的事实:对于断点异常INT 3,CPU 在断点指令结束后推送rip开始,而不是断点指令,这意味着 Windows 需要递减地址,因此堆栈调用点的顶部rip位于陷阱帧中,而不是CPU推送的返回地址。

于 2021-03-27T05:52:43.337 回答