Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicitly pass the size of the requested arguments #188

Merged
merged 9 commits into from
Dec 2, 2023

Conversation

1ndahous3
Copy link
Contributor

@1ndahous3 1ndahous3 commented Nov 4, 2023

Due to refactoring in #155 the argument size bug was introduced.

Initially the code was like this:

  // ntdll!NtDeviceIoControlFile()
  // Ioctl:              @rsp + 0x30
  // InputBuffer:        @rsp + 0x38
  // InputBufferLength:  @rsp + 0x40

  const Gva_t Stack = Gva_t(g_Backend->Rsp());

  const Gva_t InputBufferLengthPtr = Stack + Gva_t(0x40);
  uint32_t CurrentIoctlBufferSize = g_Backend->VirtRead4(InputBufferLengthPtr);

But after refactoring it became like this:

const auto &[InputBufferSize, InputBufferSizePtr] =
g_Backend->GetArgAndAddress(7);
const uint32_t MutatedInputBufferSize =
std::min(TotalInputBufferSize, uint32_t(InputBufferSize));
//
// Calculate the new InputBuffer address by pushing the mutated buffer as
// close as possible from its end.
//
const auto &[InputBuffer, InputBufferPtr] = g_Backend->GetArgAndAddress(6);
const auto NewInputBuffer =
Gva_t(InputBuffer + InputBufferSize - MutatedInputBufferSize);

So 8 bytes are read for the InputBufferSize argument, and we got an invalid value - only one uint32_t(InputBufferSize) cast is made, but then the same cast is not made during addition operation.

This patch replaces one argument getter function with two: GetArg4() for 4-byte values and GetArg8() for 8-byte values. Also, many additional casts to uint32_t have been removed, which are no longer needed.

@0vercl0k
Copy link
Owner

0vercl0k commented Nov 5, 2023 via email

@0vercl0k
Copy link
Owner

Looking into this..

@0vercl0k
Copy link
Owner

@1ndahous3 what do you think of the new changes?

Cheers

@1ndahous3
Copy link
Contributor Author

@0vercl0k looks good, I think it makes no difference for GetArg4() to read 4 bytes or read 8 bytes with garbage and trim it through a uint32_t cast.

In my opinion, it would be nice to rename GetArg() to GetArg8() to show the size not only by the type of the return value. This will not give a chance to make a bug when writing code without noticing the GetArg4() pair function.

@0vercl0k
Copy link
Owner

I do agree, but it also means it breaks everybody that is using GetArg which is not desirable. What I can do is to introduce a GetArg8 version though to be consistent - wdyt?

Cheers

@1ndahous3
Copy link
Contributor Author

What I can do is to introduce a GetArg8 version though to be consistent - wdyt?

Sounds like a good compromise.

@0vercl0k
Copy link
Owner

All right - take this for a spin and let me know 🫡

Cheers

@1ndahous3
Copy link
Contributor Author

1ndahous3 commented Nov 28, 2023

AFAIR the BugCheckCode from KeBugCheck2() is of ULONG type, so we need to get the uint32_t value.

@0vercl0k
Copy link
Owner

0vercl0k commented Nov 29, 2023 via email

@0vercl0k
Copy link
Owner

Done!

@1ndahous3
Copy link
Contributor Author

I can only suggest adding a [[deprecated]] attribute to the GetArg() function.

The code is ok.

@0vercl0k
Copy link
Owner

0vercl0k commented Dec 1, 2023

Neat, TIL [[deprecated]]!

@1ndahous3
Copy link
Contributor Author

I don't have any additional suggestions or notes, everything looks great!

@0vercl0k
Copy link
Owner

0vercl0k commented Dec 2, 2023 via email

@0vercl0k 0vercl0k merged commit 3106447 into 0vercl0k:main Dec 2, 2023
5 checks passed
@1ndahous3 1ndahous3 deleted the explicit_args_size branch December 2, 2023 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants