Stack (GS) Cookies and Stop 0xF7

x BlueRobot

Administrator
Staff member
Joined
May 7, 2013
Posts
10,400
I was just reading a thread over at another forum since it mentioned a Stop 0xF7 bugcheck, and while the dump file doesn't reveal the exact culprit, I was curious about why the bugcheck was produced. I found particularly interesting because usually these bugchecks are produced when the stack cookie has been overwritten, however, in this case it will due to a single bit error.

Rich (BB code):
DRIVER_OVERRAN_STACK_BUFFER (f7)
A driver has overrun a stack-based buffer.  This overrun could potentially
allow a malicious user to gain control of this machine.
DESCRIPTION
A driver overran a stack-based buffer (or local variable) in a way that would
have overwritten the function's return address and jumped back to an arbitrary
address when the function returned.  This is the classic "buffer overrun"
hacking attack and the system has been brought down to prevent a malicious user
from gaining complete control of it.
Do a kb to get a stack backtrace -- the last routine on the stack before the
buffer overrun handlers and bugcheck call is the one that overran its local
variable(s).
Arguments:
Arg1: fffe000027008e65, Actual security check cookie from the stack
Arg2: fffe000027008e65, Expected security check cookie
Arg3: ffff878ed8ff719a, Complement of the expected security check cookie
Arg4: 0000000000000000, zero

In most circumstances, the first and second parameters are very different from each other, and therefore it's obvious that the stack cookie has been overwritten. At first, I admit I was little thrown off and was wondering why it didn't like the stack cookie. It turns out, the higher (last) 16 bits must be set to 0xFFFF otherwise the stack cookie validation will fail.

Rich (BB code):
6: kd> knL
# Child-SP          RetAddr           Call Site
00 ffffb90a`12c53748 fffff801`7c0b0cd5 nt!KeBugCheckEx
01 ffffb90a`12c53750 fffff801`7be1ae1a nt!_report_gsfailure+0x25
02 ffffb90a`12c53790 fffff801`7c1edbd4 nt!MiMakeHyperRangeAccessible+0x35a << Crash here!
03 ffffb90a`12c53920 fffff801`7c233150 nt!MiCommitPageTablesForVad+0xb4
04 ffffb90a`12c539c0 fffff801`7c232abe nt!MiInsertVadCharges+0x150
05 ffffb90a`12c53a10 fffff801`7c23230c nt!MiMapViewOfDataSection+0x42e
06 ffffb90a`12c53b40 fffff801`7c233d79 nt!MiMapViewOfSection+0x34c
07 ffffb90a`12c53c90 fffff801`7c0075b8 nt!NtMapViewOfSection+0x159
08 ffffb90a`12c53dd0 00007ff9`f282d114 nt!KiSystemServiceCopyEnd+0x28
09 00000000`002c89b8 00000000`00000000 0x00007ff9`f282d114

Rich (BB code):
6: kd> ub fffff801`7be1ae1a
nt!MiMakeHyperRangeAccessible+0x33a:
fffff801`7be1adfa 483bd8          cmp     rbx,rax
fffff801`7be1adfd 0f8535022000    jne     nt!MiMakeHyperRangeAccessible+0x200578 (fffff801`7c01b038)
fffff801`7be1ae03 4885ff          test    rdi,rdi
fffff801`7be1ae06 0f8521010000    jne     nt!MiMakeHyperRangeAccessible+0x46d (fffff801`7be1af2d)
fffff801`7be1ae0c 33c0            xor     eax,eax
fffff801`7be1ae0e 488b4d40        mov     rcx,qword ptr [rbp+40h]
fffff801`7be1ae12 4833cc          xor     rcx,rsp
fffff801`7be1ae15 e8f6111b00      call    nt!_security_check_cookie (fffff801`7bfcc010)

The _security_check_cookie function is responsible for validating and ensuring that the cookie is valid, otherwise we throw an exception and cause a Stop 0xF7 bugcheck to be produced.

Rich (BB code):
6: kd> u fffff801`7bfcc010
nt!_security_check_cookie:
fffff801`7bfcc010 483b0d49628400  cmp     rcx,qword ptr [nt!_security_cookie (fffff801`7c812260)] << Compare the generated cookie and the one present on the stack
fffff801`7bfcc017 7510            jne     nt!_security_check_cookie+0x19 (fffff801`7bfcc029)
fffff801`7bfcc019 48c1c110        rol     rcx,10h
fffff801`7bfcc01d 66f7c1ffff      test    cx,0FFFFh << Check the high 16-bits; remember the h postfix means hexadecimal format, so it's comparing the 16-bits of the rcx register to 0xFFFF
fffff801`7bfcc022 7501            jne     nt!_security_check_cookie+0x15 (fffff801`7bfcc025) << Validate the security cookie, and then fail
fffff801`7bfcc024 c3              ret
fffff801`7bfcc025 48c1c910        ror     rcx,10h
fffff801`7bfcc029 e9824c0e00      jmp     nt!_report_gsfailure (fffff801`7c0b0cb0)

If we dump the security cookie from the stack as binary, then we can see why the pattern match failed.

Rich (BB code):
6: kd> .formats fffe000027008e65
Evaluate expression:
  Hex:     fffe0000`27008e65
  Decimal: -562949299073435
  Octal:   1777760000004700107145
  Binary:  11111111 11111110 00000000 00000000 00100111 00000000 10001110 01100101
  Chars:   ....'..e
  Time:    ***** Invalid FILETIME
  Float:   low 1.78408e-015 high -1.#QNAN
  Double:  -1.#QNAN

11111111 11111110 = 0xFFFE
11111111 11111111 = 0xFFFF


Notice the single bit error? Hence why the failure bucket string states:

Rich (BB code):
FAILURE_BUCKET_ID:  0xF7_ONE_BIT_MISSING_GSFRAME_nt!_report_gsfailure

The _report_gs_failure simply set ups the stack frame for our bugcheck call.

Rich (BB code):
6: kd> u fffff801`7c0b0cb0
nt!_report_gsfailure:
fffff801`7c0b0cb0 4883ec38        sub     rsp,38h
fffff801`7c0b0cb4 488364242000    and     qword ptr [rsp+20h],0
fffff801`7c0b0cba 488bd1          mov     rdx,rcx
fffff801`7c0b0cbd 4c8b0da4157600  mov     r9,qword ptr [nt!_security_cookie_complement (fffff801`7c812268)]
fffff801`7c0b0cc4 b9f7000000      mov     ecx,0F7h
fffff801`7c0b0cc9 4c8b0590157600  mov     r8,qword ptr [nt!_security_cookie (fffff801`7c812260)]
fffff801`7c0b0cd0 e87b4ff4ff      call    nt!KeBugCheckEx (fffff801`7bff5c50)
fffff801`7c0b0cd5 cc              int     3

That's all! I just thought I would share it with everyone in case you wondering like I was.
 

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top