1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Memory Dump Analysis Anthology- P3 doc

30 516 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Minidump Analysis
Trường học University of Information Technology
Chuyên ngành Computer Science
Thể loại Thesis
Năm xuất bản 2004
Thành phố Ho Chi Minh City
Định dạng
Số trang 30
Dung lượng 629,1 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Minidump Analysis 63 SYMBOLS AND IMAGES Suppose we have a minidump with a stack trace that involves our product driver and due to some reason WinDbg doesn’t pick symbols automatically

Trang 1

Minidump Analysis 61

0: kd> lmv m dxg

start end module name

bf9c3000 bf9d4580 dxg (pdb symbols)

Loaded symbol image file: dxg.sys

Mapped memory image file: c:\websymbols\dxg.sys\41107B9311580\dxg.sys

Image path: dxg.sys

Image name: dxg.sys

Timestamp: Wed Aug 04 07:00:51 2004 (41107B93)

CheckSum: 0001D181

ImageSize: 00011580

File version: 5.1.2600.2180

Product version: 5.1.2600.2180

File flags: 0 (Mask 3F)

File OS: 40004 NT Win32

File type: 3.7 Driver

File date: 00000000.00000000

Translations: 0409.04b0

CompanyName: Microsoft Corporation

ProductName: Microsoft® Windows® Operating System

InternalName: dxg.sys

OriginalFilename: dxg.sys

ProductVersion: 5.1.2600.2180

FileVersion: 5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)

FileDescription: DirectX Graphics Driver

LegalCopyright: © Microsoft Corporation All rights reserved

0: kd> lmv m win32k

start end module name

bf800000 bf9c2180 win32k # (pdb symbols)

Loaded symbol image file: win32k.sys

Mapped memory image file:

c:\websymbols\win32k.sys\45F013F61c2180\win32k.sys

Image path: win32k.sys

Image name: win32k.sys

Timestamp: Thu Mar 08 13:47:34 2007 (45F013F6)

CheckSum: 001C4886

ImageSize: 001C2180

File version: 5.1.2600.3099

Product version: 5.1.2600.3099

File flags: 0 (Mask 3F)

File OS: 40004 NT Win32

File type: 3.7 Driver

File date: 00000000.00000000

Translations: 0406.04b0

CompanyName: Microsoft Corporation

ProductName: Microsoft® Windows® Operativsystem

Trang 3

Minidump Analysis 63

SYMBOLS AND IMAGES

Suppose we have a minidump with a stack trace that involves our product driver

and due to some reason WinDbg doesn’t pick symbols automatically and shows the

following stack trace and crash address pointing to driver.sys module:

start end module name

bfa9e000 bfb42a00 driver T (no symbols)

Loaded symbol image file: driver.sys

Image path: driver.sys

Image name: driver.sys

Timestamp: Thu Mar 01 20:50:04 2007 (45E73C7C)

CheckSum: 000A5062

ImageSize: 000A4A00

Translations: 0000.04b0 0000.04e0 0409.04b0 0409.04e0

We see that no symbols for driver.sys were found and this is also indicated by the

absence of function names and the presence of huge code offsets like 0x2df2a

Perhaps we don’t have a symbol server and store our symbol files somewhere Or we

got symbols from the developer of the recent fix that bugchecks and we want to apply

them In any case if we add a path to Symbol Search Path dialog (File -> Symbol File Path

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 4

…) or use sympath WinDbg command we are able to get better stack trace and crash

point:

1: kd> reload

Loading Kernel Symbols

Loading User Symbols

Loading unloaded module list

Unable to load image driver.sys, Win32 error 0n2

*** WARNING: Unable to verify timestamp for driver.sys

1: kd> kL

ChildEBP RetAddr

ba0fd0c0 bfabc399 driver!ProcessBytes+0×18

ba0fd0e4 bfabd64b driver!ProcessObject+0xc9

Because WinDbg reports that it was unable to verify timestamp for driver.sys we

might want to double check the return address saved when ProcessBytes function was

called If symbols are correct then disassembling the return address backwards will most

