My file system minifilter driver for Windows 7x64 must denied access for some files. I`m get it, but associated application still work. I want to terminate process with this application. For example, when user try to open *.txt file, file and associated copy of notepad must be closed. I used example from WDK (Minispy) and functions ZwTerminateProcess and PsGetCurrentProcessId. Now, when user enter monitoring directory, my minifilter close explorer.exe. Example code:
minispy.c
...
NTSTATUS TermFunction( HANDLE ProcessID )
{
NTSTATUS ntStatus = STATUS_SUCCESS;
HANDLE hProcess;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
DbgPrint( "drvTerminateProcess( %u )", ProcessID );
InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_INHERIT, NULL, NULL );
ClientId.UniqueProcess = (HANDLE)ProcessID;
ClientId.UniqueThread = NULL;
__try
{
ntStatus = ZwOpenProcess( &hProcess, PROCESS_ALL_ACCESS, &ObjectAttributes, &ClientId );
if( NT_SUCCESS(ntStatus) )
{
ntStatus = ZwTerminateProcess( hProcess, 0 );
if( !NT_SUCCESS(ntStatus) )
DbgPrint( "ZwTerminateProcess failed with status : %08X\n", ntStatus );
ZwClose( hProcess );
}
else
DbgPrint( "ZwOpenProcess failed with status : %08X\n", ntStatus );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
ntStatus = STATUS_UNSUCCESSFUL;
DbgPrint( "Exception caught in drvTerminateProcess()" );
}
return ntStatus;
}
...
FLT_PREOP_CALLBACK_STATUS
SpyPreOperationCallback (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
UNICODE_STRING old_name;
PUNICODE_STRING new_old_name;
...
if (NT_SUCCESS( status )) {
nameToUse = &nameInfo->Name;
//
// Parse the name if requested
//
//Start of My func
RtlInitUnicodeString( &old_name, L"\\Device\\HarddiskVolume2\\secretfile.txt" );
new_old_name = &old_name;
if(RtlCompareUnicodeString(nameToUse, new_old_name, FALSE) == 0){
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
TermFunction(PsGetCurrentProcessId);
return FLT_PREOP_COMPLETE;
}
...
}
....
}
Any idea?
(Excuse me if my English is bad)
Related
I'm trying to create a basic minifilter driver using Microsoft examples (PassThough, minispy...), but my MfPreOperationCallback is not called. I tried different contexts (even if I'm not sure to understand how that works...). I tried the PassThrough example and it works very well and it is very similar to my code...
Here is my inf file and my code :
;
; KmdfMiniFilter.inf
;
[Version]
Signature = "$WINDOWS NT$"
Class = "ActivityMonitor"
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
Provider = %ProviderString%
DriverVer = 02/09/2017,1.0.0.0
CatalogFile = KmdfMiniFilter.cat
[DestinationDirs]
DefaultDestDir = 12
KmdfMiniFilter.DriverFiles = 12
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = KmdfMiniFilter.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,KmdfMiniFilter.Service
[DefaultUninstall]
DelFiles = KmdfMiniFilter.DriverFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200
[KmdfMiniFilter.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys
Dependencies = "FltMgr"
ServiceType = 2 ; SERVICE_FILE_SYSTEM_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = KmdfMiniFilter.AddRegistry
[KmdfMiniFilter.AddRegistry]
HKR,,"DebugFlags",0x00010001 ,0x0
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%
[KmdfMiniFilter.DriverFiles]
%DriverName%.sys
[SourceDisksFiles]
KmdfMiniFilter.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
[Strings]
ProviderString = "GUIDONO"
ServiceDescription = "KmdfMiniFilter mini-filter driver"
ServiceName = "KmdfMiniFilter"
DriverName = "KmdfMiniFilter"
DiskId1 = "File Change Monitoring Device Installation Disk"
DefaultInstance = "KmdfMiniFilter Instance"
Instance1.Name = "KmdfMiniFilter Middle Instance"
Instance1.Altitude = "370000"
Instance1.Flags = 0x1 ; Suppress automatic attachments
Registration.c
/**
Filter registration information
*/
#pragma once
#include <fltKernel.h>
#include "MiniFilter.h"
// Callbacks : list of FLT_OPERATION_REGISTRATION structures, one for each type of I/O for which the minifilter
// registers preoperation and postoperation callback routines.
// The last element must be IRP_MJ_OPERATION_END
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{
IRP_MJ_CREATE,
0,
MfPreOperationCallback,
MfPostOperationCallback
},
{ IRP_MJ_OPERATION_END }
};
// Defines the minifilter context structure
typedef struct _MINIFILTER_TRANSACTION_CONTEXT {
ULONG Flags;
ULONG Count;
} MINIFILTER_TRANSACTION_CONTEXT, *PMINIFILTER_CONTEXT;
// Contexts : a context structure is used to register context types
const FLT_CONTEXT_REGISTRATION Contexts[] =
{
{
FLT_TRANSACTION_CONTEXT, // Context type
0, // Flags
MfDeleteTxfContext, // ContextCleanupCallback
sizeof(MINIFILTER_TRANSACTION_CONTEXT), // Size
'ypsM' // PoolTag
},
{
FLT_CONTEXT_END
}
};
// This defines what we want to filter with FltMgr
CONST FLT_REGISTRATION FilterRegistration =
{
sizeof(FLT_REGISTRATION), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
Contexts, // Contexts
Callbacks, // Callbacks
MfUnload, // FilterUnload
MfInstanceSetup, // InstanceSetup
MfInstanceQueryTeardown, // InstanceQueryTeardown
MfInstanceTeardownStart, // InstanceTeardownStart
MfInstanceTeardownComplete, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL, // NormalizeNameComponent
};
Driver.c
#include <ntifs.h>
#include <wdf.h>
#include "RegistrationData.h"
#include "MiniFilter.h"
// Global data
MINIFILTER_DATA MfData;
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
//DbgSetDebugFilterState(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, TRUE);
NTSTATUS status;
MfData.Driver = DriverObject;
// Registering the minifilter driver
status = FltRegisterFilter(DriverObject, &FilterRegistration, &MfData.Filter);
KdPrint(("MINIFILTER INIT\n"));
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltRegisterFilter failed. Code 0x%x\n", status));
return STATUS_UNSUCCESSFUL;
}
status = FltStartFiltering(MfData.Filter);
if (!NT_SUCCESS(status)) {
KdPrint(("MINIFILTER ERROR : FltStartFiltering faild. Code 0x%x\n", status));
FltUnregisterFilter(MfData.Filter);
return STATUS_UNSUCCESSFUL;
}
KdPrint(("MINIFILTER is Filtering!\n"));
return status;
}
NTSTATUS MfUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
KdPrint(("MINIFILTER UNLOAD\n"));
FltUnregisterFilter(MfData.Filter);
return STATUS_SUCCESS;
}
NTSTATUS MfQueryTearDown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(Flags);
PAGED_CODE();
return STATUS_SUCCESS;
}
MiniFilter.h
#pragma once
#include <fltKernel.h>
typedef struct MINIFILTER_DATA {
PDRIVER_OBJECT Driver;
PFLT_FILTER Filter;
} MINIFILTER_DATA;
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
);
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
);
NTSTATUS MfInstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
);
NTSTATUS MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
);
NTSTATUS MfUnload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);
NTSTATUS MfQueryTearDown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
NTSTATUS MfInstanceQueryTeardown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);
MiniFilter.c
#include "MiniFilter.h"
FLT_PREOP_CALLBACK_STATUS MfPreOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
KdPrint(("MINIFILTER PreOperationCallback\n"));
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS MfPostOperationCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);
KdPrint(("MINIFILTER PostOperationCallback\n"));
return FLT_POSTOP_FINISHED_PROCESSING;
}
VOID MfDeleteTxfContext(
_Inout_ PFLT_CONTEXT Context,
_In_ FLT_CONTEXT_TYPE ContextType
)
{
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(ContextType);
KdPrint(("MINIFILTER DeleteTxfContext\n"));
}
NTSTATUS
MfInstanceSetup (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
UNREFERENCED_PARAMETER( VolumeDeviceType );
UNREFERENCED_PARAMETER( VolumeFilesystemType );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceSetup: Entered\n") );
return STATUS_SUCCESS;
}
NTSTATUS
MfInstanceQueryTeardown (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceQueryTeardown: Entered\n") );
return STATUS_SUCCESS;
}
VOID
MfInstanceTeardownStart (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownStart: Entered\n") );
}
VOID
MfInstanceTeardownComplete (
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
KdPrint(("PassThrough!PtInstanceTeardownComplete: Entered\n") );
}
Does anyone see what's going on ?
I solved my problem : I had the wrong flag in my inf file. The good one is 0x0 flag in order to attach the minifilter automatically to the different volumes.
Instance1.Flags = 0x1 ; Suppress automatic attachments
to
Instance1.Flags = 0x0 ; Automatic attachments
What I'm trying to do:
User-mode app sends Process ID to driver
Driver gets handle to specified Process ID
Drivers passes opened handle to user-mode app
I'm not sure if this code is even completely working. I'm quite new to drivers, so I haven't set up debugging yet and virtual machine hasn't finished downloading (slow connection problems).
Getting Process ID from user-mode app should be working fine and it should be getting stored in PROCESS_INFO struct as ProcessId. The opened handle is stored in the same struct as ProcessHandle to be sent back to the user-mode application. I'm not sure how to return data from kernel to user-mode tho, maybe someone could explain briefly.
Here's my code:
#include <ntifs.h>
#include <wdf.h>
DRIVER_INITIALIZE DriverEntry;
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\GetSysHandle"), SymbolicLink = RTL_CONSTANT_STRING(L"\\DosDevices\\GetSysHandle");
typedef struct _PROCESS_INFO
{
HANDLE ProcessId;
HANDLE ProcessHandle;
}PROCESS_INFO, *PPROCESS_INFO;
BOOLEAN GetSysHandle(PPROCESS_INFO ProcessInfo)
{
NTSTATUS status = STATUS_ACCESS_DENIED;
PEPROCESS eProcess = NULL;
status = PsLookupProcessByProcessId(ProcessInfo->ProcessId, &eProcess);
if ((!NT_SUCCESS(status)) || (!eProcess))
{
return FALSE;
}
status = ObOpenObjectByPointer(eProcess, 0, NULL, 0, 0, KernelMode, &ProcessInfo->ProcessHandle);
if ((!NT_SUCCESS(status)) || (!ProcessInfo->ProcessHandle))
{
ObDereferenceObject(eProcess);
return FALSE;
}
return TRUE;
}
void Unload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("# GetSysHandle driver unloaded.");
IoDeleteSymbolicLink(&SymbolicLink);
IoDeleteDevice(pDriverObject->DeviceObject);
}
NTSTATUS DriverDispatch(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
PIO_STACK_LOCATION io;
PPROCESS_INFO ProcessInfo;
NTSTATUS status;
io = IoGetCurrentIrpStackLocation(irp);
irp->IoStatus.Information = 0;
switch (io->MajorFunction)
{
case IRP_MJ_CREATE:
status = STATUS_SUCCESS;
break;
case IRP_MJ_CLOSE:
status = STATUS_SUCCESS;
break;
case IRP_MJ_READ:
status = STATUS_SUCCESS;
break;
case IRP_MJ_WRITE:
ProcessInfo = (PPROCESS_INFO)MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
if (!ProcessInfo)
{
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (!GetSysHandle(ProcessInfo))
{
DbgPrint("# Failed to get process handle");
status = STATUS_UNSUCCESSFUL;
break;
}
status = STATUS_SUCCESS;
irp->IoStatus.Information = sizeof(PROCESS_INFO);
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
ULONG i;
DbgPrint("# GetSysHandle driver loaded");
IoCreateDevice(DriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject);
IoCreateSymbolicLink(&SymbolicLink, &DeviceName);
for (i = 0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
{
DriverObject->MajorFunction[i] = DriverDispatch;
}
return STATUS_SUCCESS;
}
First and foremost (to avoid confusion): this code is for Windows and Windows Drivers.
The biggest issue I see with your driver code is that you aren't registering the IRP major functions inside of DriverEntry. You will need to set the MajorFunction parameters of the PDRIVER_OBJECT DriverObject to the dispatch functions. Without assigning these MajorFunctions, the driver will have no way of knowing what function to call when receiving a command.
To do this, break up the cases for the switch (io->MajorFunction) into different dispatch functions. For example, IRP_MJ_WRITE will be its own function, and you can declare it like so:
DRIVER_DISPATCH DispatchReadFunction;
In this case, we will want all read commands issued to the driver to run whatever code is inside the DispatchReadFunction function. So the definition will look a little like this:
NTSTATUS DispatchReadFunction(_In_ PDEVICE_OBJECT DriverObject, _In_ PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
//Do read code here
return status;
}
Once we have the DispatchReadFunction function written, you will need to assign it to the DriverObject->MajorFunction in the DriverEntry function like so:
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadFunction;
Finally, stub out and write the rest of the IRP_MJ_ functions that you need, making sure that you assign them to the MajorFunction memeber of DriverObject.
My DriverEntry function looks like this (I removed extra functionality):
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
status = STATUS_SUCCESS;
DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadFunc;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateFunc;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCloseFunc;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWriteFunc;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDevCtrlFunc;
return status;
}
A good starting point would be here. This link also includes a simple example (driver code and application code) that does what you are attempting to do.
Good Luck!
I have the problem , I can't get names of every process, some process show normal name but another return . How can I get the name of such process ? But the id is ok.
May I did something wrond , I am testing this on Windows 8.1
Here is the code .
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
//This returns a list of handles to processes running on the system as an array.
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) {
return 0;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Display the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ ) {
if( aProcesses[i] != 0 ) {
DisplayProcessNameAndID( aProcesses[i] );
}
}
void DisplayProcessNameAndID( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
//Given a handle to a process, this returns all the modules running within the process.
//The first module is the executable running the process,
//and subsequent handles describe DLLs loaded into the process.
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
{
//This function returns the short name for a module,
//typically the file name portion of the EXE or DLL
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Display the process name and identifier.
char buffer[400];
sprintf_s(buffer,"Text:%s, PID : %u", szProcessName, processID );
MessageBox(mainWinH,buffer, "Ok", MB_OK);
//close the process handle
CloseHandle( hProcess );
}
First of all some parts of the code are from Calling function in injected DLL but somewhere it doesn't work.
I have a question regarding DLL Injection: after I loaded the library into another process:
HANDLE InjectDLL(DWORD ProcessID, char *dllName)
{
HANDLE Proc;
char buf[50]={0};
LPVOID RemoteString, LoadLibAddy;
if(!ProcessID)
return NULL;
Proc = OpenProcess(CREATE_THREAD_ACCESS, FALSE, ProcessID);
if(!Proc)
{
sprintf(buf, "OpenProcess() failed: %d", GetLastError());
MessageBox(NULL, buf, "Loader", NULL);
return NULL;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(dllName), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, dllName, strlen(dllName), NULL);
HANDLE hThread = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
if( hThread != 0 ) {
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, ( LPDWORD )&hInjected );
CloseHandle( hThread );
}
CloseHandle(Proc);
return hThread != 0 ? Proc : NULL;
}
I wanted to call a function from inside that space:
void* GetPayloadExportAddr( LPCSTR lpPath, HMODULE hPayloadBase, LPCSTR lpFunctionName )
{
// Load payload in our own virtual address space
HMODULE hLoaded = LoadLibrary( lpPath );
if( hLoaded == NULL ) {
return NULL;
} else {
void* lpFunc = GetProcAddress( hLoaded, lpFunctionName );
DWORD dwOffset = (char*)lpFunc - (char*)hLoaded;
FreeLibrary( hLoaded );
return (void*)((DWORD)hPayloadBase + dwOffset);
}
}
BOOL InitPayload( HANDLE hProcess, LPCSTR lpPath, HMODULE hPayloadBase)
{
void* lpInit = GetPayloadExportAddr( lpPath, hPayloadBase, "Start" );
if( lpInit == NULL ) {
return FALSE;
}
else {
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)lpInit, (LPVOID) NULL, 0, NULL );
if( hThread == NULL ) {
return FALSE;
}
else {
CloseHandle( hThread );
}
}
return TRUE;
}
The GetPayloadExportAddr returns the Current Location from IDA (i guess that is the space where my function starts).
So the problem is at the InitPayload function when I try to create the new thread, it fails to do so and I don't know why.
My dll is the following:
extern "C"
{
__declspec(dllexport) void* Start(LPVOID param)
{
MessageBox(NULL, L"Start", L"Hello", MB_OK);
return NULL;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
The thing is if I put the Start method at DLL_PROCESS_ATTACH it works, but otherwise it doesn't.
Your GetPayloadExportAddr() returns the address of the function in your local process. This address will not be the same in other processes if the base address of the module is different, which is common with DLL files which can be relocated if their PreferredImageBase is not available.
You should modify your GetPayloadExportAddr() function to return the offset. Then get the address of the module in the target process. Add these two together and that is the correct address for you to call in the target process.
I am working on getting the device id from the usb device i plug...
The above application works on win-Xp but not in Windows 7
When i try to figure it i found that CM_Get_Parent () not works...
can anybody please guide me on why its not working ...and is there any compatible function which can work on windows 7
source code:
HDEVINFO hDevInfo;
GUID guid;
BYTE buffer[ 1024 ];
DWORD dwRequiredSize ;
WCHAR buf[ 1024 ];
DEVINST devInstParent;
WCHAR volume[1024];
int aLength, anIndex;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
guid = GUID_DEVINTERFACE_VOLUME;
hDevInfo = SetupDiGetClassDevs( &guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
if( hDevInfo == INVALID_HANDLE_VALUE )
{
qDebug() << "Error - SetupDiGetClassDevs failed\n";
}
for( DWORD dwIndex = 0;; dwIndex ++ )
{
ZeroMemory( &devInterfaceData, sizeof( devInterfaceData ) );
devInterfaceData.cbSize = sizeof(devInterfaceData );
if( !SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guid,dwIndex, &devInterfaceData ) )
{
break;
}
ZeroMemory( &devInfoData, sizeof( devInfoData ) );
devInfoData.cbSize = sizeof(devInfoData);
pDevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buffer;
pDevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA );
// Get device interface detail data to get Device Instance from
// SP_DEVINFO_DATA and Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
SetupDiGetDeviceInterfaceDetail(
hDevInfo,&devInterfaceData,
pDevDetail, // SP_DEVICE_INTERFACE_DETAIL_DATA
1024,&dwRequiredSize,&devInfoData ); // SP_DEVINFO_DATA
CM_Get_Parent( &devInstParent,devInfoData.DevInst, 0 );
CM_Get_Parent( &devInstParent,devInstParent, 0 );
CM_Get_Device_ID( devInstParent, buf, 1024,0 );
}
The following a litle modified code
#include <Windows.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <tchar.h>
#include <stdio.h>
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
#pragma comment (lib, "setupapi.lib")
int main()
{
HDEVINFO hDevInfo;
GUID guid;
BYTE buffer[ 1024 ];
DWORD dwRequiredSize ;
DEVINST devInstParent;
SP_DEVICE_INTERFACE_DATA devInterfaceData;
SP_DEVINFO_DATA devInfoData;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetail;
CONFIGRET status;
TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
BOOL bSuccess;
guid = GUID_DEVINTERFACE_VOLUME;
hDevInfo = SetupDiGetClassDevs( &guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
if( hDevInfo == INVALID_HANDLE_VALUE ) {
return 1;
}
for( DWORD dwIndex = 0;; dwIndex ++ ) {
ZeroMemory( &devInterfaceData, sizeof( devInterfaceData ));
devInterfaceData.cbSize = sizeof( devInterfaceData );
if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &guid, dwIndex, &devInterfaceData ) ) {
DWORD dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_NO_MORE_ITEMS)
break;
else
return 1; // ERROR!!!
}
ZeroMemory( &devInfoData, sizeof( devInfoData ) );
devInfoData.cbSize = sizeof( devInfoData);
pDevDetail = ( PSP_DEVICE_INTERFACE_DETAIL_DATA )buffer;
pDevDetail->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA );
// Get device interface detail data to get Device Instance from
// SP_DEVINFO_DATA and Device Path from SP_DEVICE_INTERFACE_DETAIL_DATA
bSuccess = SetupDiGetDeviceInterfaceDetail( hDevInfo,&devInterfaceData,
pDevDetail,// SP_DEVICE_INTERFACE_DETAIL_DATA
sizeof(buffer),&dwRequiredSize,&devInfoData ); // SP_DEVINFO_DATA
status = CM_Get_Device_ID (devInfoData.DevInst, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS) {
_tprintf (TEXT("%s\n"), szDeviceInstanceID);
}
status = CM_Get_Parent( &devInstParent,devInfoData.DevInst, 0 );
if (status == CR_SUCCESS) {
status = CM_Get_Device_ID (devInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS)
_tprintf (TEXT(" %s\n"), szDeviceInstanceID);
status = CM_Get_Parent( &devInstParent,devInstParent, 0 );
if (status == CR_SUCCESS) {
status = CM_Get_Device_ID( devInstParent, szDeviceInstanceID, ARRAY_SIZE(szDeviceInstanceID), 0);
if (status == CR_SUCCESS) {
_tprintf (TEXT(" %s\n"), szDeviceInstanceID);
}
}
else {
continue;
}
}
else {
continue;
}
}
}
work without any problem on my Windows 7 computer and produce output like following:
SCSI\CDROM&VEN_ELBY&PROD_CLONEDRIVE&REV_1.4\1&2AFD7D61&0&000000
ROOT\SCSIADAPTER\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#0000000000100000
ROOT\VOLMGR\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#000000004B100000
ROOT\VOLMGR\0000
HTREE\ROOT\0
STORAGE\VOLUME\{21C004DA-0EB2-11DF-8C02-806E6F6E6963}#00000037C7A00000
ROOT\VOLMGR\0000
HTREE\ROOT\0
UPDATED based on the comment: On my Windows XP in the VMware the same utility produce the following output
FDC\GENERIC_FLOPPY_DRIVE\6&1435B2E2&0&0
ACPI\PNP0700\5&324D5432&0
ACPI\PNP0A05\4&5289E18&0
IDE\CDROMNECVMWAR_VMWARE_IDE_CDR10_______________1.00____\3031303030303030303030303030303030303130
PCIIDE\IDECHANNEL\4&23686003&0&1
PCI\VEN_8086&DEV_7111&SUBSYS_197615AD&REV_01\3&61AAA01&0&39
STORAGE\VOLUME\1&30A96598&0&SIGNATURE91929192OFFSET7E00LENGTH1FFD5AA00
ROOT\FTDISK\0000
HTREE\ROOT\0
Of cause it is another computer (a virtual computer) on the other operation system and we receive another list of devices. You current question was to make the function CM_Get_Parent() working on both Windows XP and Windows 7. The posted code do this like we can see. Or it is now work correctly on your Windows XP or Windows 7 computer?
How to get pid and vid (product id and ventor id) I described in Get information about disk drives result on windows7 - 32 bit system, but for any drive letters and not for the volume devices. One can easy change the code to show more information like Volume name, Bus name and other information. But this all is already another question.
UPDATED: I placed the extended version of program from Get information about disk drives result on windows7 - 32 bit system under http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c because of restriction with the message size in stackoverflow.com. The test output looks like http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.txt