Why does the SVL Admin Service inject into processes?
Why does the SVL Admin Service inject into processes?
We were recently asked this question by a customer because their security team was concerned that this behaviour was unexpected and might be malicious.
In this article I’m going to describe every Software Verify process that injects into another process and explain why it is doing that.
Summary
Before I do that, here’s the summary:
- We inject into other processes mainly to set environment variables that will allow .Net and .Net Core processes to load our .Net profiler.
- We inject into other processes mainly to delete environment variables that will allow .Net and .Net Core processes to load our .Net profiler.
- We inject into other processes sometimes to attach to a native process to allow profiling of that process. This is the Inject into running process… option on the Launch menu.
- We can also eject a DLL from a target process.
Setting Environment Variables
We set environment variables in a target process – used to set .Net Profiler environment variables.
- We allocate some memory in the target process and setup the environment variables values we want to set.
- We then create a remote thread in the target process and call the SetEnvironmentVariable() function (found in kernel32.dll in the target process) with a pointer to the memory setup previously.
Deleting Environment Variables
We delete environment variables in a target process – used to reset .Net Profiler environment variables.
- We allocate some memory in the target process and setup the environment variables values we want to delete.
- We then create a remote thread in the target process and call the SetEnvironmentVariable() function (found in kernel32.dll in the target process) with a pointer to the memory setup previously.
Injecting a DLL into a target process
We inject Software Verify DLLs into a target process – used to attach to processes that are already running.
-
- We create a remote thread in the target process.
- The thread loads the Software Verify DLL we want loaded.
- The thread calls the function we want called in that DLL. There are two use cases for this.
Injecting a profiler into an application that is about to start
This is the Launch Application… option on the Launch menu.
We start the target application in a suspended state, then modify the entry point code to run our code that will load the native profiler before any other code gets executed. This allows us to monitor more of your application’s behaviour than any other method. It is also more reliable and doesn’t suffer from the risk of deadlocks that Injecting a profiler into a running application has.
Note that for this method we do not create a remote thread, it is not required.
The function called is “startProfiler” or “startProfilerEx”.
The DLL that will be injected depends on the software tool being used.
Bug Validator | svlBugValidatorStub.dll |
Coverage Validator x86 | svlCoverageValidatorStub.dll |
Coverage Validator x64 | svlCoverageValidatorStub_x64.dll |
Memory Validator x86 | svlMemoryValidatorStub.dll |
Memory Validator x64 | svlMemoryValidatorStub_x64.dll |
Performance Validator x86 | svlPerformanceValidatorStub.dll |
Performance Validator x64 | svlPerformanceValidatorStub_x64.dll |
Thread Validator x86 | svlThreadValidatorStub.dll |
Thread Validator x64 | svlThreadValidatorStub_x64.dll |
Injecting a profiler into a running application
This is the Inject into running process… option on the Launch menu.
There is a risk of deadlock with this method because it is impossible to know the state of locks and critical sections that are already active before you inject to a running application (not the same as attaching a debugger to a running application – the debugger is a separate process). We do note in the software documentation that you should always prefer Launch Application to Inject into running process.
The function called is “startProfiler” or “startProfilerEx”.
The DLL that will be injected depends on the software tool being used.
Bug Validator | svlBugValidatorStub.dll |
Coverage Validator x86 | svlCoverageValidatorStub.dll |
Coverage Validator x64 | svlCoverageValidatorStub_x64.dll |
Memory Validator x86 | svlMemoryValidatorStub.dll |
Memory Validator x64 | svlMemoryValidatorStub_x64.dll |
Performance Validator x86 | svlPerformanceValidatorStub.dll |
Performance Validator x64 | svlPerformanceValidatorStub_x64.dll |
Thread Validator x86 | svlThreadValidatorStub.dll |
Thread Validator x64 | svlThreadValidatorStub_x64.dll |
Injecting a DLL that sets some environment variables
Injecting a DLL that sets some environment variables via the DllMain() function.
There is no risk of deadlock injecting these DLLs, they do so little work you can’t trigger that sort of problem.
The DLL unloads immediately because once the environment variables are set it has no more work to do.
Bug Validator | svlBvSetEnv.dll |
Coverage Validator x86 | svlCvSetEnv.dll |
Coverage Validator x64 | svlCvSetEnv_x64.dll |
Memory Validator x86 | svlMvSetEnv.dll |
Memory Validator x64 | svlMvSetEnv_x64.dll |
Performance Validator x86 | svlPvSetEnv.dll |
Performance Validator x64 | svlPvSetEnv_x64.dll |
Thread Validator x86 | svlTvSetEnv.dll |
Thread Validator x64 | svlTvSetEnv_x64.dll |
The above are used when working with ASP.Net. The processes injected into are:
mmc.exe | Applications |
cmd.exe | Applications |
explorer.exe | Applications |
inetinfo.exe | Internet Information Server |
services.exe | Services |
svchost.exe | Services |
The reasons these processes are injected into is because these are the processes that may launch other processes, and those processes inherit their environment variables from the process launching them.
The applications that may initiate this are:
- bugValidator.exe
- coverageValidator.exe
- coverageValidator_x64.exe
- memoryValidator.exe
- memoryValidator_x64.exe
- performanceValidator.exe
- performanceValidator_x64.exe
- threadValidator.exe
- threadValidator_x64.exe
The services that may initiate this are:
- svlAdminService.exe via svlInject.exe
- svlAdminService.exe via svlInject_x64.exe
- svlAdminService_x64.exe via svlInject.exe
- svlAdminService_x64.exe via svlInject_x64.exe
These may also be called indirectly via the resetDotNetProfiler.exe tool which will reset all .Net Profiler environment variables.
Why do Bug Validator and Thread Validator set .Net profiler environment variables when these profilers only profile native code?
The reason for this is mixed mode .Net processes that execute both .Net and native code. If BV and TV are to profile the native code in these mixed mode processes we still need to load a .Net profiler into these processes so that the native profiling code can be loaded into the target process.
Why do x86 processes inject into x64 processes?
The reason for this is that on 64 bit systems it is most likely that a 64 bit process will start a 32 bit process that may be the target for the software tool you are using. We need to set the .Net profiling environment variables appropriately for that task. This is why svlAdminService.exe calls svlInject_x64.exe to inject 64 bit DLLs into 64 bit target processes.
Ejecting a DLL into a target process
We remove Software Verify DLLs from a target process – used to remove DLLs from a process that we have previously inject into a process.
- We create a remote thread in the target process then call FreeLibrary() with the base address of the DLL in the target process.
Conclusion
Some of Software Verify’s software tools inject DLLs into other processes.
This is done to manage .Net Profiler environment variables, or to profile already running native applications when instructed to do so by the user of the software.
There is nothing malicious about this behaviour. It is by design, and is necessary for the correct functioning of the software when working with .Net, .Net Core and debugging applications that are already running.