return STATUS_INVALID_HANDLE when send IOCTL_DISK_GET_DRIVE_GEOMETRY_EX control code

i’m trying to obtain physical drive size in kernel mode driver, and using ZwOpenFile and ZwDeviceIoControlFile to accomplish this. The code is like this:

WCHAR NameBuff[MEM_MAX_DISK_NAME] = { 0 };
UNICODE_STRING Name;
HANDLE DiskHandle;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttr;
DISK_GEOMETRY_EX DiskGeo;

_snwprintf(NameBuff, MEM_MAX_DISK_NAME, L"\??\PhysicalDrive%d", device);
RtlInitUnicodeString(&Name, NameBuff);
InitializeObjectAttributes(&ObjectAttr, &Name, OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwOpenFile(&DiskHandle,
FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttr,
&Iosb,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
return 0;
}

Status = ZwDeviceIoControlFile(&DiskHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL,
0,
&DiskGeo,
sizeof(DISK_GEOMETRY_EX)+5120); //FFFFFFFFC0000008

if (!NT_SUCCESS(Status))
{
ZwClose(DiskHandle);
return 0;
}

capacity = DiskGeo.DiskSize.QuadPart;

the return status of ZwOpenFile is Status_successful, but ZwDeviceIoControlFile return STATUS_INVALID_HANDLE.
How to debug or fix it?
Thanks.

Why do you pass wrong structure size to DeviceIoControl?

to supply sufficent memory for output.
And, i have tried to pass sizeof(DISK_GEOMETRY_EX) as output buffer size, the return value is the same.

> Status = ZwDeviceIoControlFile(&DiskHandle,

NULL,
[snip]

the return status of ZwOpenFile is Status_successful, but
ZwDeviceIoControlFile return STATUS_INVALID_HANDLE.
How to debug or fix it?

You are passing the address of the handle instead of the handle. Just use

Status = ZwDeviceIoControlFile(DiskHandle,

You cannot pass more size than you actually allocated. If you want bigger size, you need to actually have a buffer of bigger size.

>You cannot pass more size than you actually allocated. If you want bigger size,
you need to actually have a buffer of bigger size.

He is testing the requested driver to see if it writes more then sizeof(DISK_GEOMETRY_EX). If it does, the worst thing would be a corruption of the stack cookie (stack buffer overflow). This would raise a “security check failure” and a bugcheck when the requested driver’s dispatch routine returns.

The requested driver will most likely check the size of the output buffer and return STATUS_INVALID_PARAMETER_9.

>The requested driver will most likely check the size of the output buffer and return STATUS_INVALID_PARAMETER_9.

Sorry, ZwDeviceIoControlFile will most probably check the parameters and return STATUS_INVALID_PARAMETER_9., The driver would never know about the request.

ZwDeviceIoControlFile file does not check most parameters, it has no clue
about specific IOCTL’s that is all handled at the driver level.

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Friday, July 29, 2016 12:27 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] return STATUS_INVALID_HANDLE when send
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX control code

>The requested driver will most likely check the size of the output buffer
and return STATUS_INVALID_PARAMETER_9.

Sorry, ZwDeviceIoControlFile will most probably check the parameters and
return STATUS_INVALID_PARAMETER_9., The driver would never know about the
request.


NTDEV is sponsored by OSR

Visit the list online at:
http:

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:</http:></http:></http:>

David Boyce wrote:

> Status = ZwDeviceIoControlFile(&DiskHandle,
> NULL,
[snip]
>
> the return status of ZwOpenFile is Status_successful, but
> ZwDeviceIoControlFile return STATUS_INVALID_HANDLE.
> How to debug or fix it?

You are passing the address of the handle instead of the handle. Just use

Status = ZwDeviceIoControlFile(DiskHandle,

Amidst all the noise in this thread, I want to make sure the original
poster understands THIS is the right answer to his question. In the
kernel, it’s often true that the creation of a thing gets a pointer to
X, but all the APIs that use the thing get an X. C doesn’t catch this
for HANDLEs, but C++ does…

And to be brutally honest, given that the error message told you exactly
that the handle was invalid, the fact that you couldn’t figure this out
should lead you to ask some real questions about your powers of
investigation.


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

>ZwDeviceIoControlFile file does not check most parameters, it has no clue about specific IOCTL’s that is all handled at the driver level.

Yes, you are right, of course. So ZwDeviceIoControlFile tries to obtain a FILE_OBJECT pointer with the file handle so to call the driver, but the Object Manager returns STATUS_INVALID_HANDLE…

xxxxx@gmail.com wrote:

> ZwDeviceIoControlFile file does not check most parameters, it has no clue about specific IOCTL’s that is all handled at the driver level.
Yes, you are right, of course. So ZwDeviceIoControlFile tries to obtain a FILE_OBJECT pointer with the file handle so to call the driver, but the Object Manager returns STATUS_INVALID_HANDLE…

No. That’s NOT what happened. Look at your code again:

HANDLE DiskHandle;

Status = ZwOpenFile(&DiskHandle,
FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttr,
&Iosb,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);

Status = ZwDeviceIoControlFile(&DiskHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL,
0,
&DiskGeo,
sizeof(DISK_GEOMETRY_EX)+5120); //FFFFFFFFC0000008

In the first call, you’re expected to pass the address of a HANDLE. You do that, and ZwOpenFile puts the handle there.

In the second call, you’re expected to pass a HANDLE directly, not the address of a HANDLE. You’re passing a kernel address. The object manager returns STATUS_INVALID_HANDLE because what you gave it is not a HANDLE. It’s just that simple.


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

I think he meant that Nt routines convert handles to fileobjects with
ObReferenceObjectByHandle

On Saturday, 30 July 2016, Tim Roberts wrote:

> xxxxx@gmail.com <javascript:> wrote:
> >> ZwDeviceIoControlFile file does not check most parameters, it has no
> clue about specific IOCTL’s that is all handled at the driver level.
> > Yes, you are right, of course. So ZwDeviceIoControlFile tries to obtain
> a FILE_OBJECT pointer with the file handle so to call the driver, but the
> Object Manager returns STATUS_INVALID_HANDLE…
>
> No. That’s NOT what happened. Look at your code again:
>
> HANDLE DiskHandle;
> …
> Status = ZwOpenFile(&DiskHandle,
> FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
> &ObjectAttr,
> &Iosb,
> FILE_SHARE_READ,
> FILE_SYNCHRONOUS_IO_NONALERT);
> …
> Status = ZwDeviceIoControlFile(&DiskHandle,
> NULL,
> NULL,
> NULL,
> &Iosb,
> IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
> NULL,
> 0,
> &DiskGeo,
> sizeof(DISK_GEOMETRY_EX)+5120); //FFFFFFFFC0000008
>
> In the first call, you’re expected to pass the address of a HANDLE. You
> do that, and ZwOpenFile puts the handle there.
>
> In the second call, you’re expected to pass a HANDLE directly, not the
> address of a HANDLE. You’re passing a kernel address. The object manager
> returns STATUS_INVALID_HANDLE because what you gave it is not a HANDLE.
> It’s just that simple.
>
> –
> Tim Roberts, xxxxx@probo.com <javascript:>
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> 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;
>


Sent from Gmail Mobile</http:></javascript:></javascript:>

Just to be clear.
Source of the error is passing the pointer to handle instead of handle
itself though, not internals of Ntxxx, of course.

On Sat, Jul 30, 2016 at 12:55 AM, Sergey Pisarev
wrote:

> I think he meant that Nt routines convert handles to fileobjects with
> ObReferenceObjectByHandle
>
>
> On Saturday, 30 July 2016, Tim Roberts wrote:
>
>> xxxxx@gmail.com wrote:
>> >> ZwDeviceIoControlFile file does not check most parameters, it has no
>> clue about specific IOCTL’s that is all handled at the driver level.
>> > Yes, you are right, of course. So ZwDeviceIoControlFile tries to obtain
>> a FILE_OBJECT pointer with the file handle so to call the driver, but the
>> Object Manager returns STATUS_INVALID_HANDLE…
>>
>> No. That’s NOT what happened. Look at your code again:
>>
>> HANDLE DiskHandle;
>> …
>> Status = ZwOpenFile(&DiskHandle,
>> FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
>> &ObjectAttr,
>> &Iosb,
>> FILE_SHARE_READ,
>> FILE_SYNCHRONOUS_IO_NONALERT);
>> …
>> Status = ZwDeviceIoControlFile(&DiskHandle,
>> NULL,
>> NULL,
>> NULL,
>> &Iosb,
>> IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
>> NULL,
>> 0,
>> &DiskGeo,
>> sizeof(DISK_GEOMETRY_EX)+5120); //FFFFFFFFC0000008
>>
>> In the first call, you’re expected to pass the address of a HANDLE. You
>> do that, and ZwOpenFile puts the handle there.
>>
>> In the second call, you’re expected to pass a HANDLE directly, not the
>> address of a HANDLE. You’re passing a kernel address. The object manager
>> returns STATUS_INVALID_HANDLE because what you gave it is not a HANDLE.
>> It’s just that simple.
>>
>> –
>> Tim Roberts, xxxxx@probo.com
>> Providenza & Boekelheide, Inc.
>>
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list online at: <
>> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>>
>> 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;
>>
>
>
> –
> Sent from Gmail Mobile
></http:>

Thanks for all.
The root cause has been founded. I pass a wrong parameter to ZwDeviceIoControlFile.
Status = ZwDeviceIoControlFile(DiskHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL,
0,
&DiskGeo,
sizeof(DISK_GEOMETRY_EX));
the first parameter should be the disk handle, not the address of the handle.