Once I've written a sort of a driver for Windows, which had to intercept the interaction of the native display driver with the OS. The native display driver consists of a miniport driver and a DLL loaded by win32k.sys into the session space. My goal was to meddle between the win32k.sys and that DLL. Moreover, the system might have several display drivers, I had to hook them all.
I created a standard WDM driver, which was configured to load at system boot (i.e. before win32k). During its initialization it hooked the ZwSetSystemInformation, by patching the SSDT. This function is called by the OS whenever it loads/unloads a DLL into the session space, which is exactly what I need.
When ZwSetSystemInformation is invoked with SystemLoadImage parameter - one of its parameters is the pointer to a SYSTEM_LOAD_IMAGE structure, and its ModuleBase is the module base mapping address. Then I analyze the mapped image, patch its entry point with my function, and the rest is straightforward.
Now I need to port this driver to a 64-bit Windows. Needless to say it's not a trivial task at all. So far I found the following obstacles:
All drivers must be signed
PatchGuard
SSDT is not directly exported.
If I understand correctly, PatchGuard and driver signing verification may be turned off, the driver should be installed on a dedicated machine, and we may torture it the way we want.
There're tricks to locate the SSDT as well, according to online sources.
However recently I've discovered there exists a function called PsSetLoadImageNotifyRoutine. It may simplify the task considerably, and help avoid dirty tricks.
My question are:
If I use PsSetLoadImageNotifyRoutine, will I receive notifications about DLLs loaded into the session space? The official documentation talks about "system space or user space", but does "system space" also includes the session space?
Do I need to disable the PatchGuard if I'm going to patch the mapped DLL image after it was mapped?
Are there any more potential problems I didn't think about?
Are there any other ways to achieve what I want?
Thanks in advance.
Do I need to disable the PatchGuard if I'm going to patch the mapped DLL image after it was mapped?
To load any driver on x64 it must be signed. With admin rights you can disabled PatchGuard and I personally recommend using DSEO, a GUI application made for this. Or you can bypass PatchGuard by overwriting the MBR (or BIOS), although this is typically considered a bootkit - malware.
Related
I'm installing my driver using dpinst.exe. But before installing my driver I wish to delete all the oem files from inf directory corresponding to my hardware ID.
I want to do this programatically. Please suggest me a way to do this.
**Update :**
I want to do this without device connected as I may pre-install the driver before connecting the device. My device is PNP device.
Use SetupDiEnumDeviceInfo and SetupDiGetDeviceRegistryProperty to match your hardware ID
Use SetupDiOpenDevRegKey and RegQueryValueEx to read the corresponding InfPath
Call SetupUninstallOEMInf
PhilMY has already posted an excellent answer, which is still relevant. However, it is more than ten years old now, so I wanted to update it with more recent/recommended APIs:
Use SetupDiEnumDeviceInfo() and SetupDiGetDeviceRegistryProperty() to match your hardware ID
To get the OEM INF path, SetupDiGetDriverInfoDetail() can be used instead of reading the registry directly
Call DiUninstallDriver() on the resulting INF path (Microsoft recommends using it instead of SetupUninstallOEMInf(). In addition, it returns the needReboot flag, which may be useful in some scenarios.)
#2 is a little tricky as it requires SP_DRVINFO_DATA on input. To acquire it, one typically needs to call SetupDiBuildDriverInfoList() and SetupDiEnumDriverInfo() to iterate through all installed drivers for a particular device (use SPDIT_COMPATDRIVER flag to enumerate 3rd-party drivers).
It has a significant advantage in scenarios when multiple drivers are suitable for the given device, and this approach allows one to choose exactly which driver to uninstall.
I have a Program.exe that I need to intercept. That specific program uses CreateFile & ReadFile, however I need to intercept ReadFile function.
I thought about writing my own File System Filter MiniDriver.
I found this link by Googling: http://msdn.microsoft.com/en-us/library/ff551862(v=vs.85)
It seems that is the correct way to do this. However last time I did any driver development, I remember that >= VISTA did not allow drivers to be installed easily. You needed to acquire "Signed" priviledge from Microsoft(you had to pay).
My question is that, can I create Simple File System Filter Driver for my USB stick and intercept any readings from ReadFile()? All I want to do is to allow ReadFile by a specific process.
1) I need this legally
2) I need to avoid unsigned drivers, so the driver would always work.
Will one minifilter driver work for every OS starting from XP?!
Prohibit of loading unsigned drivers is exist only on x64 versions of windows >= vista
On x64 versions you can
1) Switch to test mode to turm off this restriction
2) Add test sertificate as root to certificate storage
But if you want distribute this driver you must bay certificate.
Yes, minifilter is the preferred way for this. You can intercept system calls/IRPs and allow-deny any of them depending upon your criteria.
Also, same driver code can be used for multiple OSes, however you need to build for specific Os.
WDK 7 can be used to build drivers from XP to Windows 7.
Also, as izlesa suggested, you need to sign for x64 windows higher than vista.
I am new to device driver programming. I've followed the available tutorials on the web which has provided helpful information to get started. However now I have embarked on a new project where the exclusive goal is to search for functions which have been hooked by malware or keyloggers. So I think I have sorted out what I need to accomplish this though I still need to be able to locate the load address of the system dll's (i.e. kernel32.dll, user32.dll and the like) that are already loaded in memory. I need the load address so that I can parse their PE to get to the export and import sections. Furthermore adding the load address to the file size will give me a address range to cross reference the addresses of the export functions no ? Cross referencing the the IMPORT address will be a little more involved but it can be done according to my estimates. I thought that building a kernel mode driver would be the right way to go since accessing memory outside the kernel driver's address range would not be an issue for the driver as opposed to a user mode app. How else will I be able to access the addresses located in the EAT and IAT of the target dll ? I know there exist a user mode API that can provide the load address mainly being GetModuleHandle but I would like to find the equivalent in kernel mode. I could write a user mode application that could relay this information to the driver but prefer that this all be done in kernel mode if possible. Any suggestions or comments would be most welcome.
Thanks in advance
Victor
p.s This post has been edited for more clarity. Hopefully it will make it more clear as what I am trying to accomplish.
This is probably not a very good idea to do in kernel mode. When are you going to actually do this and guarantee the process is in a state where you could walk the IAT?
What if the process is in the middle of loading a DLL? If you're executing in-thread (i.e. from a syscall or device IOCTL), what if other threads are executing too? Doing this when you're not the OS is a very difficult proposition to correctly do, and it's very easy to destabilize your customers' machines (hell, it's reasonably hard to do even if you are the OS)
Take a look at LdrGetProcedureAddress and the rest of the gang.
Edit:
MmGetSystemRoutineAddress might also be helpful.
Just wanted to thank everyone for their contribution. I did manage to some further research and discovered that there is a kernel mode API called PsLoadImageNotifyCallback that is able to find the base addresss of any process.
I have a .NET winform application that requires to register a native dll during installation. My question is how can I register a dll (regsvr32 ABC.dll) as part of MSI installion process? Similary how can I un-register a dll as part of un-installation process?
Nice answer from Chris Painter, adding for reference: how to register DLL's properly in wix 3.9. And one with WiX-focus: Registering COM EXE with WIX.
Self-Registration considered harmful
The proper way to register a COM file is to extract the COM registry information from the file and add to the appropriate family of COM tables in the MSI. Most MSI tools have features to support this COM extraction, see separate section towards the end of the answer for details.
This MSI SDK article lists several variations on the general issues with self registration described below, as well as describing some further details - particularly with regards to per-user registration of COM data, and run-from-source scenarios.
Extracted COM data will ensure reliable installation of your COM server as well as support for advanced MSI features such as "advertisement", "rollback", resiliency and "elevated privileges". You can read more about these advanced MSI benefits in this summary that has become somewhat popular on serverfault.com: corporate benefits of MSI.
It is also possible to use the built-in SelfReg table in Windows installer to register the file using regsvr32.exe as part of the installation process (or even invoked as a custom action), but this is considered bad practice for a number of reasons:
Rollback: Windows Installer is unable to properly handle rollback unless the COM data is extracted and embedded in the MSI. The result is that a failed setup may not clean up its COM footprint correctly and the MSI does not put the machine back in the original state properly. The rollback of COM data really does work like "auto-magic" tracking every change in the registry whether it be addition, modification or deletion and is reliable when done right.
Security: The self registration process of a COM server may in certain cases perform unorthodox tasks such as modifying the system's network settings or perform other crazy maneuvers that have nothing to do with COM and are hard to identify and debug. I have personally seen, in disbelief I might add, COM registration change system-wide network settings without any warning, and for no obvious reason. It might have been just an optimization for an application, but this is rarely acceptable when it changes the whole system affecting all other software. Though an EXE file run in admin mode can do the same and be equally faulty, self-registration may go under the radar and be less obvious as a security issue. This is a core reason why large corporations and Microsoft best practices insist on not allowing self-registration as it may interfere with business critical systems.
Chained dependencies: Some COM files may need to be registered in a specific order on the system to register successfully. In other words file B can't register until file A has been registered. I have honestly never seen this in real life, but it is technically possible, and I have seen dependencies on language dlls (resource only dlls) cause COM extraction to fail. Though slightly different, it is still a dependency issue. MSI does not allow specification of the registration order (probably due to the database origin of MSI, rows are unordered). If you extract the registry data properly on the build computer and put it into the MSI, these chained dependencies will not cause an application error.
Permission problems: Windows Installer has advanced features to elevate the privilege level of the user installing the MSI to allow all information to be registered without permission problems (no messing about with temporary admin rights). If you use the SelfReg table you are more likely to run into registration problems caused by permission or privilege peculiarities on the local system (in my experience this is particularly evident for self-repair operations). Permission problems like these occur more and more as new versions of Windows steadily put new obstacles in place for the successful deployment of software (UAC prompts, self-repair lockdown, impersonation changes etc...).
Resiliency: If another application destroys your COM registry entries, the COM data embedded in your MSI will reinstall the COM component with all associated registry entries via self-repair if proper COM extraction is used to make the package. This means that your application should always be able to launch with its COM servers properly registered. However, this can also trigger the dreaded repetitive sequence of self repair cycles that many experienced computer users have seen (here is a simpler and shorter explanation). In other words COM extraction can be riddled with problems as well, but just using self-registration would leave your application broken, and also prone to security errors being triggered if you run repair, modify or self-repair of your product (the self registration operation may run without elevated rights and hence fail to complete if the repair is run as a restricted user). This means the errors are impossible to fix for most normal users. It is all they know how to do if the product isn't working.
Advertisement: Advertised products are available to the user via shortcuts and registry entries, but not presently installed on the machine. An "on demand" installation can be invoked in a handful of ways - referred to as advertised entry points (recommended Symantec article), one of which is the invocation of an advertised COM server. No install will be triggered unless the file is properly advertised in the registry and a crucial trigger of "self repair" is hence missing if you use self-registration.
Installation Tool Support for COM Registration
The extraction of COM data and entry into MSI tables is a fairly involved task, and most tools on the market such as Installshield, Advanced Installer, and Wise (Wise is now off-market, unfortunately) have automated solutions for this.
In Installshield you simply enable a component flag called "Extract COM data on build", and Wise has a similar flag on the component level. WiX can extract the COM registry data using a tool called heat.exe and the generated WiX-code can be inserted into your source WiX file (there may be new features for this by now that I am not aware of). I am not aware of any features in Visual Studio that will extract the COM data automatically, but it looks like Chris Painter provides a possibility in his answer.
Check out RegSpy2 if Heat doesn't work for you (Phil Wilson - the author of "The Definitive Guide to Windows Installer" wrote RegSpy and someone extended it to RegSpy2). Also check this: Register ActiveX exe server using WiX (my answer towards the bottom for regspy.exe command line use).
Erroneous COM data inserted into an MSI - particularly for repackaged applications in corporate environments - is one of the leading causes of "unexpected cyclical self-repair". Please see this long article for explanation of this issue: How can I determine what causes repeated Windows Installer self-repair? (bullet point 3 in section "Some typical self-repair problem scenarios" describes this issue).
Several other installation tools exist with similar extraction features: What installation product to use? InstallShield, WiX, Wise, Advanced Installer, etc
vsdrfCOMSelfReg is not a best practice. Try vsdrfCOM instead. This will "extract" ( or try, vdproj is a POS sometimes ) the COM metadata from the DLL and author it into the correct COM tables. This is better then hoping an out of process call to DllRegisterServer will work at install time.
Now that MSI is natively aware of your COM resources, it will handle install and uninstall for you.
Scroll down to Rule 19 in the Tao of Windows Installer to see what the MSI team said:
Using the self-registering capabilities of certain DLLs is highly discouraged. Any activity performed by the self-registration (e.g. addition of registry entries) is out of the control of the Installer, so cannot be part of advertisement, repair and is not removed on uninstall. Instead you should have the Installer manage the data for you by using the appropriate tables in the MSI database.
Select the file you want to register and in the Properties window set the Register field to vsdrfCOMSelfReg. This will author an entry in the SelfReg table which will automatically register / un-register your DLL.
http://msdn.microsoft.com/en-us/library/aa371608(VS.85).aspx
I noticed that WPF application startup is sometimes pretty slow. Does anybody know if the the cause is the elements initialization or DLLs loading or something else?
The text below was extracted from this MSDN article on Improving WPF applications startup time (Edit: now merged into WPF Application Startup Time)
Application Startup Time
The amount of time that is required for a WPF application to start can vary greatly. This topic describes various techniques for reducing the perceived and actual startup time for a Windows Presentation Foundation (WPF) application.
Understanding Cold Startup and WarmStartup
Cold startup occurs when your application starts for the first time after a system reboot, or when you start your application, close it, and then start it again after a long period of time. When an application starts, if the required pages (code, static data, registry, etc) are not present in the Windows memory manager's standby list, page faults occur. Disk access is required to bring the pages into memory.
Warm startup occurs when most of the pages for the main common language runtime (CLR) components are already loaded in memory, which saves expensive disk access time. That is why a managed application starts faster when it runs a second time.
Implement a Splash Screen
In cases where there is a significant, unavoidable delay between starting an application and displaying the first UI, optimize the perceived startup time by using a splash screen. This approach displays an image almost immediately after the user starts the application. When the application is ready to display its first UI, the splash screen fades. Starting in the .NET Framework 3.5 SP1, you can use the SplashScreen class to implement a splash screen. For more information, see How to: Add a Splash Screen to a WPF Application.
You can also implement your own splash screen by using native Win32 graphics. Display your implementation before the Run method is called.
Analyze the Startup Code
Determine the reason for a slow cold startup. Disk I/O may be responsible, but this is not always the case. In general, you should minimize the use of external resources, such as network, Web services, or disk.
Before you test, verify that no other running applications or services use managed code or WPF code.
Start your WPF application immediately after a reboot, and determine how long it takes to display. If all subsequent launches of your application (warm startup) are much faster, your cold startup issue is most likely caused by I/O.
If your application's cold startup issue is not related to I/O, it is likely that your application performs some lengthy initialization or computation, waits for some event to complete, or requires a lot of JIT compilation at startup. The following sections describe some of these situations in more detail.
Optimize Module Loading
Use tools such as Process Explorer (Procexp.exe) and Tlist.exe to determine which modules your application loads. The command Tlist <pid> shows all the modules that are loaded by a process.
For example, if you are not connecting to the Web and you see that System.Web.dll is loaded, then there is a module in your application that references this assembly. Check to make sure that the reference is necessary.
If your application has multiple modules, merge them into a single module. This approach requires less CLR assembly-loading overhead. Fewer assemblies also mean that the CLR maintains less state.
Defer Initialization Operations
Consider postponing initialization code until after the main application window is rendered.
Be aware that initialization may be performed inside a class constructor, and if the initialization code references other classes, it can cause a cascading effect in which many class constructors are executed.
Avoid Application Configuration
Consider avoiding application configuration. For example, if an application has simple configuration requirements and has strict startup time goals, registry entries or a simple INI file may be a faster startup alternative.
Utilize the GAC
If an assembly is not installed in the Global Assembly Cache (GAC), there are delays caused by hash verification of strong-named assemblies and by Ngen image validation if a native image for that assembly is available on the computer. Strong-name verification is skipped for all assemblies installed in the GAC. For more information, see Gacutil.exe (Global Assembly Cache Tool).
Use Ngen.exe
Consider using the Native Image Generator (Ngen.exe) on your application. Using Ngen.exe means trading CPU consumption for more disk access because the native image generated by Ngen.exe is likely to be larger than the MSIL image.
To improve the warm startup time, you should always use Ngen.exe on your application, because this avoids the CPU cost of JIT compilation of the application code.
In some cold startup scenarios, using Ngen.exe can also be helpful. This is because the JIT compiler (mscorjit.dll) does not have to be loaded.
Having both Ngen and JIT modules can have the worst effect. This is because mscorjit.dll must be loaded, and when the JIT compiler works on your code, many pages in the Ngen images must be accessed when the JIT compiler reads the assemblies' metadata.
Ngen and ClickOnce
The way you plan to deploy your application can also make a difference in load time. ClickOnce application deployment does not support Ngen. If you decide to use Ngen.exe for your application, you will have to use another deployment mechanism, such as Windows Installer.
For more information, see Ngen.exe (Native Image Generator).
Rebasing and DLL Address Collisions
If you use Ngen.exe, be aware that rebasing can occur when the native images are loaded in memory. If a DLL is not loaded at its preferred base address because that address range is already allocated, the Windows loader will load it at another address, which can be a time-consuming operation.
You can use the Virtual Address Dump (Vadump.exe) tool to check if there are modules in which all the pages are private. If this is the case, the module may have been rebased to a different address. Therefore, its pages cannot be shared.
For more information about how to set the base address, see Ngen.exe (Native Image Generator).
Optimize Authenticode
Authenticode verification adds to the startup time. Authenticode-signed assemblies have to be verified with the certification authority (CA). This verification can be time consuming, because it can require connecting to the network several times to download current certificate revocation lists. It also makes sure that there is a full chain of valid certificates on the path to a trusted root. This can translate to several seconds of delay while the assembly is being loaded.
Consider installing the CA certificate on the client computer, or avoid using Authenticode when it is possible. If you know that your application does not need the publisher evidence, you do not have to pay the cost of signature verification.
Starting in .NET Framework 3.5, there is a configuration option that allows the Authenticode verification to be bypassed. To do this, add the following setting to the app.exe.config file:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
Compare Performance on Windows Vista
The memory manager in Windows Vista has a technology called SuperFetch. SuperFetch analyzes memory usage patterns over time to determine the optimal memory content for a specific user. It works continuously to maintain that content at all times.
This approach differs from the pre-fetch technique used in Windows XP, which preloads data into memory without analyzing usage patterns. Over time, if the user uses your WPF application frequently on Windows Vista, the cold startup time of your application may improve.
Use AppDomains Efficiently
If possible, load assemblies into a domain-neutral code area to make sure that the native image, if one exists, is used in all AppDomains created in the application.
For the best performance, enforce efficient cross-domain communication by reducing cross-domain calls. When possible, use calls without arguments or with primitive type arguments.
Use the NeutralResourcesLanguage Attribute
Use the NeutralResourcesLanguageAttribute to specify the neutral culture for the ResourceManager. This approach avoids unsuccessful assembly lookups.
Use the BinaryFormatter Class for Serialization
If you must use serialization, use the BinaryFormatter class instead of the XmlSerializer class. The BinaryFormatter class is implemented in the Base Class Library (BCL) in the mscorlib.dll assembly. The XmlSerializer is implemented in the System.Xml.dll assembly, which might be an additional DLL to load.
If you must use the XmlSerializer class, you can achieve better performance if you pre-generate the serialization assembly.
Configure ClickOnce to Check for Updates After Startup
If your application uses ClickOnce, avoid network access on startup by configuring ClickOnce to check the deployment site for updates after the application starts.
If you use the XAML browser application (XBAP) model, keep in mind that ClickOnce checks the deployment site for updates even if the XBAP is already in the ClickOnce cache. For more information, see ClickOnce Security and Deployment.
Configure the PresentationFontCache Service to Start Automatically
The first WPF application to run after a reboot is the PresentationFontCache service. The service caches the system fonts, improves font access, and improves overall performance. There is an overhead in starting the service, and in some controlled environments, consider configuring the service to start automatically when the system reboots.
Set Data Binding Programmatically
Instead of using XAML to set the DataContext declaratively for the main window, consider setting it programmatically in the OnActivated method.
The most useful advice on fixing WPF startup performance I've ever seen was given in this other question: run "ngen update" in every framework folder.
It seems that Microsoft can't keep their ngen cache up-to-date, which results in your application pretty much recompiling half the .NET framework every single startup.
Hard to believe, but seems to be true.
The startup time of a WPF Application can be much faster if you use Framework 3.51 and not 3.5 or 3.0. The 3.51 is really an improvement.
This is an old thread, but I've ended up here several times while trying to fix a startup performance issue with WPF apps on my Win10 system, so I thought I'd state an answer which may help others - an answer that takes a horrible 5 second startup time for all WPF apps on this system down to just a few milliseconds. Remove the nVidia "3d Vision" driver. I have a GeForce GTX 650 card, and the "3d Vision" driver doesn't seem to offer anything useful, so removing it is no problem for me. The VisualStudio2015 performance analysis tool finally helped show that almost all the 5 second startup time was spent IDLE after a call through nvapi64.dll - the nVidia driver. Wow.
What helped me the most from the excellent article that Stuart links to was the XmlSerializer trick. That really shaved up quite a few seconds. Furthermore don't underestimate defragmenting your HD :-)