Trang 5

Minidump Analysis 65 likely show ProcessObject function code and “call” instruction with ProcessBytes

address Unfortunately minidumps don’t have code except for the currently executing

No code found, aborting

Therefore we need to point WinDbg to our driver.sys which contains executable

code This can be done by specifying a path in Executable Image Search Path dialog

(File -> Image File Path …) or using exepath WinDbg command

Now we get more complete stack trace and we are able to double check the

re-turn address:

1: kd> reload

Loading Kernel Symbols

Loading User Symbols

Loading unloaded module list

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 6

1: kd> kL

ChildEBP RetAddr

ba0fd0c0 bfabc399 driver!ProcessBytes+0×18

ba0fd0e4 bfabd64b driver!ProcessObject+0xc9

ba0fd104 bfac5aac driver!CacheBitBlt+0×13d

ba0fd114 bfac6840 driver!ProcessCommand+0×150

ba0fd140 bfac1878 driver!CheckSurface+0×258

ba0fd178 bfaba0ee driver!CopyBitsEx+0xfa

bfabc387 57 push edi

bfabc388 40 inc eax

bfabc389 50 push eax

bfabc38a e861fb0000 call driver!convert (bfacbef0)

bfabc38f ff7508 push dword ptr [ebp+8]

bfabc392 57 push edi

bfabc393 50 push eax

bfabc394 e879fb0000 call driver!ProcessBytes (bfacbf12)

Trang 7

Minidump Analysis 67

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 8

INTERRUPTS AND EXCEPTIONS EXPLAINED

EXCEPTIONS AB INITIO

Where do native exceptions come from? How do they propagate from hardware

and eventually result in crash dumps? I was asking these questions when I started doing

crash dump analysis more than four years ago and I tried to find answers using IA-32

Intel® Architecture Software Developer’s Manual, WinDbg and complete memory

dumps Let’s look at some findings

Trang 9

Interrupts and Exceptions Explained 69

X86 INTERRUPTS

How do exceptions happen in the first place and how does the execution flow

reach KiDispatchException function? When some abnormal condition happens such as a

breakpoint, division by zero or memory protection violation then the normal CPU

execu-tion flow (code stream) is interrupted (I use the terms “interrupt” and “excepexecu-tion”

interchangeably here) The type of interrupt is specified by a number called interrupt

vector number CPU has to transfer execution to some procedure in memory to handle

that interrupt CPU has to find that procedure, theoretically either having one procedure

for all interrupts and specifying an interrupt vector number as a parameter or having a

table containing pointers to various procedures that correspond to different interrupt

vectors Intel x86 and x64 CPUs use the latter approach which is depicted on the

follow-ing diagram:

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 10

KiTrap00 (808347ca)

KiTrap01 (8083494a) KiTrap02 (80834a3d)

808347d4 push ebx 808347d5 push esi 808347d6 push edi 808347d7 push fs 808347d9 mov ebx,30h 808347de mov fs,bx 808347e0 mov ebx,dword ptr fs:[0]

808347e7 push ebx

Trang 11

Interrupts and Exceptions Explained 71

When an exception happens, for example, divide by zero, CPU gets the address

of the procedure table from IDTR (Interrupt Descriptor Table Register) This IDT

(Inter-rupt Descriptor Table) is a zero-based array of 8-byte descriptors (x86) or 16-byte

descriptors (x64) CPU calculates the location of the necessary procedure to call and

does some necessary steps like saving appropriate registers before the call

The same happens when some external I/O device interrupts For I/O devices the

term “interrupt” is more appropriate On the picture above I/O hardware interrupt

vec-tor numbers were taken from some crash dump These are OS and user-defined

num-bers The first 32 vectors are reserved by Intel Before Windows switches CPU to

pro-tected mode during boot process it creates IDT table in memory and sets IDTR to point

to it by using SIDT instruction

Let me now illustrate this by using a UML class diagram annotated by

code that shows what CPU does before calling the appropriate procedure The

pseudo-code on the diagram below is valid for interrupts and exceptions happening when

