Non-zero Code Integrity statistic found: Execute Pool Type Count

When I ran HLK for my old WDM driver for WIndows 10 64, I have got failures for HVCI code integrity test as below,

“WDTF_TEST : Non-zero Code Integrity statistic found: Execute Pool Type Count: == 71”

Could anybody help me to identify these violations in the code?
How to verify the actual allocations for IRP/MDL/MEMORY in my driver code, which making these failure count.?

Driver was built with WDK 7.

Steve Walkin wrote:

Could anybody help me to identify these violations in the code?

Use the ‘Code Integrity Check’ option of the Driver Verifier (Windows 10).

You?ll inevitably need to use POOL_NX_OPTIN:

https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/single-binary-opt-in-pool-nx-optin

-scott
OSR
@OSRDrivers

xxxxx@gmail.com wrote:

When I ran HLK for my old WDM driver for WIndows 10 64, I have got failures for HVCI code integrity test as below,

“WDTF_TEST : Non-zero Code Integrity statistic found: Execute Pool Type Count: == 71”

Could anybody help me to identify these violations in the code?
How to verify the actual allocations for IRP/MDL/MEMORY in my driver code, which making these failure count.?

I’d like to expand on Scott’s answer, which is the correct one.

The issue here is that, traditionally, memory allocations with
ExAllocatePool have been done with PagedPool or NonPagedPool.  Those
types allocate R/W/X pages.  In Windows 8, Microsoft added the
NonPagedPoolNx type, which allocated R/W pages that cannot be executed. 
Starting with Windows 10, you are now REQUIRED to use NonPagedPoolNx.

That presents a problem for multi-platform drivers, because
NonPagedPoolNx is not valid in Windows 7.  Scott’s reference describes
that workaround.

Personally, I do not understand why Microsoft didn’t simply redefine
NonPagedPool to mean R/W and add a new type, NonPagedPoolExecute.  That
would have been a MUCH less impactful solution.  Those very, very few
drivers that need R/W/X pages would have caused an easily correctable
BSOD, while the overwhelming majority of drivers that only needed R/W
could have continued life unimpeded.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks for your reply and suggestions, Aleh, Scott & Tim.

Let me see whether I can get it fixed with it.

I think the annoying reason to not make the much simpler change was to
retain compatibility binary with existing code, even if that code presented
a security risk. Although if it was my driver that suddenly stopped working
I would not find this annoying.

Mark Roddy

On Tue, Jan 9, 2018 at 12:44 PM, xxxxx@probo.com wrote:

> xxxxx@gmail.com wrote:
> > When I ran HLK for my old WDM driver for WIndows 10 64, I have got
> failures for HVCI code integrity test as below,
> >
> > “WDTF_TEST : Non-zero Code Integrity statistic found: Execute Pool Type
> Count: == 71”
> >
> > Could anybody help me to identify these violations in the code?
> > How to verify the actual allocations for IRP/MDL/MEMORY in my driver
> code, which making these failure count.?
>
> I’d like to expand on Scott’s answer, which is the correct one.
>
> The issue here is that, traditionally, memory allocations with
> ExAllocatePool have been done with PagedPool or NonPagedPool. Those
> types allocate R/W/X pages. In Windows 8, Microsoft added the
> NonPagedPoolNx type, which allocated R/W pages that cannot be executed.
> Starting with Windows 10, you are now REQUIRED to use NonPagedPoolNx.
>
> That presents a problem for multi-platform drivers, because
> NonPagedPoolNx is not valid in Windows 7. Scott’s reference describes
> that workaround.
>
> Personally, I do not understand why Microsoft didn’t simply redefine
> NonPagedPool to mean R/W and add a new type, NonPagedPoolExecute. That
> would have been a MUCH less impactful solution. Those very, very few
> drivers that need R/W/X pages would have caused an easily correctable
> BSOD, while the overwhelming majority of drivers that only needed R/W
> could have continued life unimpeded.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

I have used NonPagedPoolNx and thereby I am able to stripe out the Execute Pool Type Count completely. Thanks.

