Skip to content

Instantly share code, notes, and snippets.

@skissane
Created March 28, 2023 00:35
Show Gist options
  • Save skissane/210359e4645edbc19a93998cc4009d2b to your computer and use it in GitHub Desktop.
Save skissane/210359e4645edbc19a93998cc4009d2b to your computer and use it in GitHub Desktop.
Tool to dump CallNtPowerInformation(GetPowerRequestList) results
#define _WIN32_WINNT 0x0602
#define UMDF_USING_NTSTATUS
#include <stdio.h>
#include <windows.h>
#include <powerbase.h>
#include <stdbool.h>
#include <ntstatus.h>
#include <shlobj.h>
#pragma comment(lib, "PowrProf.lib")
typedef NTSTATUS PowerInformationWithPrivileges_t(
POWER_INFORMATION_LEVEL InformationLevel,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength
);
static PowerInformationWithPrivileges_t* PowerInformationWithPrivileges = NULL;
NTSTATUS QueryPowerInformationLevel(POWER_INFORMATION_LEVEL InformationLevel, void** OutBuf, ULONG* OutSize) {
if (PowerInformationWithPrivileges == NULL) {
// Call LoadModule to load powrprof.dll
HMODULE hPowrProf = LoadLibraryA("powrprof.dll");
if (hPowrProf == NULL) {
printf("ERROR: LoadLibraryA(\"powrprof.dll\") failed with error %d\n", GetLastError());
return STATUS_UNSUCCESSFUL;
}
// Use GetProcAddress to get PowerInformationWithPrivileges function from hPowrProf
// and stick it in PowerInformationWithPrivileges global variable
PowerInformationWithPrivileges = (PowerInformationWithPrivileges_t*)GetProcAddress(hPowrProf, "PowerInformationWithPrivileges");
if (PowerInformationWithPrivileges == NULL) {
printf("ERROR: GetProcAddress(\"PowerInformationWithPrivileges\") failed with error %d\n", GetLastError());
return STATUS_UNSUCCESSFUL;
}
}
if (OutSize != NULL) *OutSize = 0;
ULONG OutputBufferLength = 0x40;
PVOID OutputBuffer = malloc(OutputBufferLength);
if (OutputBuffer == NULL) {
printf("ERROR: malloc() could not allocate %lu bytes\n", OutputBufferLength);
return STATUS_NO_MEMORY;
}
while (true) {
NTSTATUS status = PowerInformationWithPrivileges(InformationLevel, NULL, 0, OutputBuffer, OutputBufferLength);
if (status == STATUS_BUFFER_TOO_SMALL) {
// Resize the buffer
OutputBufferLength *= 2;
PVOID NewOutputBuffer = realloc(OutputBuffer, OutputBufferLength);
if (NewOutputBuffer == NULL) {
printf("ERROR: realloc() could not resize the buffer to %lu bytes\n", OutputBufferLength);
free(OutputBuffer);
return STATUS_NO_MEMORY;
}
OutputBuffer = NewOutputBuffer;
}
else if (status == STATUS_SUCCESS) {
if (OutSize != NULL) *OutSize = OutputBufferLength;
*OutBuf = OutputBuffer;
return status;
}
else {
free(OutputBuffer);
return status;
}
}
}
int main(int argc, char* argv[]) {
printf("GetPowerRequestList tool\n\n");
if (!IsUserAnAdmin()) {
printf("ERROR: You must run this program as an administrator\n");
return 1;
}
void* OutBuf = NULL;
ULONG OutSize = 0;
NTSTATUS status = QueryPowerInformationLevel(GetPowerRequestList, &OutBuf, &OutSize);
if (status != STATUS_SUCCESS) {
printf("ERROR: GetPowerRequestList failed with status=%08x\n", status);
return 1;
}
SIZE_T* count = (SIZE_T*)OutBuf;
printf("GetPowerRequestList entry count=%zu\n", count[0]);
for (int i = 0; i < count[0]; i++) {
SIZE_T startOffset = count[i + 1];
SIZE_T endOffset = i == count[0] - 1 ? OutSize : count[i + 2];
SIZE_T size = endOffset - startOffset;
printf("GetPowerRequestList entry %d: startOffset=%zu endOffset=%zu size=%zu\n",
i, startOffset, endOffset, size);
// Dump all text found in entry
printf("\t[");
WCHAR* ptr = (WCHAR*)((SIZE_T)OutBuf + startOffset);
bool spaceOut = true;
for (int j = 0; j < (size / 2); j++) {
int ch = ptr[j];
if (ch > 0x20 && ch < 0x7f) {
spaceOut = false;
printf("%c", ptr[j]);
}
else if (!spaceOut) {
printf(" ");
spaceOut = true;
}
}
printf("]\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment