微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

知道父进程的句柄,如何获取子进程句柄?

如何解决知道父进程的句柄,如何获取子进程句柄?

在 Windows 10 上,我想在每个子/孙子进程上使用 <root> <name><s>Light and dark</s></name> <address> <sector>142</sector> <location>Noida</location> </address> </root> 挂起整个进程树。

我使用 NtSuspendProcess 启动父进程,进程树应如下所示:

exec.Command("java",...)

我可以使用以下命令检索进程父句柄 uintptr:

myapp (executes cmd.Start())
   \__java (parent)
        \__java
             |__proc1
             \__proc2

我不知道如何从父句柄(或 pid)中检索子进程的句柄,以便单独挂起它们。
(由于不存在将所有父进程和子进程一起暂停的选项,我应该一一暂停吗?)

  • 我尝试列出所有进程,然后仅选择具有正确父 pid 的进程,但是我找不到通过知道子 pid 来可靠地获取父 pid 的方法(另外,在孙进程的情况下会出现问题,另外我更喜欢只使用手柄,这应该更可靠)。
  • 我尝试创建一个生成一个进程的作业,以便能够使用作业的句柄列出所有子 pid/句柄,但它非常复杂,需要一些低级实现(不需要非常适合cmd := exec.Command("java",...) cmd.Start() // mirror os.Process struct type osprocmirror struct { Pid int handle uintptr isdone uint32 sigMu sync.RWMutex } handle := (*osprocmirror)(unsafe.Pointer(cmd.Process)) 包)。
  • 我从 os.exec 中找到了一个名为 user32.dll 的 windows 函数并开始实现它,但由于我不完全理解它是如何工作的(它是否只适用于具有图形窗口的进程?因为我根本不使用 GUI),我想知道其他可能的解决方案(也许更简单)。

有没有更简单的方法可以从父句柄获取所有子进程句柄?
如果没有,您是否有此类实现的好例子?

谢谢

解决方法

我创建了一个小脚本来实现这一点(检查 here
我会在这里发布:

// This is a script to retrieve the child processes pids of a process (retrieve the complete process tree)
// Tn this example the process identified by pid 7400 is used
// (please to run the test chose a process pid that has at least 1 child process)
// (tested on windows)

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func main() {
    rootPid := uint32(7400)

    tree,err := getTreePids(rootPid)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("tree [",len(tree),"]:\t",tree)
}

// getTreePids will return a list of pids that represent the tree of process pids originating from the specified one.
// (they are ordered: [parent,1 gen child,2 gen child,...])
func getTreePids(rootPid uint32) ([]uint32,error) {
    // https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32
    procEntry := syscall.ProcessEntry32{}
    parentLayer := []uint32{rootPid}
    treePids := parentLayer
    foundRootPid := false

    snapshot,err := syscall.CreateToolhelp32Snapshot(uint32(syscall.TH32CS_SNAPPROCESS),0)
    if err != nil {
        return nil,err
    }
    defer syscall.CloseHandle(snapshot)

    procEntry.Size = uint32(unsafe.Sizeof(procEntry))

    for {
        // set procEntry to the first process in the snapshot
        err = syscall.Process32First(snapshot,&procEntry)
        if err != nil {
            return nil,err
        }

        // loop through the processes in the snapshot,if the parent pid of the analyzed process
        // is in in the parent layer,append the analyzed process pid in the child layer
        var childLayer []uint32
        for {
            if procEntry.ProcessID == rootPid {
                foundRootPid = true
            }

            if contains(parentLayer,procEntry.ParentProcessID) {
                // avoid adding a pid if it's already contained in treePids
                // useful for pid 0 whose ppid is 0 and would lead to recursion (windows)
                if !contains(treePids,procEntry.ProcessID) {
                    childLayer = append(childLayer,procEntry.ProcessID)
                }
            }

            // advance to next process in snapshot
            err = syscall.Process32Next(snapshot,&procEntry)
            if err != nil {
                // if there aren't anymore processes to be analyzed,break out of the loop
                break
            }
        }

        // if the specified rootPid is not found,return error
        if !foundRootPid {
            return nil,fmt.Errorf("specified rootPid not found")
        }

        // fmt.Println(childLayer)

        // there are no more child processes,return the process tree
        if len(childLayer) == 0 {
            return treePids,nil
        }

        // append the child layer to the tree pids
        treePids = append(treePids,childLayer...)

        // to analyze the next layer,set the child layer to be the new parent layer
        parentLayer = childLayer
    }
}

func contains(list []uint32,e uint32) bool {
    for _,l := range list {
        if l == e {
            return true
        }
    }
    return false
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。