C#获取x86/x64软件注册信息

问题描述:如果当前软件是x86或Any CPU平台编译,要想获取到x64软件注册信息默认是不支持的,但又不可避免需要检查其他软件是否完成安装,因此,需要对32位和64位软件注册信息进行全面检查,我们通过调用Advapi32.dll来实现。 

1)默认获取与当前编译平台对应的软件注册信息

List<string> displayNameList = new List<string>();
Microsoft.Win32.RegistryKey uninstallNode = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.Default, RegistryRights.FullControl);
foreach (string subKeyName in uninstallNode.GetSubKeyNames())
{
    Microsoft.Win32.RegistryKey subKey = uninstallNode.OpenSubKey(subKeyName, false);
    object displayName = subKey.GetValue("DisplayName");
    if (displayName != null)
    {
        displayNameList.Add(displayName.ToString());
    }
}

2)获取所有软件注册信息

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;

namespace CHC.Controller.ApplicationService
{
    public class RegisterTableUnitity
    {
        #region 32位程序读写64注册表

        static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000;
        static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001;
        static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
        static UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
        static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005;

        // 关闭64位(文件系统)的操作转向
         [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
        // 开启64位(文件系统)的操作转向
         [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);    
   
        // 获取操作Key值句柄
         [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions,int samDesired, out UIntPtr phkResult);
        //关闭注册表转向(禁用特定项的注册表反射)
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern long RegDisableReflectionKey(UIntPtr hKey);
        //使能注册表转向(开启特定项的注册表反射)
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern long RegEnableReflectionKey(UIntPtr hKey);
        //获取Key值(即:Key值句柄所标志的Key对象的值)
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegQueryValueEx(UIntPtr hKey, string lpValueName, int lpReserved,
                                                  out uint lpType, System.Text.StringBuilder lpData,
                                                   ref uint lpcbData);
        [DllImport("advapi32.dll", EntryPoint = "RegEnumKeyEx")]
        extern private static int RegEnumKeyEx(UIntPtr hkey,
           uint index,
           StringBuilder lpName,
           ref uint lpcbName,
           IntPtr reserved,
           IntPtr lpClass,
           IntPtr lpcbClass,
           out long lpftLastWriteTime);

        [DllImport("advapi32.dll", SetLastError = false)]
        static extern int RegCreateKeyEx(
            UIntPtr hKey,
            string lpSubKey,
            IntPtr Reserved,
            string lpClass,
            RegOption dwOptions,
            RegSAM samDesired,
            ref IntPtr lpSecurityAttributes,
            out UIntPtr phkResult,
            out RegResult lpdwDisposition);

        [Flags]
        public enum RegOption
        {
            NonVolatile = 0x0,
            Volatile = 0x1,
            CreateLink = 0x2,
            BackupRestore = 0x4,
            OpenLink = 0x8
        }

        [Flags]
        public enum RegSAM
        {
            QueryValue = 0x0001,
            SetValue = 0x0002,
            CreateSubKey = 0x0004,
            EnumerateSubKeys = 0x0008,
            Notify = 0x0010,
            CreateLink = 0x0020,
            WOW64_32Key = 0x0200,
            WOW64_64Key = 0x0100,
            WOW64_Res = 0x0300,
            Read = 0x00020019,
            Write = 0x00020006,
            Execute = 0x00020019,
            AllAccess = 0x000f003f
        }

        public enum RegResult
        {
            CreatedNewKey = 0x00000001,
            OpenedExistingKey = 0x00000002
        }

        private static UIntPtr TransferKeyName(string keyName)
         {
             switch (keyName)
             {
                 case "HKEY_CLASSES_ROOT":
                     return HKEY_CLASSES_ROOT;
                 case "HKEY_CURRENT_USER":
                     return HKEY_CURRENT_USER;
                 case "HKEY_LOCAL_MACHINE":
                     return HKEY_LOCAL_MACHINE;
                 case "HKEY_USERS":
                    return HKEY_USERS;
                 case "HKEY_CURRENT_CONFIG":
                     return HKEY_CURRENT_CONFIG;
             }
 
             return HKEY_CLASSES_ROOT;
         }
 
         public static List<string> Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName)
         {
             List<string> programKeyValueList = new List<string>();
             int KEY_QUERY_VALUE = (0x0001);
             int KEY_WOW64_64KEY = (0x0100);
             int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);
 
