kernel32.searchpath 是不是有托管 API?

Posted

技术标签:

【中文标题】kernel32.searchpath 是不是有托管 API?【英文标题】:Is there a managed API for kernel32.searchpath?kernel32.searchpath 是否有托管 API? 【发布时间】:2010-12-13 15:40:07 【问题描述】:

是否有用于 kernel32.searchpath 的托管 API? 即不使用 pinvoke。

http://www.pinvoke.net/default.aspx/kernel32.searchpath

【问题讨论】:

【参考方案1】:
    static void Main(string[] args)
    

        string lpPath = null;
        string lpFileName = "notepad";
        string lpExtension = ".exe";
        int nBufferLength = 255;
        string lpBuffer = "";
        string lpFilePart = "";

        int bufferSize = SearchPath(lpPath, lpFileName, lpExtension, nBufferLength, out lpBuffer, out lpFilePart);

    

    private static int SearchPath(string lpPath, string lpFileName, string lpExtension, int nBufferLength, out string lpBuffer, out string lpFilePart)
    
        // lpPath [in, optional] 
        // The path to be searched for the file. 
        // If this parameter is NULL, the function searches for a matching file using a registry-dependent system search path.

        //lpFileName [in] 
        //The name of the file for which to search.

        //lpExtension [in, optional] 
        //The extension to be added to the file name when searching for the file. The first character of the file name extension must be a period (.). The extension is added only if the specified file name does not end with an extension. 

        //If a file name extension is not required or if the file name contains an extension, this parameter can be NULL.

        //nBufferLength [in] 
        //The size of the buffer that receives the valid path and file name, in TCHARs.

        //lpBuffer [out] 
        //A pointer to the buffer to receive the path and file name of the file found. The string is a null-terminated string.

        //lpFilePart [out, optional] 
        //A pointer to the variable to receive the address (within lpBuffer) of the last component of the valid path and file name, which is the address of the character immediately following the final backslash (\) in the path.

        //Return Value
        //If the function succeeds, the value returned is the length, in TCHARs, of the string that is copied to the buffer, not including the terminating null character. If the return value is greater than nBufferLength, the value returned is the size of the buffer that is required to hold the path.

        //If the function fails, the return value is zero. 

        List<string> pathsToSearch = new List<string>();
        string currentWorkingFolder = Environment.CurrentDirectory;
        string path = System.Environment.GetEnvironmentVariable("path");
        lpBuffer = "";
        lpFilePart = "";

        if (lpPath == null)
        
            RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager");
            object safeProcessSearchModeObject = key.GetValue("SafeProcessSearchMode");
            if (safeProcessSearchModeObject != null)
            
                int safeProcessSearchMode = (int)safeProcessSearchModeObject;
                if (safeProcessSearchMode == 1)
                
                    // When the value of this registry key is set to "1", 
                    // SearchPath first searches the folders that are specified in the system path, 
                    // and then searches the current working folder. 
                    pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[]  Path.PathSeparator , StringSplitOptions.None));
                    pathsToSearch.Add(currentWorkingFolder);
                
                else 
                
                    // When the value of this registry entry is set to "0", 
                    // the computer first searches the current working folder, 
                    // and then searches the folders that are specified in the system path. 
                    // The system default value for this registry key is "0".
                    pathsToSearch.Add(currentWorkingFolder);
                    pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[]  Path.PathSeparator , StringSplitOptions.None));
                
            
            else
            
                // Default 0 case
                pathsToSearch.Add(currentWorkingFolder);
                pathsToSearch.AddRange(Environment.GetEnvironmentVariable("PATH").Split(new char[]  Path.PathSeparator , StringSplitOptions.None));
            
        
        else
        
            // Path was provided, use it
            pathsToSearch.Add(lpPath);
        

        FileInfo foundFile = SearchPath(pathsToSearch, lpExtension, lpFileName);
        if (foundFile!= null)
        
            lpBuffer = Path.Combine(foundFile.DirectoryName, foundFile.Name);
            lpFilePart = foundFile.Name;

        

        return lpBuffer.Length;
    

    private static FileInfo SearchPath(List<string> paths, string extension, string fileNamePart)
    
        foreach (string path in paths)
        
            DirectoryInfo dir = new DirectoryInfo(path);
            var fileInfo = dir.GetFiles().Where(file => file.Extension == extension && file.Name.Contains(fileNamePart));
            if (fileInfo.Any())
                return fileInfo.First();
        
        return null;
    

【讨论】:

不错,但您的两种搜索模式都不正确。见docs.microsoft.com/en-us/windows/win32/dlls/…【参考方案2】:

不是真的,除非您自己计算在 C# 中重新实现函数的整个逻辑,这将是浪费时间,IMO,当几行 P/Invoke 也能做到这一点时。

【讨论】:

@codeka - P/Invoke 不适用于单声道(如果那是需要托管解决方案的驱动程序)。显然,无论出于何种原因,P/Invoke 都不会为 Simon 做同样的事情。不是一个很有帮助的答案。 @Michael:在单声道中实现 SearchPath 甚至没有意义(至少在 Linux 上,Windows 上单声道中的 P/Invoke 可以正常工作)。【参考方案3】:

您可以使用 DirectoryInfo.GetFiles(String searchPattern, SearchOption searchOption)。要获取包含子目录的目录中的所有 *.exe 文件,您可以使用:

DirectoryInfo di = new DirectoryInfo("c:\temp");
var files = di.GetFiles("*.exe", SearchOption.AllDirectories);

查看http://msdn.microsoft.com/en-us/library/ms143327.aspx 的 MSDN 文档

【讨论】:

这并不是一个真正的最佳解决方案。这可能需要几分钟并返回错误的结果。

以上是关于kernel32.searchpath 是不是有托管 API?的主要内容,如果未能解决你的问题,请参考以下文章

kernel pwn-kernel UAF

kernel pwn-kernel UAF

openwrt 怎么更换kernel

XDP/eBPF — 基于 eBPF 的 Linux Kernel 可观测性

XDP/eBPF — 基于 eBPF 的 Linux Kernel 可观测性

Python----Kernel SVM