But I still have errors on “Section Alignment Failures =8” and “Execute-Write Section Count=1”.

The “Execute-Write Section Count=1” appearing only in Windows 10 10586 build, whereas all the later builds does not showing this error.

Any further insight for me resolve these failures.

Driver Compatibility with Device Guard
https://docs.microsoft.com/en-us/windows-hardware/test/hlk/testref/driver-compatibility-with-device-guard

How to build compatible drivers

* Don’t use sections that are both writable and executable

* Section Alignment must be a multiple of 0x1000 (PAGE_SIZE).
E.g. DRIVER_ALIGNMENT=0x1000

Wherever I used ExAllocatePoolWithTag , I have used the pool tag with a multiple of 0x100.

I have enabled the driver verifier and debugged remotely with Windbg. I am getting following 8 Code integrity issues.
How can I trace this .text, .rdata , .data etc to the code for page alignment issues ?
Since it is a Verifier crash, I am not able to debug even with the .pdb file in Windbg.
Any thoughts to identify the root cause of this failure ? Please help.

Driver Verifier: Enabled for driverxxx.sys, flags 0x2000000, build 10586, key xxxxxxxx
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF800873401F0 that is not page aligned (name .text).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF80087340218 that is not page aligned (name .rdata).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF80087340240 that is not page aligned (name .data).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF80087340268 that is not page aligned (name .pdata).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF80087340290 that is not page aligned (name .CRT).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF800873402B8 that is not page aligned (name INIT).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF800873402E0 that is not page aligned (name .rsrc).
**
*****************************************************************
*********** Verifier Detected a Code Integrity Issue ************
**
** The image driverxxx.sys contains section 0xFFFFF80087340308 that is not page aligned (name .reloc).
**
*****************************************************************

xxxxx@gmail.com wrote:

Wherever I used ExAllocatePoolWithTag , I have used the pool tag with a multiple of 0x100.

I don’t think that’s really what you meant, but it’s also not relevant
to this issue.

 

I have enabled the driver verifier and debugged remotely with Windbg. I am getting following 8 Code integrity issues.
How can I trace this .text, .rdata , .data etc to the code for page alignment issues ?
Since it is a Verifier crash, I am not able to debug even with the .pdb file in Windbg.
Any thoughts to identify the root cause of this failure ? Please help.

Yes.  The root cause is that, in your build, you have overridden the
default value for the linker’s /ALIGN parameter.  The default value of
/ALIGN is 4096, which results in all sections being page-aligned.  Some
people override that in a foolish attempt to save disk space for the
executable, but the kernel requires that sections actually have page
alignment.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I have added below ones into my build, still the page alignment issues persists.

First try.
LINKER_FLAGS=/ALIGN:4096

Second try.
LINKER_FLAGS=/SECTION:.text!RX,ALIGN:4096
DRIVER_ALIGNMENT=0x1000

Any idea of what is going wrong ?

xxxxx@gmail.com wrote:

I have added below ones into my build, still the page alignment issues persists.

First try.
LINKER_FLAGS=/ALIGN:4096

Second try.
LINKER_FLAGS=/SECTION:.text!RX,ALIGN:4096
DRIVER_ALIGNMENT=0x1000

You shouldn’t need either of those; 4096 is the default.  What is your
build environment?  Is that in a “sources” file?  If you look in the
buildxxx.log file, do you see an “align” value?  If you do “link /dump
/headers xxxx.sys”, what do you see for “section alignment”?  Are the
virtual addresses for the individual sections actually page aligned?

And, the stupid question, are you sure you’re testing with the newly
build driver?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

xxxxx@gmail.com wrote:

I have added below ones into my build, still the page alignment issues persists.

Any idea of what is going wrong ?

Is it possible you’re setting _NT_TARGET_VERSION to XP?  In XP, the
default driver alignment was only 0x80.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yes Tim, I am using build environment from “sources” file. In the buildxxx.log file shows align value as 1>/align:0x0080

