Skip to content

Instantly share code, notes, and snippets.

@jarek-przygodzki
Last active August 18, 2023 09:26
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarek-przygodzki/0fd8b2c12a91d0141ca032794d08c05e to your computer and use it in GitHub Desktop.
Save jarek-przygodzki/0fd8b2c12a91d0141ca032794d08c05e to your computer and use it in GitHub Desktop.
procmon - tools to monitor process creation on various platforms
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
/*
#include <linux/netlink.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
*/
import "C"
func main() {
sock, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_DGRAM, unix.NETLINK_CONNECTOR)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return
}
addr := &unix.SockaddrNetlink{Family: unix.AF_NETLINK, Groups: C.CN_IDX_PROC, Pid: uint32(os.Getpid())}
err = unix.Bind(sock, addr)
if err != nil {
fmt.Fprintf(os.Stderr, "bind: %v\n", err)
return
}
defer func() {
send(sock, C.PROC_CN_MCAST_IGNORE)
unix.Close(sock)
}()
err = send(sock, C.PROC_CN_MCAST_LISTEN)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return
}
for {
p := make([]byte, 1024)
nbytes, from, err := unix.Recvfrom(sock, p, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return
}
pid := from.(*unix.SockaddrNetlink).Pid
if pid != 0 {
fmt.Fprintf(os.Stderr, "sender was not kernel (PID %d)", pid)
return
}
nlmessages, err := syscall.ParseNetlinkMessage(p[:nbytes])
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return
}
for _, m := range nlmessages {
if m.Header.Type == unix.NLMSG_DONE {
cnhdr := (*C.struct_cn_msg)(unsafe.Pointer(&m.Data[0]))
ptr := uintptr(unsafe.Pointer(cnhdr))
ptr += unsafe.Sizeof(*cnhdr)
pe := (*C.struct_proc_event)(unsafe.Pointer(ptr))
switch pe.what {
case C.PROC_EVENT_EXEC:
e := (*C.struct_exec_proc_event)(unsafe.Pointer(&pe.event_data))
fmt.Printf("Process started: PID %d\n", e.process_pid)
case C.PROC_EVENT_EXIT:
e := (*C.struct_exit_proc_event)(unsafe.Pointer(&pe.event_data))
fmt.Printf("Process exited: PID %d\n", e.process_pid)
}
}
}
}
}
func send(sockfd int, op C.enum_proc_cn_mcast_op) error {
cnhdr := &C.struct_cn_msg{
id: C.struct_cb_id{idx: C.CN_IDX_PROC, val: C.CN_VAL_PROC},
len: C.__u16(C.sizeof_enum_proc_cn_mcast_op),
}
header := unix.NlMsghdr{
Len: uint32(C.sizeof_struct_nlmsghdr + C.sizeof_struct_cn_msg + C.sizeof_enum_proc_cn_mcast_op),
Type: uint16(unix.NLMSG_DONE),
Flags: 0,
Seq: 0,
Pid: uint32(os.Getpid()),
}
buf := bytes.NewBuffer(make([]byte, 0, header.Len))
binary.Write(buf, binary.LittleEndian, header)
binary.Write(buf, binary.LittleEndian, cnhdr)
binary.Write(buf, binary.LittleEndian, op)
destAddr := &unix.SockaddrNetlink{Family: unix.AF_NETLINK, Groups: C.CN_IDX_PROC, Pid: 0} // 0 is the kernel
return unix.Sendto(sockfd, buf.Bytes(), 0, destAddr)
}
/*
* Useful to monitor process creation when additional tools cannot be installed.
*
* It depends only on .NET framework (csc compiler is part of standard installation, somewhere in C:\Windows\Microsoft.NET\Framework64\)
*
* csc procmon_wmi.cs
*/
using System;
using System.Management;
class ProcessMonitor
{
static public void Main(String[] args)
{
var processStartEvent =
new ManagementEventWatcher("SELECT * FROM Win32_ProcessStartTrace");
var processStopEvent =
new ManagementEventWatcher("SELECT * FROM Win32_ProcessStopTrace");
processStartEvent.EventArrived +=
new EventArrivedEventHandler(
delegate (object sender, EventArrivedEventArgs e)
{
var processName = e.NewEvent.Properties["ProcessName"].Value;
var processId = e.NewEvent.Properties["ProcessID"].Value;
Console.WriteLine("{0} Process started. Name: {1} | PID: {2}",
DateTime.Now, processName, processId);
});
processStopEvent.EventArrived +=
new EventArrivedEventHandler(
delegate (object sender, EventArrivedEventArgs e)
{
var processName = e.NewEvent.Properties["ProcessName"].Value;
var processId = e.NewEvent.Properties["ProcessID"].Value;
Console.WriteLine("{0} Process stopped. Name: {1} | PID: {2}",
DateTime.Now, processName, processId);
});
processStartEvent.Start();
processStopEvent.Start();
Console.ReadKey();
}
}
#!/usr/bin/env python
#
# Requries WMI and pywin32 modules. Install with
# ```
# pip install wmi
# pip install pywin32
# ````
#
import wmi, logging
logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)
c = wmi.WMI()
process_watcher = c.Win32_Process.watch_for("creation")
while True:
new_process = process_watcher()
processName = new_process.Caption
processId = new_process.ProcessId
logging.info("Process started. Name: %s | PID: %d", processName, processId)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment