diff --git a/clrinject-cli/cli.cpp b/clrinject-cli/cli.cpp index 067e1da..92a0506 100644 --- a/clrinject-cli/cli.cpp +++ b/clrinject-cli/cli.cpp @@ -136,10 +136,10 @@ int main(int argc, char** argv) { printf("Enumeration:\n"); int index = 1; for (int i = 0; i < result.numRuntimes; i++) { - const Runtime& runtime = result.runtimes[i]; + const RuntimeInfo& runtime = result.runtimes[i]; printf("#\tRuntime Version: '%ls', %s\n", runtime.version, runtime.started ? "is started" : "is not started"); for (int j = 0; j < runtime.numAppDomains; j++) { - const AppDomain& appDomain = runtime.appDomains[j]; + const AppDomainInfo& appDomain = runtime.appDomains[j]; printf("#%d\t\tAppDomain Name: '%ls'\n", index++, appDomain.friendlyName); } } @@ -148,9 +148,9 @@ int main(int argc, char** argv) { else { printf("Injection succeeded for following Runtimes and AppDomains:\n"); for (int i = 0; i < result.numRuntimes; i++) { - const Runtime& runtime = result.runtimes[i]; + const RuntimeInfo& runtime = result.runtimes[i]; for (int j = 0; j < runtime.numAppDomains; j++) { - const AppDomain& appDomain = runtime.appDomains[j]; + const AppDomainInfo& appDomain = runtime.appDomains[j]; if(appDomain.injected) printf("\tRuntime '%ls', AppDomain '%ls'\n", runtime.version, appDomain.friendlyName); } @@ -158,9 +158,9 @@ int main(int argc, char** argv) { printf("Injection failed for following Runtimes and AppDomains:\n"); int index = 1; for (int i = 0; i < result.numRuntimes; i++) { - const Runtime& runtime = result.runtimes[i]; + const RuntimeInfo& runtime = result.runtimes[i]; for (int j = 0; j < runtime.numAppDomains; j++) { - const AppDomain& appDomain = runtime.appDomains[j]; + const AppDomainInfo& appDomain = runtime.appDomains[j]; if (!appDomain.injected && (!options.appDomainIndex || options.appDomainIndex == index)) printf("\tRuntime '%ls', AppDomain '%ls'\n", runtime.version, appDomain.friendlyName); index++; diff --git a/clrinject-cli/clrinject-cli.vcxproj b/clrinject-cli/clrinject-cli.vcxproj index 60eac87..c9b1825 100644 --- a/clrinject-cli/clrinject-cli.vcxproj +++ b/clrinject-cli/clrinject-cli.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -30,26 +30,26 @@ Application true - v140 + v141 MultiByte Application true - v140 + v141 MultiByte Application false - v140 + v141 MultiByte true Application false - v140 + v141 MultiByte true diff --git a/clrinject-lib.test/App.config b/clrinject-lib.test/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/clrinject-lib.test/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/clrinject-lib.test/Program.cs b/clrinject-lib.test/Program.cs new file mode 100644 index 0000000..1b34f8e --- /dev/null +++ b/clrinject-lib.test/Program.cs @@ -0,0 +1,111 @@ + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace InjectorApp +{ + class Program + { + static void Main(string[] args) + { + Process victimProcess = null; + + try + { + victimProcess = Process.Start(PathOfVictimApp); + if (!victimProcess.IsRunning()) + return; + + System.Threading.Thread.Sleep(TimeSpan.FromSeconds(6)); + + Injector injector = new Injector(); + + //Test enumeration + var result = injector.EnumerateAppDomains("victim.exe"); + + if (result.Any()) + { + result.ForEach(runtime => + { + var runtimeStatus = runtime.IsRuntimeStarted ? "started" : "stopped"; + Console.WriteLine($"Runtime Version : {runtime.runtimeVersion} is {runtimeStatus}, and have following app domains:"); + int index = 0; + runtime.AppDomains.ForEach(appd => Console.WriteLine($"{++index}. {appd}")); + }); + } + else + { + Console.WriteLine("Enumeration yielded no result"); + } + + Console.WriteLine(); + + //Test injection in all app domains + //injector.InjectIntoProcess("victim.exe", PathOfProcessToInject); + + //Test injection in the specified app domain + injector.InjectIntoProcess("victim.exe", PathOfProcessToInject, 3); + + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + } + + Console.WriteLine("Press any key to exit."); + Console.ReadLine(); + + victimProcess.Kill(); + + } + + public static string PathOfProcessToInject + { + get + { + return GetPath("invader"); + } + } + + public static string PathOfVictimApp + { + get + { + return GetPath("victim"); + } + } + + private static string GetPath(string appName) + { + var assembly = Assembly.GetExecutingAssembly(); + string codeBase = assembly.CodeBase; + UriBuilder uri = new UriBuilder(codeBase); + var projectRootDirectory = Directory.GetParent(Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path))).Parent.Parent.Parent; + string buildMode = codeBase.Contains("Debug") ? "Debug" : "Release"; + var assemblyName = AssemblyName.GetAssemblyName(assembly.FullName.Split(',')[0] + ".exe"); + var assemblyArchitecture = assemblyName.ProcessorArchitecture == ProcessorArchitecture.Amd64 ? "x64" : "x86"; + return $"{projectRootDirectory.FullName}\\{appName}\\bin\\{assemblyArchitecture}\\{buildMode}\\{appName}.exe"; + } + } + + public static class ProcessExtensions + { + public static bool IsRunning(this Process process) + { + if (process == null) + throw new ArgumentNullException("process"); + try + { + Process.GetProcessById(process.Id); + } + catch (ArgumentException) + { + return false; + } + return true; + } + } +} diff --git a/clrinject-lib.test/Properties/AssemblyInfo.cs b/clrinject-lib.test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8ba14a4 --- /dev/null +++ b/clrinject-lib.test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("InjectorApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("InjectorApp")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ccc57338-7ddc-4106-bf33-2538188d17ea")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/clrinject-lib.test/clrinject-lib.test.csproj b/clrinject-lib.test/clrinject-lib.test.csproj new file mode 100644 index 0000000..493e742 --- /dev/null +++ b/clrinject-lib.test/clrinject-lib.test.csproj @@ -0,0 +1,76 @@ + + + + + Debug + AnyCPU + {CCC57338-7DDC-4106-BF33-2538188D17EA} + Exe + InjectorApp + InjectorApp + v4.6.1 + 512 + true + true + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + + + + + + + + + + + + + + + + + + + + + {9dc43a8d-8596-4704-9982-c2bad7087de9} + clrinject-lib + + + + \ No newline at end of file diff --git a/clrinject-lib/AssemblyInfo.cpp b/clrinject-lib/AssemblyInfo.cpp new file mode 100644 index 0000000..70258d9 --- /dev/null +++ b/clrinject-lib/AssemblyInfo.cpp @@ -0,0 +1,21 @@ + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +[assembly:AssemblyTitleAttribute(L"clrinjectlib")]; +[assembly:AssemblyDescriptionAttribute(L"")]; +[assembly:AssemblyConfigurationAttribute(L"")]; +[assembly:AssemblyCompanyAttribute(L"")]; +[assembly:AssemblyProductAttribute(L"clrinjectlib")]; +[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2019")]; +[assembly:AssemblyTrademarkAttribute(L"")]; +[assembly:AssemblyCultureAttribute(L"")]; + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; diff --git a/clrinject-lib/clrinject-lib.cpp b/clrinject-lib/clrinject-lib.cpp new file mode 100644 index 0000000..e747b01 --- /dev/null +++ b/clrinject-lib/clrinject-lib.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include "msclr\marshal_cppstd.h" +#include "clrinject-lib.h" +#include "../clrinject/clrinject.h" + +using namespace System::Runtime::InteropServices; + +private class SZStringToOleString { + OLECHAR * data; +public: + SZStringToOleString(const char * in_data) { + data = new OLECHAR[strlen(in_data) + 1]; + for (size_t i = 0; i <= strlen(in_data); i++) { + data[i] = in_data[i]; + } + } + operator OLECHAR*() { + return data; + } + ~SZStringToOleString() { + delete[] data; + } +}; + +System::Collections::Generic::List^ Injector::EnumerateAppDomains(int processId) +{ + InjectionOptions options = {}; + options.enumerate = true; + options.processId = processId; + return EnumerateAppDomains(options); +} + +System::Collections::Generic::List^ Injector::EnumerateAppDomains(String ^ processName) +{ + InjectionOptions options = {}; + int processId = GetProcessIdFromName(processName); + options.enumerate = true; + options.processId = processId; + return EnumerateAppDomains(options); +} + +void Injector::InjectIntoProcess(int processId, String^ pathOfAssemblyToBeInjected) +{ + InjectionOptions options = {}; + options.processId = processId; + std::string pathOfAssemblyToBeInjectedString = msclr::interop::marshal_as(pathOfAssemblyToBeInjected); + lstrcpynW(options.assemblyFile, SZStringToOleString(pathOfAssemblyToBeInjectedString.c_str()), MAX_PATH); + //options.appDomainIndex = 1; + InjectionResult result = InvokeInjection(options); +} + +void Injector::InjectIntoProcess(String ^ processName, String^ pathOfAssemblyToBeInjected) +{ + int processId = GetProcessIdFromName(processName); + return Injector::InjectIntoProcess(processId, pathOfAssemblyToBeInjected); +} + +void Injector::InjectIntoProcess(int processId, String^ pathOfAssemblyToBeInjected, int appDomainNo) +{ + InjectionOptions options = {}; + options.processId = processId; + std::string pathOfAssemblyToBeInjectedString = msclr::interop::marshal_as(pathOfAssemblyToBeInjected); + lstrcpynW(options.assemblyFile, SZStringToOleString(pathOfAssemblyToBeInjectedString.c_str()), MAX_PATH); + options.appDomainIndex = appDomainNo; + InjectionResult result = InvokeInjection(options); +} + +void Injector::InjectIntoProcess(String ^ processName, String^ pathOfAssemblyToBeInjected, int appDomainNo) +{ + int processId = GetProcessIdFromName(processName); + return Injector::InjectIntoProcess(processId, pathOfAssemblyToBeInjected, appDomainNo); +} + +System::Collections::Generic::List ^ Injector::EnumerateAppDomains(InjectionOptions &options) +{ + InjectionResult result = InvokeInjection(options); + return ExtractEnumerationInfo(result); +} + +InjectionResult InvokeInjection(InjectionOptions &options) +{ + InjectionResult result; + int retVal = Inject(&options, &result); + ResultGuard(retVal, result); + return result; +} + +System::Collections::Generic::List^ ExtractEnumerationInfo(InjectionResult &result) +{ + System::Collections::Generic::List ^output = gcnew System::Collections::Generic::List(); + for (int i = 0; i < result.numRuntimes; i++) { + const RuntimeInfo& runtime = result.runtimes[i]; + + EnumerationResult enumeration; + enumeration.runtimeVersion = gcnew String(runtime.version); + enumeration.IsRuntimeStarted = runtime.started; + enumeration.AppDomains = gcnew System::Collections::Generic::List(); + + for (int index = 0; index < runtime.numAppDomains; index++) { + const AppDomainInfo& appDomain = runtime.appDomains[index]; + enumeration.AppDomains->Add(gcnew String(appDomain.friendlyName)); + } + + output->Add(enumeration); + } + + return output; +} + +int GetProcessIdFromName(String ^ processName) +{ + String ^ processNameWithoutExtension = processName->Substring(0, processName->LastIndexOf('.')); + array ^processes = System::Diagnostics::Process::GetProcessesByName(processNameWithoutExtension); + + if (processes->Length == 0) { + throw gcnew System::ApplicationException("Failed to get id for process name" + processNameWithoutExtension);; + } + + return processes[0]->Id; +} + +void ResultGuard(int retVal, InjectionResult &result) +{ + if (retVal) { + if (result.status || result.statusMessage[0]) + throw gcnew System::ApplicationException(System::String::Format(L"Injection failed, return value: {0}, code: {1}, reason: {2}", gcnew String(retVal.ToString()), gcnew String(result.status.ToString()), gcnew String(result.statusMessage))); + else + throw gcnew System::ApplicationException(System::String::Format("Injection failed, return value: {0}", gcnew String(retVal.ToString()))); + } +} + + diff --git a/clrinject-lib/clrinject-lib.h b/clrinject-lib/clrinject-lib.h new file mode 100644 index 0000000..c07d047 --- /dev/null +++ b/clrinject-lib/clrinject-lib.h @@ -0,0 +1,33 @@ +#pragma once +#include "clrinject-lib.h" +#include "../clrinject/clrinject.h" + +using namespace System; + +typedef public value struct EnumerationResult +{ +public: + String ^runtimeVersion; + Boolean IsRuntimeStarted; + System::Collections::Generic::List^ AppDomains; +}; + +public ref class Injector +{ +public: + System::Collections::Generic::List^ EnumerateAppDomains(int processId); + System::Collections::Generic::List^ EnumerateAppDomains(String ^processName); + void InjectIntoProcess(int processId, String^ pathOfAssemblyToBeInjected); + void InjectIntoProcess(String ^processName, String^ pathOfAssemblyToBeInjected); + void InjectIntoProcess(int processId, String^ pathOfAssemblyToBeInjected, int appDomainNo); + void InjectIntoProcess(String ^processName, String^ pathOfAssemblyToBeInjected, int appDomainNo); +private: + System::Collections::Generic::List ^ EnumerateAppDomains(InjectionOptions &options); +}; + +InjectionResult InvokeInjection(InjectionOptions &options); +System::Collections::Generic::List^ ExtractEnumerationInfo(InjectionResult &result); +void ResultGuard(int retVal, InjectionResult &result); +int GetProcessIdFromName(String ^ processName); +InjectionResult InvokeInjection(InjectionOptions &options); + diff --git a/clrinject-lib/clrinject-lib.vcxproj b/clrinject-lib/clrinject-lib.vcxproj new file mode 100644 index 0000000..3ff94c7 --- /dev/null +++ b/clrinject-lib/clrinject-lib.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9} + v4.5 + ManagedCProj + clrinjectlib + 10.0.17763.0 + + + + DynamicLibrary + true + v141 + true + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + DynamicLibrary + true + v141 + true + MultiByte + + + DynamicLibrary + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)clrinject;$(IncludePath) + bin\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)32 + + + true + bin\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)64 + + + false + bin\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)32 + + + false + bin\$(Configuration)\ + obj\$(Configuration)\ + $(ProjectName)64 + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;%(PreprocessorDefinitions) + + + + + + + + NotUsing + Level3 + Disabled + _DEBUG;%(PreprocessorDefinitions) + + + + + + + + NotUsing + Level3 + WIN32;NDEBUG;%(PreprocessorDefinitions) + + + + + + + + NotUsing + Level3 + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + {4fa32c01-2b57-4d78-a079-905295575cad} + + + + + + \ No newline at end of file diff --git a/clrinject-lib/clrinject-lib.vcxproj.filters b/clrinject-lib/clrinject-lib.vcxproj.filters new file mode 100644 index 0000000..69e1e45 --- /dev/null +++ b/clrinject-lib/clrinject-lib.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/clrinject.sln b/clrinject.sln index 6d213ff..f602c82 100644 --- a/clrinject.sln +++ b/clrinject.sln @@ -1,60 +1,103 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clrinject", "clrinject\clrinject.vcxproj", "{4FA32C01-2B57-4D78-A079-905295575CAD}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "victim", "victim\victim.csproj", "{14EC8B28-633C-451B-864D-829D1D0D02A5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "invader", "invader\invader.csproj", "{20974E0D-C43C-46E7-8F34-1457613024BD}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clrinject-cli", "clrinject-cli\clrinject-cli.vcxproj", "{6A9CF653-0969-492F-AB03-B6C01CD8AA3F}" - ProjectSection(ProjectDependencies) = postProject - {4FA32C01-2B57-4D78-A079-905295575CAD} = {4FA32C01-2B57-4D78-A079-905295575CAD} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x64.ActiveCfg = Debug|x64 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x64.Build.0 = Debug|x64 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x86.ActiveCfg = Debug|Win32 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x86.Build.0 = Debug|Win32 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x64.ActiveCfg = Release|x64 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x64.Build.0 = Release|x64 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x86.ActiveCfg = Release|Win32 - {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x86.Build.0 = Release|Win32 - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x64.ActiveCfg = Debug|Any CPU - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x64.Build.0 = Debug|Any CPU - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x86.Build.0 = Debug|Any CPU - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x64.ActiveCfg = Release|x64 - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x64.Build.0 = Release|x64 - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x86.ActiveCfg = Release|Any CPU - {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x86.Build.0 = Release|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x64.ActiveCfg = Debug|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x64.Build.0 = Debug|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x86.ActiveCfg = Debug|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x86.Build.0 = Debug|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x64.ActiveCfg = Release|x64 - {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x64.Build.0 = Release|x64 - {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x86.ActiveCfg = Release|Any CPU - {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x86.Build.0 = Release|Any CPU - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x64.ActiveCfg = Debug|x64 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x64.Build.0 = Debug|x64 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x86.ActiveCfg = Debug|Win32 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x86.Build.0 = Debug|Win32 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x64.ActiveCfg = Release|x64 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x64.Build.0 = Release|x64 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x86.ActiveCfg = Release|Win32 - {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.271 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clrinject", "clrinject\clrinject.vcxproj", "{4FA32C01-2B57-4D78-A079-905295575CAD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "victim", "victim\victim.csproj", "{14EC8B28-633C-451B-864D-829D1D0D02A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "invader", "invader\invader.csproj", "{20974E0D-C43C-46E7-8F34-1457613024BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clrinject-cli", "clrinject-cli\clrinject-cli.vcxproj", "{6A9CF653-0969-492F-AB03-B6C01CD8AA3F}" + ProjectSection(ProjectDependencies) = postProject + {4FA32C01-2B57-4D78-A079-905295575CAD} = {4FA32C01-2B57-4D78-A079-905295575CAD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "clrinject-lib", "clrinject-lib\clrinject-lib.vcxproj", "{9DC43A8D-8596-4704-9982-C2BAD7087DE9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "clrinject-lib.test", "clrinject-lib.test\clrinject-lib.test.csproj", "{CCC57338-7DDC-4106-BF33-2538188D17EA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x64.ActiveCfg = Debug|x64 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x64.Build.0 = Debug|x64 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x86.ActiveCfg = Debug|Win32 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Debug|x86.Build.0 = Debug|Win32 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|Any CPU.ActiveCfg = Release|Win32 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x64.ActiveCfg = Release|x64 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x64.Build.0 = Release|x64 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x86.ActiveCfg = Release|Win32 + {4FA32C01-2B57-4D78-A079-905295575CAD}.Release|x86.Build.0 = Release|Win32 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x64.ActiveCfg = Debug|x64 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x64.Build.0 = Debug|x64 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x86.ActiveCfg = Debug|x86 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Debug|x86.Build.0 = Debug|x86 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|Any CPU.Build.0 = Release|Any CPU + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x64.ActiveCfg = Release|x64 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x64.Build.0 = Release|x64 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x86.ActiveCfg = Release|x86 + {14EC8B28-633C-451B-864D-829D1D0D02A5}.Release|x86.Build.0 = Release|x86 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x64.ActiveCfg = Debug|x64 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x64.Build.0 = Debug|x64 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x86.ActiveCfg = Debug|x86 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Debug|x86.Build.0 = Debug|x86 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|Any CPU.Build.0 = Release|Any CPU + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x64.ActiveCfg = Release|x64 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x64.Build.0 = Release|x64 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x86.ActiveCfg = Release|x86 + {20974E0D-C43C-46E7-8F34-1457613024BD}.Release|x86.Build.0 = Release|x86 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x64.ActiveCfg = Debug|x64 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x64.Build.0 = Debug|x64 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x86.ActiveCfg = Debug|Win32 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Debug|x86.Build.0 = Debug|Win32 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|Any CPU.ActiveCfg = Release|Win32 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x64.ActiveCfg = Release|x64 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x64.Build.0 = Release|x64 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x86.ActiveCfg = Release|Win32 + {6A9CF653-0969-492F-AB03-B6C01CD8AA3F}.Release|x86.Build.0 = Release|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Debug|x64.ActiveCfg = Debug|x64 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Debug|x64.Build.0 = Debug|x64 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Debug|x86.ActiveCfg = Debug|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Debug|x86.Build.0 = Debug|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Release|Any CPU.ActiveCfg = Release|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Release|x64.ActiveCfg = Release|x64 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Release|x64.Build.0 = Release|x64 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Release|x86.ActiveCfg = Release|Win32 + {9DC43A8D-8596-4704-9982-C2BAD7087DE9}.Release|x86.Build.0 = Release|Win32 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|x64.ActiveCfg = Debug|x64 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|x64.Build.0 = Debug|x64 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|x86.ActiveCfg = Debug|x86 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Debug|x86.Build.0 = Debug|x86 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|Any CPU.Build.0 = Release|Any CPU + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|x64.ActiveCfg = Release|x64 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|x64.Build.0 = Release|x64 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|x86.ActiveCfg = Release|x86 + {CCC57338-7DDC-4106-BF33-2538188D17EA}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BE5B568C-B40E-4555-989A-28585B5D06E0} + EndGlobalSection +EndGlobal diff --git a/clrinject/clrinject.cpp b/clrinject/clrinject.cpp index 29f90f5..042a611 100644 --- a/clrinject/clrinject.cpp +++ b/clrinject/clrinject.cpp @@ -103,7 +103,7 @@ static DWORD WINAPI RemoteProc(void * param) { retVal = 2; goto cleanup2; } - Runtime& resultRuntime = result.runtimes[result.numRuntimes++]; + RuntimeInfo& resultRuntime = result.runtimes[result.numRuntimes++]; ICLRRuntimeInfo* pCLRRuntimeInfo = NULL; status = pCLRRuntimeInfoThunk->QueryInterface(CC(IID_ICLRRuntimeInfo), (LPVOID*)&pCLRRuntimeInfo); @@ -134,7 +134,7 @@ static DWORD WINAPI RemoteProc(void * param) { retVal = 2; goto cleanup5; } - AppDomain& resultAppDomain = resultRuntime.appDomains[resultRuntime.numAppDomains++]; + AppDomainInfo& resultAppDomain = resultRuntime.appDomains[resultRuntime.numAppDomains++]; mscorlib::_AppDomain * pAppDomain = NULL; status = pAppDomainThunk->QueryInterface(CC(__uuidof(mscorlib::_AppDomain)), (LPVOID*)&pAppDomain); diff --git a/clrinject/clrinject.h b/clrinject/clrinject.h index 91e8a95..4701ac6 100644 --- a/clrinject/clrinject.h +++ b/clrinject/clrinject.h @@ -4,18 +4,18 @@ #define MAX_RUNTIMES 8 #define MAX_APPDOMAINS 32 -struct AppDomain { +struct AppDomainInfo { OLECHAR friendlyName[256]; bool injected; }; -struct Runtime { +struct RuntimeInfo { WCHAR version[32]; BOOL started; DWORD startedFlags; int numAppDomains; - AppDomain appDomains[MAX_APPDOMAINS]; + AppDomainInfo appDomains[MAX_APPDOMAINS]; }; struct InjectionResult { @@ -24,7 +24,7 @@ struct InjectionResult { char statusMessage[256]; int numRuntimes; - Runtime runtimes[MAX_RUNTIMES]; + RuntimeInfo runtimes[MAX_RUNTIMES]; }; struct InjectionOptions { diff --git a/clrinject/clrinject.vcxproj b/clrinject/clrinject.vcxproj index 3881893..8fdff63 100644 --- a/clrinject/clrinject.vcxproj +++ b/clrinject/clrinject.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -28,26 +28,26 @@ StaticLibrary true - v140 + v141 MultiByte StaticLibrary true - v140 + v141 MultiByte StaticLibrary false - v140 + v141 MultiByte true StaticLibrary false - v140 + v141 MultiByte true diff --git a/invader/invader.cs b/invader/invader.cs index 076fc32..167968b 100644 --- a/invader/invader.cs +++ b/invader/invader.cs @@ -1,24 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Invader -{ - public class Invader - { - static int Main(string[] args) { - Console.WriteLine("data = "+ AppDomain.CurrentDomain.GetData("dummy")); - Console.Write("new data = "); - AppDomain.CurrentDomain.SetData("dummy", Console.ReadLine()); - - return 0x12345678; - } - - public Invader() - { - AppDomain.CurrentDomain.SetData("dummy", "Data set from Invader.Invader.Invader()!"); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Invader +{ + public class Invader + { + static int Main(string[] args) { + Console.WriteLine("Current data is: "+ AppDomain.CurrentDomain.GetData("dummy")); + AppDomain.CurrentDomain.SetData("dummy", "You have been invaded !!"); + + return 0; + } + + public Invader() + { + AppDomain.CurrentDomain.SetData("dummy", "Data set from Invader.Invader.Invader()!"); + } + } +} diff --git a/invader/invader.csproj b/invader/invader.csproj index 08221a8..642d9f9 100644 --- a/invader/invader.csproj +++ b/invader/invader.csproj @@ -1,83 +1,91 @@ - - - - - Debug - AnyCPU - {20974E0D-C43C-46E7-8F34-1457613024BD} - Exe - Properties - invader - invader - v4.5.2 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\x64\Release\ - TRACE - true - pdbonly - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {20974E0D-C43C-46E7-8F34-1457613024BD} + Exe + Properties + invader + invader + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/victim/victim.csproj b/victim/victim.csproj index 48d05fa..d4c6aec 100644 --- a/victim/victim.csproj +++ b/victim/victim.csproj @@ -1,81 +1,89 @@ - - - - - Debug - AnyCPU - {14EC8B28-633C-451B-864D-829D1D0D02A5} - Exe - Properties - victim - victim - v4.5.2 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - bin\x64\Debug\ - DEBUG;TRACE - full - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - bin\x64\Release\ - TRACE - true - pdbonly - x64 - prompt - MinimumRecommendedRules.ruleset - true - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {14EC8B28-633C-451B-864D-829D1D0D02A5} + Exe + Properties + victim + victim + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file