So I specifically put _NT_TARGET_VERSION=$(_NT_TARGET_VERSION_LATEST) in the “sources” file and rebuilt. Still it is not page aligned.

Dump of file C:\VS-OLD\objfre_win7_amd64\amd64\driverxxx.sys

File Type: EXECUTABLE IMAGE

Summary

80 .CRT
A80 .data
1F00 .pdata
2200 .rdata
880 .reloc
480 .rsrc
40B00 .text
D80 INIT

On Feb 4, 2018, at 9:06 PM, xxxxx@gmail.com wrote:
>
> Yes Tim, I am using build environment from “sources” file. In the buildxxx.log file shows align value as 1>/align:0x0080

Well, that says you haven’t found the magic recipe yet. Are you doing a full/clean build each time? Just because you modify “sources” doesn’t mean it will actually redo the linking.

> So I specifically put _NT_TARGET_VERSION=$(_NT_TARGET_VERSION_LATEST) in the “sources” file and rebuilt. Still it is not page aligned.
>
> Dump of file C:\VS-OLD\objfre_win7_amd64\amd64\driverxxx.sys

This output is from “link /dump”, not from “link /dump /headers”.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

You said it right Tim. I did not get either the magic recipe or the proper headers :(.
I used to build “bld -cew” command every time i changes.

Here is the complete header details. I could see each section are “Not paged”. Can you guide more.

FILE HEADER VALUES
8664 machine (x64)
8 number of sections
5A780F9A time date stamp Mon Feb 05 13:32:34 2018
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
22 characteristics
Executable
Application can handle large (>2GB) addresses

OPTIONAL HEADER VALUES
20B magic # (PE32+)
9.00 linker version
41800 size of code
5880 size of initialized data
0 size of uninitialized data
459E4 entry point (00000000000559E4) GsDriverEntry
380 base of code
10000 image base (0000000000010000 to 00000000000573FF)
80 section alignment
80 file alignment
6.01 operating system version
6.01 image version
1.10 subsystem version
0 Win32 version
47400 size of image
380 size of headers
492AA checksum
1 subsystem (Native)
2000 DLL characteristics
WDM Driver
40000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 loader flags
10 number of directories
0 [0] RVA [size] of Export Directory
45A04 [50] RVA [size] of Import Directory
46700 [438] RVA [size] of Resource Directory
43A00 [1ECC] RVA [size] of Exception Directory
0 [0] RVA [size] of Certificates Directory
46B80 [510] RVA [size] of Base Relocation Directory
41150 [1C] RVA [size] of Debug Directory
0 [0] RVA [size] of Architecture Directory
0 [0] RVA [size] of Global Pointer Directory
0 [0] RVA [size] of Thread Storage Directory
0 [0] RVA [size] of Load Configuration Directory
0 [0] RVA [size] of Bound Import Directory
40E00 [350] RVA [size] of Import Address Table Directory
0 [0] RVA [size] of Delay Import Directory
0 [0] RVA [size] of COM Descriptor Directory
0 [0] RVA [size] of Reserved Directory

SECTION HEADER #1
.text name
40A15 virtual size
380 virtual address (0000000000010380 to 0000000000050D94)
40A80 size of raw data
380 file pointer to raw data (00000380 to 00040DFF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
68000020 flags
Code
Not Paged
Execute Read

SECTION HEADER #2
.rdata name
215C virtual size
40E00 virtual address (0000000000050E00 to 0000000000052F5B)
2180 size of raw data
40E00 file pointer to raw data (00040E00 to 00042F7F)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
48000040 flags
Initialized Data
Not Paged
Read Only

Debug Directories

Time Type Size RVA Pointer


5A780F9A cv 57 000427B0 427B0 Format: RSDS, {75ACD3F0-83E2-44A6-BA4F-E9BCB3A138B3}, 1, c:\winddk\vs-old\objfre_win7_amd64\amd64\driverxxx.pdb

SECTION HEADER #3
.data name
A40 virtual size
42F80 virtual address (0000000000052F80 to 00000000000539BF)
A80 size of raw data
42F80 file pointer to raw data (00042F80 to 000439FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C8000040 flags
Initialized Data
Not Paged
Read Write

SECTION HEADER #4
.pdata name
1ECC virtual size
43A00 virtual address (0000000000053A00 to 00000000000558CB)
1F00 size of raw data
43A00 file pointer to raw data (00043A00 to 000458FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
48000040 flags
Initialized Data
Not Paged
Read Only

SECTION HEADER #5
.CRT name
58 virtual size
45900 virtual address (0000000000055900 to 0000000000055957)
80 size of raw data
45900 file pointer to raw data (00045900 to 0004597F)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
48000040 flags
Initialized Data
Not Paged
Read Only

SECTION HEADER #6
INIT name
D3A virtual size
45980 virtual address (0000000000055980 to 00000000000566B9)
D80 size of raw data
45980 file pointer to raw data (00045980 to 000466FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
E2000020 flags
Code
Discardable
Execute Read Write

SECTION HEADER #7
.rsrc name
438 virtual size
46700 virtual address (0000000000056700 to 0000000000056B37)
480 size of raw data
46700 file pointer to raw data (00046700 to 00046B7F)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
Read Only

SECTION HEADER #8
.reloc name
838 virtual size
46B80 virtual address (0000000000056B80 to 00000000000573B7)
880 size of raw data
46B80 file pointer to raw data (00046B80 to 000473FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
Read Only

Summary

80 .CRT
A80 .data
1F00 .pdata
2180 .rdata
880 .reloc
480 .rsrc
40A80 .text
D80 INIT

Steve Walkin wrote:

I have added below ones into my build, still the page alignment issues persists.

First try.
LINKER_FLAGS=/ALIGN:4096

Second try.
LINKER_FLAGS=/SECTION:.text!RX,ALIGN:4096
DRIVER_ALIGNMENT=0x1000

Any idea of what is going wrong ?

Remove the following line from your ‘sources’ file:

DRIVERTYPE=WDM

Probably this is a bug: when compiling in x64 mode this directive
causes an invalid section alignment. I using the following template
and everything works fine:

!IF “$(DDK_TARGET_OS)”==“WinXP”
DRIVER_ALIGNMENT=4096
!ELSE
LINKER_FLAGS = $(LINKER_FLAGS) /ALIGN:4096
!ENDIF

Aleh, that’s a perfect catch. It worked for me too.
Now it is page aligned as
1000 .CRT
1000 .data
2000 .pdata
3000 .rdata
1000 .reloc
1000 .rsrc
41000 .text
1000 INIT

Thanks for the prompt reply.

Can we remove the the RWX from INIT section, while in the same build environment. Any parameter or any settings in make files ?.

Any clues on this, please suggest.

Steve Walkin wrote:

Can we remove the the RWX from INIT section, while in the same build
environment. Any parameter or any settings in make files ?

You can’t achieve this until WDK 10. Yes, some compiler and linker options
may be helpful, but all of them have undesirable side effects.

But as far as I know, the INIT/RWX section is a special exclusion for
Driver Verifier, HLK and HVCI/DevGuard. For example, it is not generate a
violation when running on Windows 10 under HVCI or Verifier.
Some time ago I successfully passed HLK tests for a minifilter that was
built in WDK 7.1 with RWX attributes of INIT section.

FYI:
When running under HVCI/DevGuard the RWX section is silently converted to RX…

Thanks Aleh for the clarification.

I have another suggestion to propose. How efficient and error free is the below approach.

Use the ‘MapAndLoad’ to identify the image(.sys) properties via LOADED_IMAGE structure.
Use the IMAGE_SECTION_HEADER structure, to retrieve the parameter ‘Characteristics’ to get the Writable section.
Strip the value IMAGE_SCN_MEM_WRITE from the identified section.
Use ‘UnMapAndLoad’ by adding the correct checksum in the header.

Can we reuse this image(.sys) ? What will be the implications.
Please suggest.