the current CPU execution mode is kernel For interrupts and exceptions

gener-ated when CPU executes code in user mode the picture is a little more complicgener-ated

because the processor has to switch the current user-mode stack to kernel mode stack

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 12

The following diagram is for 32-bit x86 processor:

Offset(0 15) : Uint2BSelector : Uint2BAccess : Uint2BExtendedOffset(16 31) : Uint2B

IDT[VectorNumber].ExtendedOffset<<16 + IDT[VectorNumber].Offset

Let’s see all this in some kernel memory dump The address of IDT can be found

by using !pcr [processor number] command Every processor on a multiprocessor

ma-chine has its own IDT:

Trang 13

Interrupts and Exceptions Explained 73

Every entry in IDT has the type _KIDTENTRY and we can get the first entry for

di-vide by zero exception which has vector number 0:

By gluing together ExtendedOffset and Offset fields we get the address of the

interrupt handling procedure (0×808347ca) which is KiTrap00:

0: kd> ln 0x808347ca

(808347ca) nt!KiTrap00 | (808348a5) nt!Dr_kit1_a

Exact matches:

nt!KiTrap00

We can also see the interrupt trace in raw stack For example, we have the

following stack trace and registers in the output of !analyze -v command:

Trang 14

Dumping memory around ESP value (f2178c1c) shows the values processor

pushes when divide by zero exception happens:

Trang 15

Interrupts and Exceptions Explained 75

ErrorCode is not the same as interrupt vector number although it is the same

number here (0) I won’t cover interrupt error codes here If you are interested please

consult Intel Architecture Software Developer’s Manual

If we try to execute !idt extension command it will show us only user-defined

hardware interrupt vectors:

93: 89f1e044 SCSIPORT!ScsiPortInterrupt (KINTERRUPT 89f1e008)

a3: 894fa044 USBPORT!USBPORT_InterruptService (KINTERRUPT 894fa008)

a4: 894a3044 cpqcidrv+0×22AE (KINTERRUPT 894a3008)

b1: 89f697dc ACPI!ACPIInterruptServiceRoutine (KINTERRUPT 89f697a0)

b3: 89498824 i8042prt!I8042KeyboardInterruptService (KINTERRUPT 894987e8)

b4: 894a2044 cpqasm2+0×5B99 (KINTERRUPT 894a2008)

c1: 80a7d410 hal!HalpBroadcastCallService

d1: 80a7c754 hal!HalpClockInterrupt

e1: 80a7d830 hal!HalpIpiHandler

e3: 80a7d654 hal!HalpLocalApicErrorService

fd: 80a7e11c hal!HalpProfileInterrupt

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 16

X64 INTERRUPTS

Now I describe changes in 64-bit Windows The size of IDTR is 10 bytes where 8

bytes hold 64-bit address of IDT The size of IDT entry is 16 bytes and it holds the

ad-dress of an interrupt procedure corresponding to an interrupt vector However interrupt

procedure names are different in x64 Windows, they do not follow the same pattern like

KiTrapXX

The following UML class diagram describes the relationship and also shows what

registers are saved In native x64 mode SS and RSP are saved regardless of kernel or user

mode

OffsetLow(0 15) : Uint2BSelector : Uint2BAccess : Uint2BOffsetMiddle(16 31) : Uint2BOffsetHigh(32:63) : Uint4BReserverd : Uint4B

IDT[VectorNumber].OffsetHigh<<32 + IDT[VectorNumber].OffsetMiddle<<16 + IDT[VectorNumber].OffsetLow

Let’s dump all architecture-defined interrupt procedure names This is a good

exercise because we will use WinDbg scripting !pcr extension reports wrong IDT base

so we use dt command:

Trang 17

Interrupts and Exceptions Explained 77

Trang 18

Next we dump the first entry of IDT array and glue together OffsetHigh,

OffsetMiddle and OffsetLow fields to form the interrupt procedure address

correspond-ing to the interrupt vector 0, divide by zero exception:

