The IP used to be a CPU register.
Malfunction here would execute various memory locations that actually exist (assuming correct fetchs),
just not in the correct, or intended order.
Any links to the issue called
instruction pointer misalignment?
I'm not trying to be a wise-azz here, just trying to learn a little bit more.
I salute you for being interested in old-school computery stuff :)
I'll aim to explain the "what" first, then the why...Here's the stack of the crashing thread at the time the user sees blue:
Code:
0: kd> kv
Child-SP RetAddr : Args to Child : Call Site
fffff880`031af358 fffff800`02c884e9 : 00000000`0000000a 00000000`00000020 00000000`00000002 00000000`00000001 : nt!KeBugCheckEx
fffff880`031af360 fffff800`02c87160 : 00000000`00000000 00000000`00000004 00000000`00000000 00000000`00000000 : nt!KiBugCheckDispatch+0x69
fffff880`031af4a0 fffff880`014e7f4b : 00000000`00000001 fffff880`01687391 00000000`00000014 fffffa80`00000000 : nt!KiPageFault+0x260 (TrapFrame @ fffff880`031af4a0)
fffff880`031af630 00000000`00000001 : fffff880`01687391 00000000`00000014 fffffa80`00000000 00000000`00000014 : ndis+0x1f4b
fffff880`031af638 fffff880`01687391 : 00000000`00000014 fffffa80`00000000 00000000`00000014 00000000`00000010 : 0x1
fffff880`031af640 00000000`00000014 : fffffa80`00000000 00000000`00000014 00000000`00000010 00000000`00000000 : tcpip+0x7f391
fffff880`031af648 fffffa80`00000000 : 00000000`00000014 00000000`00000010 00000000`00000000 00000000`000007be : 0x14
fffff880`031af650 00000000`00000014 : 00000000`00000010 00000000`00000000 00000000`000007be 00000000`00000078 : 0xfffffa80`00000000
fffff880`031af658 00000000`00000010 : 00000000`00000000 00000000`000007be 00000000`00000078 fffff880`014028b1 : 0x14
fffff880`031af660 00000000`00000000 : 00000000`000007be 00000000`00000078 fffff880`014028b1 fffff880`00000001 : 0x10
And the register context:
Code:
0: kd> r
rax=fffff880031af460 rbx=0000000000000004 rcx=000000000000000a
rdx=0000000000000020 rsi=0000000000000000 rdi=0000000000000000
rip=fffff80002c88f80 rsp=fffff880031af358 rbp=fffff880031af520
r8=0000000000000002 r9=0000000000000001 r10=fffff880014e7f4b
r11=fffff6fb40000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei ng nz na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000286
nt!KeBugCheckEx:
fffff800`02c88f80 48894c2408 mov qword ptr [rsp+8],rcx ss:0018:fffff880`031af360=000000000000000a
But that's not the crashing code - that's the "last resort" mechanism which elevates IRQL to 31 (the highest), thereby interrupting any and all other activity in order to dump physical memory to disk because an irrecoverable error has occurred.
To see the crashing code, we'd have to set the register context as it looked at the time of the fault. Thankfully, the OS dumps a trap frame (in red above) which records that info. To change the context:
Code:
0: kd> .trap fffff880`031af4a0
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000008 rbx=0000000000000000 rcx=fffffa8004861b80
rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000
rip=fffff880014e7f4b rsp=fffff880031af630 rbp=fffffa8004861a00
r8=0000000000000000 r9=0000000000000000 r10=fffffa8004861c00
r11=fffff880031af938 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl nz na pe cy
ndis+0x1f4b:
fffff880`014e7f4b 896e20 mov dword ptr [rsi+20h],ebp ds:5c70:00000000`00000020=????????
OK, so the immediate cause of a crash is a function supposedly at ndis+0x1f4b which tries to move the contents of EBP into the memory address pointed at by RSI plus 0x20 bytes. Trouble is, RSI happens to be zero at the time, so the instruction turns into an attempt to write to memory address 0x20, which is not only in user-mode but also within the first 64KB "guard" block which is always designated no-access in order to catch null pointer references.
Note the (64-bit) RIP instruction pointer though: rip=fffff880014e7f4b
So the offending function which causes the crash (in green) is supposedly at that address, pointed up by RIP. Let's disassemble the code around that address:
Code:
0: kd> u fffff880`014e7f4b
ndis+0x1f4b:
fffff880`014e7f4b 896e20 mov dword ptr [rsi+20h],ebp
fffff880`014e7f4e 48897e08 mov qword ptr [rsi+8],rdi
fffff880`014e7f52 48897e10 mov qword ptr [rsi+10h],rdi
fffff880`014e7f56 48897e18 mov qword ptr [rsi+18h],rdi
fffff880`014e7f5a 48897e38 mov qword ptr [rsi+38h],rdi
fffff880`014e7f5e 48897e30 mov qword ptr [rsi+30h],rdi
fffff880`014e7f62 48897e68 mov qword ptr [rsi+68h],rdi
fffff880`014e7f66 48897e60 mov qword ptr [rsi+60h],rdi
For reasons not simple to explain succinctly, that looks a little odd. Let's start the disassembly a bit higher up:
Code:
0: kd> u fffff880`014e7f40
ndis+0x1f40:
fffff880`014e7f40 f6 ???
fffff880`014e7f41 0f8413840100 je ndis+0x1a35a (fffff880`0150035a)
fffff880`014e7f47 48893e mov qword ptr [rsi],rdi
fffff880`014e7f4a 48896e20 mov qword ptr [rsi+20h],rbp
fffff880`014e7f4e 48897e08 mov qword ptr [rsi+8],rdi
fffff880`014e7f52 48897e10 mov qword ptr [rsi+10h],rdi
fffff880`014e7f56 48897e18 mov qword ptr [rsi+18h],rdi
fffff880`014e7f5a 48897e38 mov qword ptr [rsi+38h],rdi
Hold on, that looks different, although it's still not right because I happen to have arbitrarily started disassembly in the middle of an instruction. Let's go back a little more:
Code:
0: kd> u fffff880`014e7f3a
ndis+0x1f3a:
fffff880`014e7f3a 8b6c2430 mov ebp,dword ptr [rsp+30h]
fffff880`014e7f3e 4885f6 test rsi,rsi
fffff880`014e7f41 0f8413840100 je ndis+0x1a35a (fffff880`0150035a)
fffff880`014e7f47 48893e mov qword ptr [rsi],rdi
fffff880`014e7f4a 48896e20 mov qword ptr [rsi+20h],rbp
fffff880`014e7f4e 48897e08 mov qword ptr [rsi+8],rdi
fffff880`014e7f52 48897e10 mov qword ptr [rsi+10h],rdi
fffff880`014e7f56 48897e18 mov qword ptr [rsi+18h],rdi
That looks like real code. There's a "test" followed by a conditional jump (je), and then we're moving a bunch of structured info into memory starting with [RSI].
Note that there is no instruction at 0xfffff880`014e7f4b! There are (legit) instructions starting at '4a and '4e, but the attempt to execute an instruction starting at '4b (in red) leads to an inevitable mangling of the instruction itself.
Instead of this:
fffff880`014e7f4a 48896e20 mov qword ptr [rsi+20h],rbp
...RIP is one byte too far along and we're executing an instruction which doesn't exist:
fffff880`014e7f4b 896e20 mov dword ptr [rsi+20h],ebp
And as for the "why"... (to be continued)