DynamoRIO / drmemory

Memory Debugger for Windows, Linux, Mac, and Android
Other
2.44k stars 262 forks source link

[win32] add win32k.sys NtGdi* syscall data #96

Closed derekbruening closed 9 years ago

derekbruening commented 9 years ago

From derek.br...@gmail.com on December 10, 2010 17:57:33

PR 406349

currently I'm doing memcmp to see what has been written by the win32k.sys syscalls, to avoid false positives. we need to add data on the reads in order to avoid false negatives, however.

recording my old notes on handling win32k.sys syscalls (I implemented #3):

so our choices are: 1) have list of syscall numbers per windows version, and list of params read/written for each 2) operate at win32 layer instead, and have list of what args are written by lower-down syscall instead of by code we see? disadvantage is that our shadow updates will be too early/late vs actual syscall, and we'll miss hand-rolled syscalls. plus we may not be able to easily match exported API routines with syscalls: some internal routines may call multiple syscalls, etc. 3) give up on checking reads, but dynamically identify writes by storing a copy of all memory pointed at by valid-looking pointer args and diffing post-syscall. I don't have data on all the NtUser* syscalls anyway (unless can guess at win32 API versions) so can't check all reads regardless. subject to corner case races between post-syscall and check.

more notes:

gui-inject.exe has these win32k.sys syscalls w/ out params that matter: 0x10d7 GDI32!NtGdiGetWidthTable but who calls this from win32 API level? GDI32!bFillWidthTableForGTE+0xe3: 0x10ce GDI32!NtGdiGetTextMetricsW 0x11b2 USER32!NtUserGetThreadState 0x1090 GDI32!NtGdiExtGetObjectW

diffing syscall out params: my diff impl: look for pointer args whose targets start undefined (already worried there about missing IN/OUT structs where you set some flags or sthg in a field) and consider up until hit a non-undefined byte. round to dwords and compare afterward by dwords, since too many misses if only consider bytes where uninitialized value happened to match written value. Nearly everything is aligned to at least dword. Strings are the exception and there it's possible we'll mark beyond their length as defined...

I also mark an unchanged 0 dword as defined. Yes, I am worried about false negatives from this if unrelated uninitialized memory that happens to be 0 is adjacent to syscall params. I put it in b/c gui-inject.exe has a 0 dword in the middle of the output from 0x10ce=GDI32!NtGdiGetTextMetricsW that (a few rep movs copies later) shows up as an uninitialized read if we don't mark it defined. I don't want to limit to having changes after the 0 dword b/c there could be structs with tails that are 0 that happened to be 0 uninitialized?

That NtGdiGetTextMetricsW example also shows the dangers. It only has 3 params, but we think param 4 was changed, and consider param 5. param 4's changes happen to be an overlap w/ param 1:

NtGdiGetTextMetricsW(
    __in HDC hdc,
    __out_bcount(cj) TMW_INTERNAL * ptm,
    __in ULONG cj
    );
ignoring system call #0x10ce
pre-unknown-syscall #0x10ce: param 0 == 0xd80104a7
pre-unknown-syscall #0x10ce: param 1 == 0x0012f8ec 68 bytes
pre-unknown-syscall #0x10ce: param 2 == 0x00000044
pre-unknown-syscall #0x10ce: param 3 == 0x001544ac
pre-unknown-syscall #0x10ce: param 4 == 0x0012f954 64 bytes
pre-unknown-syscall #0x10ce: param 5 == 0x77c40020
unknown-syscall #0x10ce: param 1 written 0x0012f8ec 68 bytes
unknown-syscall #0x10ce: param 4 written 0x0012f958 52 bytes

the later rep movs implies that perhaps param 1 was only 60 bytes, but the cj param 0x44=68 implies that we were correct in the first place:

rep movs 0x0012f954 0x0012f8ec 0xf
memref: write @0x77c06172 0x0012f954 0x3c bytes (pre-dword 0xff)

Original issue: http://code.google.com/p/drmemory/issues/detail?id=96

derekbruening commented 9 years ago

From bruen...@google.com on May 30, 2011 07:30:35

MessageBox syscalls (i.e., gui-inject) split off as issue #426

derekbruening commented 9 years ago

From bruen...@google.com on June 27, 2011 10:50:18

issue #388 has laid the groundwork for adding these w/ a table of numbers and names

the vista sp0 to sp1 transition didn't change any numbers but did change some parameters, which will be special-cased:

57c56 < syscall # 0x1165 pdb 28 args = NtUserCreateWindowStation

syscall # 0x1165 pdb 32 args = NtUserCreateWindowStation 229c226 < syscall # 0x11d8 pdb 28 args = NtUserLoadKeyboardLayoutEx

syscall # 0x11d8 pdb 32 args = NtUserLoadKeyboardLayoutEx

Status: Started
Owner: bruen...@google.com
Labels: -Priority-Low Priority-Medium

derekbruening commented 9 years ago

From bruen...@google.com on June 28, 2011 07:19:14

TOT calc startup+shutdown on win7 laptop 749 unique, 173501 total uninitialized access(es)

next step: script to pull in NtGdi headers which have nice param annotations

derekbruening commented 9 years ago

From bruen...@google.com on July 07, 2011 08:02:56

split off the NtUser* syscalls as issue #484

Summary: [win32] add win32k.sys NtGdi* syscall data

derekbruening commented 9 years ago

From bruen...@google.com on July 08, 2011 11:40:51

a handful of corner cases are split into issue #485 resolving this issue: we now have handling for 381 NtGdi syscalls

Status: Verified

derekbruening commented 9 years ago

From bruen...@google.com on July 08, 2011 12:02:14

full mksystable.pl-generated table + manual fixes (just missing issue #485 ): 70 unique, 1558 total uninitialized access(es)

for xp wow64 calc: TOT calc startup+shutdown on xp64x2cpu VM 79 unique, 1365 total uninitialized access(es)

derekbruening commented 9 years ago

From derek.br...@gmail.com on July 15, 2011 11:30:16

This issue was closed by revision r370 .

Status: Fixed