fffff800`0103f254 c645ab01 mov byte ptr [rbp-55h],1

fffff800`0103f258 488945b0 mov qword ptr [rbp-50h],rax

nt!KiDivideErrorFault = <no type information>

We see that the name of the procedure is KiDivideErrorFault and not KiTrap00

We can dump the second IDT entry manually by adding a 0×10 offset but in order to

automate this I wrote the following WinDbg script to dump the first 20 vectors and get

their interrupt procedure names:

r? $t0=(_KIDTENTRY64 *)0xfffff800`00124070; for (r $t1=0; @$t1 <= 13; r?

$t0=(_KIDTENTRY64 *)@$t0+1) { printf ―Interrupt vector %d (0x%x):\n‖,

@$t1, @$t1; ln @@c++(>OffsetHigh*0×100000000 +

@$t0->OffsetMiddle*0×10000 + @$t0->OffsetLow); r $t1=$t1+1 }

Trang 19

Interrupts and Exceptions Explained 79

Here is the same script but formatted:

nt!KiInvalidOpcodeFault = <no type information>

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 20

nt!KiNpxSegmentOverrunAbort = <no type information>

Interrupt vector 10 (0xa):

nt!KiGeneralProtectionFault = <no type information>

Interrupt vector 14 (0xe):

Trang 21

Interrupts and Exceptions Explained 81

nt!KiXmmException = <no type information>

Let’s look at some dump

BugCheck 1E, {ffffffffc0000005, fffffade5ba2d643, 0, 28}

This is KMODE_EXCEPTION_NOT_HANDLED bugcheck and obviously it could have

been an invalid memory access And indeed the stack WinDbg shows after opening a

dump and entering !analyze -v command is:

Last set context:

rax=fffffade4e8907f4 rbx=fffffade6de0c2e0 rcx=fffffa8014412000

rdx=fffffade71e7e2ac rsi=0000000000000000 rdi=fffffadffff03000

rip=fffffade5ba2d643 rsp=fffffade4e890780 rbp=fffffade71e7ffff

fffffade`5ba2d643 8b4e28 mov ecx,dword ptr [rsi+28h] ds:0950:0028=????????

KiPageFault function was called and from the dumped IDT we see that it

corres-ponds to the interrupt vector 14 (0xE) called on any memory reference that is not

present in physical memory

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Trang 22

Now I’m going to dump the raw stack around fffffade`4e890780 address to see

data the processor saved before calling KiPageFault function:

We see that the values are exactly the same as WinDbg shows in the saved

con-text above Actually if we look at Page Fault Error Code bits in Intel Architecture

Soft-ware Developer’s Manual Volume 3A, you would see that for this case, all zeroes, we

have:

the page was not present in memory

the fault was caused by the read access

the processor was executing in kernel mode

no reserved bits in page directory were set to 1 when 0s were expected

it was not caused by instruction fetch

Trang 23

Interrupts and Exceptions Explained 83

INTERRUPT FRAMES AND STACK RECONSTRUCTION

When an interrupt happens and an x86 processor is in privileged protected mode

(ring 0) it pushes interrupt frame shown in the following pseudo-code:

This is an interrupt frame that is created by CPU and not a trap frame created by

a software interrupt handler to save CPU state (_KTRAP_FRAME)

If an interrupt happens when an x86 processor is in user mode (ring 3) then the

stack switch occurs before the processor saves user mode stack pointer SS:ESP and

pushes the rest of the interrupt frame Pushing both SS:RSP always happens on x64

processor regardless of the current execution mode, kernel or user The following x86

pseudo-code shows how interrupt frame is pushed on the current stack (to be precise,

on the kernel space stack if the interrupt happened in user mode):

Usually CS is 0×1b and SS is 0×23 for x86 Windows flat memory model so we can

easily identify this pattern on raw stack data

Why should we care about an interrupt frame? This is because in complete

mem-ory dumps we can see exceptions that happened in user space and processed at the

time the dump was saved

Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Ngày đăng: 15/12/2013, 11:15

TỪ KHÓA LIÊN QUAN

w