             try
             {
                 //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关)
                 UIntPtr hKey = TransferKeyName(parentKeyName);
                 //记录读取到的Key值
                 StringBuilder result = new StringBuilder("".PadLeft(1024));
                 uint resultSize = 1024;
                 uint lpType = 0;
                 //关闭文件系统转向 
                 IntPtr oldWOW64State = new IntPtr();
                 //if (Wow64DisableWow64FsRedirection(ref oldWOW64State))
                 {
                    RegResult regResult;
                    IntPtr lpSecurityAttributes = IntPtr.Zero;
                    获得操作Key值的句柄
                    UIntPtr hKeyEx = UIntPtr.Zero;
                    int r = RegCreateKeyEx(hKey, subKeyName,IntPtr.Zero, null, RegOption.NonVolatile, RegSAM.EnumerateSubKeys | RegSAM.WOW64_64Key,ref lpSecurityAttributes,out hKeyEx, out regResult);
                    StringBuilder subsubKeyName = new StringBuilder();
                    uint i = 0;
                    long lastWriteTime;
                    while (true)
                    {
                        uint cbMaxSubKey = 100; //键名的长度
                        int reke = RegEnumKeyEx(hKeyEx, i, subsubKeyName, ref cbMaxSubKey, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out lastWriteTime);
                        if (reke == 0)
                        {
                            //声明将要获取Key值的句柄
                            UIntPtr pHKey = UIntPtr.Zero;
                            result = new StringBuilder("".PadLeft(1024));
                            获得操作Key值的句柄
                            RegOpenKeyEx(hKey, subKeyName + "\\" + subsubKeyName, 0,(int)(RegSAM.QueryValue | RegSAM.WOW64_64Key), out pHKey);
                            //关闭注册表转向(禁止特定项的注册表反射)
                            //RegDisableReflectionKey(pHKey);

                            获取访问的Key值
                            RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);

                             //打开注册表转向(开启特定项的注册表反射)
                            //RegEnableReflectionKey(pHKey);

                            i++;
                            if (!string.IsNullOrEmpty(result.ToString().Trim()))
                            {
                                programKeyValueList.Add(result.ToString().Trim());
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
 
                 //打开文件系统转向
                 //Wow64RevertWow64FsRedirection(oldWOW64State);
 
                 //返回Key值
                 return programKeyValueList;
             }
             catch (Exception ex)
             {
                 return null;
             }
         }

        public static List<string> Get32BitRegistryKey(string parentKeyName, string subKeyName, string keyName)
        {
            List<string> programKeyValueList = new List<string>();
            int KEY_QUERY_VALUE = (0x0001);
            int KEY_WOW64_64KEY = (0x0100);
            int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);

            try
            {
                //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关)
                UIntPtr hKey = TransferKeyName(parentKeyName);
                //记录读取到的Key值
                StringBuilder result = new StringBuilder("".PadLeft(1024));
                uint resultSize = 1024;
                uint lpType = 0;
                //关闭文件系统转向 
                IntPtr oldWOW64State = new IntPtr();
                //if (Wow64DisableWow64FsRedirection(ref oldWOW64State))
                {
                    RegResult regResult;
                    IntPtr lpSecurityAttributes = IntPtr.Zero;
                    获得操作Key值的句柄
                    UIntPtr hKeyEx = UIntPtr.Zero;
                    int r = RegCreateKeyEx(hKey, subKeyName, IntPtr.Zero, null, RegOption.NonVolatile, RegSAM.EnumerateSubKeys | RegSAM.WOW64_32Key, ref lpSecurityAttributes, out hKeyEx, out regResult);
                    StringBuilder subsubKeyName = new StringBuilder();
                    uint i = 0;
                    long lastWriteTime;
                    while (true)
                    {
                        uint cbMaxSubKey = 100; //键名的长度
                        int reke = RegEnumKeyEx(hKeyEx, i, subsubKeyName, ref cbMaxSubKey, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, out lastWriteTime);
                        if (reke == 0)
                        {
                            //声明将要获取Key值的句柄
                            UIntPtr pHKey = UIntPtr.Zero;
                            //获取键值结果
                            result = new StringBuilder("".PadLeft(1024));
                            获得操作Key值的句柄
                            RegOpenKeyEx(hKey, subKeyName + "\\" + subsubKeyName, 0, (int)(RegSAM.QueryValue | RegSAM.WOW64_32Key), out pHKey);
                            //关闭注册表转向(禁止特定项的注册表反射)
                            //RegDisableReflectionKey(pHKey);

                            获取访问的Key值
                            RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);

                             //打开注册表转向(开启特定项的注册表反射)
                            //RegEnableReflectionKey(pHKey);

                            i++;

                            if (!string.IsNullOrEmpty(result.ToString().Trim()))
                            {
                                programKeyValueList.Add(result.ToString().Trim());
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                //打开文件系统转向
                //Wow64RevertWow64FsRedirection(oldWOW64State);

                //返回Key值
                return programKeyValueList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 获取所有软件注册信息
        /// </summary>
        /// <returns></returns>
        public List<string> ProgramInstalledList()
        {
            try
            {
                List<string> displayNameList = new List<string>();
                displayNameList = RegisterTableUnitity.Get64BitRegistryKey("HKEY_LOCAL_MACHINE", @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "DisplayName");//uninstallNode.GetValue("DisplayName");
                displayNameList.AddRange(RegisterTableUnitity.Get32BitRegistryKey("HKEY_LOCAL_MACHINE", @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "DisplayName"));//uninstallNode.GetValue("DisplayName"););
                return displayNameList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #endregion
    }
}

遇到的几个问题记录如下:

1、注册表遍历时RegEnumKeyEx返回值为5,需要利用RegCreateKey或RegOpenKey时将RegSAM设为EnumerateSubKeys。

2、RegEnumKeyEx返回234,是因为参数ref cbMaxSubKey(最大键字符长度)被改变,长度不足造成的

3、开始利用RegOpenKeyEx获取句柄,不管怎么设置参数,Any CPU编译得到的都还是默认32位的软件的注册信息,得不到X64软件的注册信息

解决方案:尝试利用RegCreateKeyEx,设置RegSAM参数为RegSAM.EnumerateSubKeys|RegSAM.WOW64_64Key,成功得到64的软件注册信息,同理,如果要获取32位的软件注册信息,设置RegSAM.WOW64_32Key即可,这样就与当前软件编译平台没有关系了,所有的软件注册信息都能够获取到了。

4、该类在x64平台编译后,文件系统转向Wow64DisableWow64FsRedirection直接就返回false了,直接注释掉吧

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于在C#中实现注入任意DLL的需求,可以使用以下步骤来实现: 1. 首先,您需要创建一个C#的类库项目,用于编写注入代码。请确保项目的目标框架是.NET Framework,并且选择适当的目标CPU架构。 2. 在项目中添加对System.Process类的引用,以便我们可以获取目标进程的句柄。 3. 使用Process类来获取目标进程的句柄。您可以使用进程名称或进程ID来获取句柄。例如,以下代码获取名为"targetProcess.exe"的进程句柄: ```csharp Process targetProcess = Process.GetProcessesByName("targetProcess")?.FirstOrDefault(); IntPtr targetProcessHandle = targetProcess?.Handle; ``` 4. 使用OpenProcess函数打开目标进程的句柄。参数dwDesiredAccess设置为PROCESS_ALL_ACCESS以获取完全访问权限。 ```csharp [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId); const uint PROCESS_ALL_ACCESS = 0x1F0FFF; // 具有完全访问权限 IntPtr targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, targetProcessId); ``` 5. 使用VirtualAllocEx函数在目标进程中分配内存。参数lpAddress设置为0以让系统自动选择地址。参数dwSize设置为你要注入DLL的大小。 ```csharp [DllImport("kernel32.dll")] public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); IntPtr dllMemoryAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, (uint)dllBytes.Length, 0x1000, 0x40); ``` 6. 使用WriteProcessMemory函数将DLL的字节写入目标进程的内存中。 ```csharp [DllImport("kernel32.dll")] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten); bool success = WriteProcessMemory(targetProcessHandle, dllMemoryAddress, dllBytes, (uint)dllBytes.Length, out int bytesWritten); ``` 7. 使用CreateRemoteThread函数在目标进程中创建一个远程线程,以加载注入的DLL。 ```csharp [DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); IntPtr loadLibraryAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); IntPtr threadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, loadLibraryAddress, dllMemoryAddress, 0, IntPtr.Zero); ``` 请注意,上述代码只是一个示例,实际在实现过程中可能需要根据具体情况进行修改和调整。此外,为了支持不同的操作系统和CPU架构,您可能需要根据编译条件进行相应的处理。 希望以上信息对您有所帮助!如有任何疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值