├── .vscode └── settings.json ├── README.md ├── dns ├── dns_socket_pro.c └── dns_udp_pro.c ├── gotls ├── https_go_tcp.c └── uprobe_go_ssl.c ├── http ├── http.c └── kprobe_http.c ├── https ├── https_py_tcp.c ├── original_https.c ├── uprobe_py_ssl.c └── uprobe_ssl.c ├── log └── flow.log ├── mygod.py ├── requirements.txt ├── tcp └── tcp.c ├── test ├── test_gohttps.py ├── test_http.py ├── test_https.py ├── test_pyhttps.py └── test_udp.py ├── udp ├── kprobe_udp.c └── udp.c ├── user ├── __pycache__ │ ├── h.cpython-310.pyc │ ├── user_dns.cpython-310.pyc │ ├── user_go_https.cpython-310.pyc │ ├── user_http.cpython-310.pyc │ ├── user_https.cpython-310.pyc │ ├── user_py_https.cpython-310.pyc │ └── user_udp.cpython-310.pyc ├── user_dns.py ├── user_go_https.py ├── user_http.py ├── user_https.py ├── user_py_https.py └── user_udp.py └── utils ├── __pycache__ └── tools.cpython-310.pyc └── tools.py /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "fs.h": "c" 4 | } 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FlowGod 2 | 3 | FlowGod is a powerful process-level network flow sniffer tool based on eBPF. 4 | ``` 5 | ______ _ _____ _ 6 | | ____| | / ____| | | 7 | | |__ | | _____ _| | __ ___ __| | 8 | | __| | |/ _ \ \ /\ / / | |_ |/ _ \ / _` | 9 | | | | | (_) \ V V /| |__| | (_) | (_| | 10 | |_| |_|\___/ \_/\_/ \_____|\___/ \__,_| 11 | ``` 12 | FlowGod supports a variety of common protocols: UDP & TCP & HTTP & HTTPS & DNS (curl/wget/nc/python/go). 13 | 14 | ## Installation 15 | 安装`bcc`相关环境和依赖(软件包安装方式): 16 | ``` 17 | # For Ubuntu20.10+ 18 | sudo apt-get install -y make clang llvm libelf-dev libbpf-dev bpfcc-tools libbpfcc-dev linux-tools-$(uname -r) linux-headers-$(uname -r) 19 | 20 | # For RHEL8.2+ 21 | sudo yum install libbpf-devel make clang llvm elfutils-libelf-devel bpftool bcc-tools bcc-devel 22 | ``` 23 | 由于`bcc`版本问题导致程序无法执行,请选择源码编译的方式安装(推荐[0.25.0版本](https://github.com/iovisor/bcc/releases/tag/v0.25.0)),相关issue参考链接:https://github.com/iovisor/bcc/issues/3993 24 | ``` 25 | # 建议先使用软件包的方式安装bcc,若运行FlowGod程序出现bcc版本问题,可参考下面的命令编译安装合适版本的bcc 26 | 27 | apt purge bpfcc-tools libbpfcc python3-bpfcc 28 | wget https://github.com/iovisor/bcc/releases/download/v0.25.0/bcc-src-with-submodule.tar.gz 29 | tar xf bcc-src-with-submodule.tar.gz 30 | cd bcc/ 31 | apt install -y python-is-python3 32 | apt install -y bison build-essential cmake flex git libedit-dev libllvm11 llvm-11-dev libclang-11-dev zlib1g-dev libelf-dev libfl-dev python3-distutils 33 | apt install -y checkinstall 34 | mkdir build 35 | cd build/ 36 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DPYTHON_CMD=python3 .. 37 | make 38 | checkinstall 39 | ``` 40 | 具体源码编译安装`bcc`的文档请参考:https://github.com/iovisor/bcc/blob/master/INSTALL.md (推荐) 41 | 42 | Python相关包安装:`pip install -r requirements` 43 | 44 | ## Usage 45 | ``` 46 | -h, --help 显示FlowGod使用帮助信息并退出 47 | 48 | -l LIBSSL_PATH, --libssl LIBSSL_PATH 49 | 指定libssl.so相关文件路径,默认为 /lib/x86_64-linux-gnu/libssl.so.3 50 | 51 | -i INTERFACE, --interface INTERFACE 52 | 指定需要捕获流量的网卡,默认为ens3 53 | 54 | -p PID, --pid PID 指定需要捕获的进程,默认捕获所有进程 55 | 56 | -f [{udp,http,https,all} ...], --protocol [{udp,http,https,dns,all} ...] 57 | 指定需要捕获的协议类型,其中 all 代表 udp+http+https+dns 58 | 59 | --pyssl 指定需要捕获Python程序发出的HTTPS请求 60 | 61 | --gotls GO_PROGRAM_PATH 62 | 指定需要捕获Go程序发出的HTTPS请求,并提供Go程序所在文件路径 63 | ``` 64 | 65 | ## Examples 66 | - 监听pid为1314的进程从eth1网口发出的udp、http和https的请求 67 | ``` 68 | python3 mygod.py -l /lib/x86_64-linux-gnu/libssl.so.3 -i eth1 -f udp http https -p 1314 69 | ``` 70 | 71 | - 监听pid为1314的进程从eth1网口发出的udp、http和Python程序的https协议请求(目前FlowGod不支持同时指定https和pyssl参数) 72 | ``` 73 | python3 mygod.py -l /lib/x86_64-linux-gnu/libssl.so.3 -i eth1 -f udp http --pyssl -p 1314 74 | ``` 75 | 76 | - 监听pid为1314的进程从eth1网口发出的udp、http和指定Go程序的https协议请求(目前FlowGod不支持同时指定https和gotls参数) 77 | ``` 78 | python3 mygod.py -l /lib/x86_64-linux-gnu/libssl.so.3 -i eth1 -f udp http --gotls /path/to/go_program -p 1314 79 | ``` 80 | 81 | - 演示视频 82 | (测试环境:Ubuntu 22.04/Kernel 5.15.0-60-generic) 83 | [![FlowGod使用演示视频](https://i.ytimg.com/vi/W-8VLt-Q4GI/maxresdefault.jpg)](https://youtu.be/W-8VLt-Q4GI "FlowGod使用演示视频") 84 | 85 | 86 | ## Thanks 87 | [1] [bcc官方项目](https://github.com/iovisor/bcc):examples/tools 88 | [2] [eCapture(旁观者)](https://github.com/gojue/ecapture): capture SSL/TLS text content without CA cert Using eBPF 89 | 90 | - 特别鸣谢:[CFC4N](https://github.com/cfc4n) 在ecapture项目的discussion中对作者的建议和解答 91 | 92 | ## Todo 93 | - Dockerfile 94 | - CO-RE 95 | - NIPS 96 | -------------------------------------------------------------------------------- /dns/dns_socket_pro.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define IP_TCP 6 8 | #define ETH_HLEN 14 9 | 10 | struct data_key { 11 | u8 proto; 12 | u32 saddr; 13 | u32 daddr; 14 | u16 sport; 15 | u16 dport; 16 | }; 17 | 18 | struct data_value { 19 | u32 pid; 20 | u32 uid; 21 | u32 gid; 22 | char comm[64]; 23 | }; 24 | 25 | BPF_TABLE("extern", struct data_key, struct data_value, proc_dns_datas, 20480); 26 | 27 | BPF_PERF_OUTPUT(events_dns); 28 | 29 | int dns_matching(struct __sk_buff *skb){ 30 | u8 *cursor = 0; 31 | u16 sport; 32 | u16 dport; 33 | 34 | struct ethernet_t *ethernet = cursor_advance(cursor,sizeof(*ethernet)); 35 | if(ethernet->type == 0x0800){ //type保存了二层协议类型,ETH_P_IP、ETH_P_ARP,ETH_P_ALL 36 | struct ip_t *ip = cursor_advance(cursor,sizeof(*ip)); 37 | if(ip->nextp == IPPROTO_UDP){ //IP_TCP(0x06)、IPPROTO_UDP 38 | struct udp_t *udp = cursor_advance(cursor, sizeof(*udp)); 39 | struct data_key key = {}; 40 | key.proto = 17; 41 | 42 | key.saddr = ip->src; 43 | key.daddr = ip->dst; 44 | key.sport = udp->sport; 45 | key.dport = udp->dport; 46 | 47 | struct data_value *value; 48 | value = proc_dns_datas.lookup(&key); 49 | 50 | if (!value){ 51 | return 0; 52 | } 53 | 54 | sport = udp->sport; 55 | dport = udp->dport; 56 | 57 | if (dport == 53){ 58 | events_dns.perf_submit_skb(skb,skb->len,value,sizeof(struct data_value)); 59 | return 0; 60 | } 61 | } 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /dns/dns_udp_pro.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define IP_TCP 6 4 | #define ETH_HLEN 14 5 | 6 | struct data_key { 7 | u8 proto; 8 | u32 saddr; 9 | u32 daddr; 10 | u16 sport; 11 | u16 dport; 12 | }; 13 | 14 | struct data_value { 15 | u32 pid; 16 | u32 uid; 17 | u32 gid; 18 | char comm[64]; 19 | }; 20 | 21 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, proc_dns_datas, 20480); 22 | 23 | int trace_udp_sendmsg(struct pt_regs *ctx, struct sock *sk) { 24 | u16 sport = sk->sk_num; 25 | u16 dport = sk->sk_dport; 26 | 27 | u32 saddr = sk->sk_rcv_saddr; 28 | u32 daddr = sk->sk_daddr; 29 | u64 pid_tgid = bpf_get_current_pid_tgid(); 30 | u64 uid_gid = bpf_get_current_uid_gid(); 31 | 32 | struct data_key key = {.proto = 17}; 33 | key.saddr = htonl(saddr); 34 | key.daddr = htonl(daddr); 35 | key.sport = sport; 36 | key.dport = htons(dport); 37 | 38 | struct data_value value = {}; 39 | value.pid = pid_tgid >> 32; 40 | value.uid = (u32)uid_gid; 41 | value.gid = uid_gid >> 32; 42 | bpf_get_current_comm(value.comm, 64); 43 | 44 | proc_dns_datas.update(&key, &value); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /gotls/https_go_tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_BUFFER_SIZE 4000 7 | 8 | struct data_key { 9 | u32 pid; 10 | u32 tid; 11 | u32 uid; 12 | char comm[TASK_COMM_LEN]; 13 | }; 14 | 15 | struct data_value { 16 | s32 len; 17 | char buf[MAX_BUFFER_SIZE]; 18 | }; 19 | 20 | struct https_data { 21 | u32 pid; 22 | u32 uid; 23 | u32 saddr; 24 | u32 daddr; 25 | u16 sport; 26 | u16 dport; 27 | s32 len; 28 | char buf[MAX_BUFFER_SIZE]; 29 | }; 30 | 31 | struct session_key { 32 | u32 saddr; 33 | u32 daddr; 34 | u16 sport; 35 | u16 dport; 36 | }; 37 | 38 | 39 | struct Leaf { 40 | int timestamp; //timestamp in ns 41 | }; 42 | 43 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 44 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 45 | 46 | BPF_HASH(bpf_context_2, u64, struct https_data, 2048); 47 | BPF_ARRAY(bpf_context_gen_2, struct https_data, 1); 48 | 49 | BPF_TABLE_PUBLIC("extern", struct data_key, struct data_value, https_data, 4096); 50 | BPF_HASH(sessions, struct session_key, struct Leaf, 1024); 51 | 52 | BPF_PERF_OUTPUT(events_go_https); 53 | 54 | //通过在堆上创建内存绕过栈空间512字节大小限制 55 | static struct data_value *make_event_1(){ 56 | int zero = 0; 57 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 58 | if (!bpf_ctx) return 0; 59 | u64 id = bpf_get_current_pid_tgid(); 60 | bpf_context_1.update(&id, bpf_ctx); 61 | return bpf_context_1.lookup(&id); 62 | } 63 | 64 | static struct https_data *make_event_2(){ 65 | int zero = 0; 66 | struct https_data *bpf_ctx = bpf_context_gen_2.lookup(&zero); 67 | if (!bpf_ctx) return 0; 68 | u64 id = bpf_get_current_pid_tgid(); 69 | bpf_context_2.update(&id, bpf_ctx); 70 | return bpf_context_2.lookup(&id); 71 | } 72 | 73 | 74 | int trace_go_tcp_sendmsg(struct pt_regs *ctx, struct sock *sk) 75 | { 76 | 77 | u16 sport = sk->sk_num; 78 | u16 dport = sk->sk_dport; 79 | u32 saddr = sk->sk_rcv_saddr; 80 | u32 daddr = sk->sk_daddr; 81 | 82 | u64 pid_tgid = bpf_get_current_pid_tgid(); 83 | u32 pid = pid_tgid >> 32; 84 | u32 tid = (u32)pid_tgid; 85 | u32 uid = bpf_get_current_uid_gid(); 86 | 87 | struct session_key session_key = {}; 88 | session_key.saddr = htonl(saddr); 89 | session_key.daddr = htonl(daddr); 90 | session_key.sport = sport; 91 | session_key.dport = htons(dport); 92 | 93 | struct https_data *data = make_event_2(); 94 | if(!data) return 0; 95 | 96 | data->saddr = htonl(saddr); 97 | data->daddr = htonl(daddr); 98 | data->sport = sport; 99 | data->dport = htons(dport); 100 | data->pid = pid; 101 | data->uid = uid; 102 | 103 | struct data_key key = {}; 104 | key.pid = pid; 105 | key.tid = tid; 106 | key.uid = uid; 107 | bpf_get_current_comm(&key.comm, sizeof(key.comm)); 108 | 109 | struct data_value *value = make_event_1(); 110 | if(!value) return 0; 111 | 112 | value = https_data.lookup(&key); 113 | 114 | if (!value){ 115 | return 0; 116 | } 117 | 118 | data->len = value->len; 119 | bpf_probe_read(&(data->buf), MAX_BUFFER_SIZE, (char *)(value->buf)); 120 | 121 | struct Leaf zero = {0}; 122 | 123 | sessions.lookup_or_try_init(&session_key, &zero); 124 | struct Leaf * lookup_leaf = sessions.lookup(&session_key); 125 | 126 | if(lookup_leaf) { 127 | 128 | events_go_https.perf_submit(ctx, data, sizeof(struct https_data)); 129 | https_data.delete(&key); 130 | return 0; 131 | } 132 | 133 | https_data.delete(&key); 134 | return 0; 135 | 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /gotls/uprobe_go_ssl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_BUFFER_SIZE 4000 5 | #define recordTypeApplicationData 23 6 | 7 | #define GO_PARAM1(x) ((x)->ax) 8 | #define GO_PARAM2(x) ((x)->bx) 9 | #define GO_PARAM3(x) ((x)->cx) 10 | #define GO_PARAM4(x) ((x)->di) 11 | #define GO_PARAM5(x) ((x)->si) 12 | #define GO_PARAM6(x) ((x)->r8) 13 | #define GO_PARAM7(x) ((x)->r9) 14 | #define GO_PARAM8(x) ((x)->r10) 15 | #define GO_PARAM9(x) ((x)->r11) 16 | #define GOROUTINE(x) ((x)->r14) 17 | 18 | struct data_key { 19 | u32 pid; 20 | u32 tid; 21 | u32 uid; 22 | char comm[TASK_COMM_LEN]; 23 | }; 24 | 25 | struct data_value { 26 | s32 len; 27 | char buf[MAX_BUFFER_SIZE]; 28 | }; 29 | 30 | 31 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 32 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 33 | 34 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, https_data, 4096); 35 | 36 | //通过在堆上创建内存绕过栈空间512字节大小限制 37 | static struct data_value *make_event_1(){ 38 | int zero = 0; 39 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 40 | if (!bpf_ctx) return 0; 41 | u64 id = bpf_get_current_pid_tgid(); 42 | bpf_context_1.update(&id, bpf_ctx); 43 | return bpf_context_1.lookup(&id); 44 | } 45 | 46 | 47 | static void* go_get_argument_by_stack(struct pt_regs *ctx, int index) { 48 | void* ptr = 0; 49 | bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx)+(index*8))); 50 | return ptr; 51 | } 52 | 53 | //通过寄存器读取入参 54 | int go_https_register(struct pt_regs *ctx){ 55 | 56 | struct data_key data_k = {}; 57 | struct data_value *data_v = make_event_1(); 58 | if(!data_v) return 0; 59 | 60 | s32 len, record_type; 61 | const char *str; 62 | void *len_ptr; 63 | 64 | 65 | void *record_type_ptr; 66 | record_type_ptr = (void *)GO_PARAM2(ctx); 67 | 68 | bpf_probe_read_kernel(&record_type, sizeof(record_type), (void*)&record_type_ptr); 69 | 70 | if (record_type != recordTypeApplicationData){ 71 | return 0; 72 | } 73 | 74 | 75 | u64 pid_tgid = bpf_get_current_pid_tgid(); 76 | u32 pid = pid_tgid >> 32; 77 | u32 tid = (u32)pid_tgid; 78 | u32 uid = bpf_get_current_uid_gid(); 79 | 80 | data_k.pid = pid; 81 | data_k.tid = tid; 82 | data_k.uid = uid; 83 | bpf_get_current_comm(&data_k.comm, sizeof(data_k.comm)); 84 | 85 | str = (void*)GO_PARAM3(ctx); 86 | len_ptr = (void*)GO_PARAM4(ctx); 87 | bpf_probe_read_kernel(&len, sizeof(len), (void*)&len_ptr); 88 | 89 | data_v->len = len; 90 | 91 | bpf_probe_read_user(&data_v->buf,sizeof(data_v->buf),(void *)str); 92 | 93 | https_data.update(&data_k, data_v); 94 | 95 | return 0; 96 | 97 | } 98 | 99 | //通过堆栈读取入参 100 | int go_https_stack(struct pt_regs *ctx){ 101 | 102 | struct data_key data_k = {}; 103 | struct data_value *data_v = make_event_1(); 104 | if(!data_v) return 0; 105 | 106 | s32 len, record_type; 107 | const char *str; 108 | void *len_ptr; 109 | 110 | void *record_type_ptr; 111 | record_type_ptr = (void *)go_get_argument_by_stack(ctx,2); 112 | 113 | bpf_probe_read_kernel(&record_type, sizeof(record_type), (void*)&record_type_ptr); 114 | 115 | if (record_type != recordTypeApplicationData){ 116 | return 0; 117 | } 118 | 119 | 120 | u64 pid_tgid = bpf_get_current_pid_tgid(); 121 | u32 pid = pid_tgid >> 32; 122 | u32 tid = (u32)pid_tgid; 123 | u32 uid = bpf_get_current_uid_gid(); 124 | 125 | data_k.pid = pid; 126 | data_k.tid = tid; 127 | data_k.uid = uid; 128 | bpf_get_current_comm(&data_k.comm, sizeof(data_k.comm)); 129 | 130 | 131 | str = (void *)go_get_argument_by_stack(ctx,3); 132 | len_ptr = (void *)go_get_argument_by_stack(ctx,4); 133 | bpf_probe_read_kernel(&len, sizeof(len), (void*)&len_ptr); 134 | 135 | data_v->len = len; 136 | 137 | bpf_probe_read_user(&data_v->buf,sizeof(data_v->buf),(void *)str); 138 | 139 | https_data.update(&data_k, data_v); 140 | 141 | return 0; 142 | 143 | } 144 | -------------------------------------------------------------------------------- /http/http.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define IP_TCP 6 8 | #define ETH_HLEN 14 9 | 10 | struct data_key { 11 | u32 src_ip; 12 | u32 dst_ip; 13 | unsigned short src_port; 14 | unsigned short dst_port; 15 | }; 16 | 17 | struct data_value { 18 | u32 pid; 19 | u32 uid; 20 | u32 gid; 21 | char comm[64]; 22 | }; 23 | 24 | struct Leaf { 25 | int timestamp; //timestamp in ns 26 | }; 27 | 28 | 29 | BPF_TABLE("extern", struct data_key, struct data_value, proc_http_datas, 20480); 30 | // Table for transferring data to the user space: 31 | 32 | BPF_HASH(sessions, struct data_key, struct Leaf, 1024); 33 | 34 | BPF_PERF_OUTPUT(events_http); 35 | 36 | int http_matching(struct __sk_buff *skb){ 37 | u8 *cursor = 0; 38 | u32 tcp_header_length = 0; 39 | u32 ip_header_length = 0; 40 | u32 payload_offset = 0; 41 | u32 payload_length = 0; 42 | 43 | 44 | struct ethernet_t *ethernet = cursor_advance(cursor,sizeof(*ethernet)); 45 | 46 | if (!(ethernet->type == 0x0800)) { 47 | return 0; 48 | } 49 | struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); 50 | struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp)); 51 | 52 | if (ip->nextp != IP_TCP) { 53 | return 0; 54 | } 55 | 56 | if (!tcp->flag_psh) { 57 | return 0; 58 | } 59 | 60 | struct data_key key = {}; 61 | struct data_key session_key = {}; 62 | struct Leaf zero = {0}; 63 | 64 | ip_header_length = ip->hlen << 2; 65 | tcp_header_length = tcp->offset << 2; //SHL 2 -> *4 multiply 66 | 67 | payload_offset = ETH_HLEN + ip_header_length + tcp_header_length; 68 | payload_length = ip->tlen - ip_header_length - tcp_header_length; 69 | 70 | key.src_ip = ip->src; 71 | key.dst_ip = ip->dst; 72 | key.src_port = tcp->src_port; 73 | key.dst_port = tcp->dst_port; 74 | 75 | 76 | session_key.src_ip = ip->src; 77 | session_key.dst_ip = ip->dst; 78 | session_key.src_port = tcp->src_port; 79 | session_key.dst_port = tcp->dst_port; 80 | 81 | 82 | struct data_value *value; 83 | value = proc_http_datas.lookup(&key); 84 | 85 | if (!value){ 86 | return 0; 87 | } 88 | 89 | unsigned long payload[7]; 90 | int i = 0; 91 | for (i = 0; i < 7; i++) { 92 | payload[i] = load_byte(skb, payload_offset + i); 93 | } 94 | 95 | if((payload[0]=='H') && (payload[1]=='T') && (payload[2]=='T') && (payload[3]=='P')){ 96 | goto SESSION_MATCH; 97 | } 98 | 99 | if((payload[0]=='G') && (payload[1]=='E') && (payload[2]=='T')){ 100 | goto SESSION_MATCH; 101 | } 102 | 103 | if((payload[0]=='P') && (payload[1]=='O') && (payload[2]=='S') && (payload[3]=='T')){ 104 | goto SESSION_MATCH; 105 | } 106 | 107 | if((payload[0]=='P') && (payload[1]=='U') && (payload[2]=='T')){ 108 | goto SESSION_MATCH; 109 | } 110 | 111 | if((payload[0]=='H') && (payload[1]=='E') && (payload[2]=='A') && (payload[3]=='D')){ 112 | goto SESSION_MATCH; 113 | } 114 | 115 | if((payload[0]=='D') && (payload[1]=='E') && (payload[2]=='L') && (payload[3]=='E') && (payload[4]=='T') && (payload[5]=='E')){ 116 | goto SESSION_MATCH; 117 | } 118 | 119 | struct Leaf * lookup_leaf = sessions.lookup(&session_key); 120 | if(lookup_leaf) { 121 | //send packet to userspace 122 | goto KEEP; 123 | } 124 | goto DROP; 125 | 126 | SESSION_MATCH: 127 | sessions.lookup_or_try_init(&session_key,&zero); 128 | 129 | //send packet to userspace returning -1 130 | KEEP: 131 | events_http.perf_submit_skb(skb,skb->len,value,sizeof(struct data_value)); 132 | proc_http_datas.delete(&key); 133 | return 0; 134 | 135 | //drop the packet returning 0 136 | DROP: 137 | return 0; 138 | 139 | } 140 | -------------------------------------------------------------------------------- /http/kprobe_http.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define IP_TCP 6 4 | #define ETH_HLEN 14 5 | 6 | struct data_key { 7 | u32 src_ip; 8 | u32 dst_ip; 9 | unsigned short src_port; 10 | unsigned short dst_port; 11 | }; 12 | 13 | struct data_value { 14 | u32 pid; 15 | u32 uid; 16 | u32 gid; 17 | char comm[64]; 18 | }; 19 | 20 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, proc_http_datas, 20480); 21 | 22 | int trace_tcp_sendmsg(struct pt_regs *ctx, struct sock *sk) { 23 | u16 sport = sk->sk_num; 24 | u16 dport = sk->sk_dport; 25 | 26 | u32 saddr = sk->sk_rcv_saddr; 27 | u32 daddr = sk->sk_daddr; 28 | u64 pid_tgid = bpf_get_current_pid_tgid(); 29 | u64 uid_gid = bpf_get_current_uid_gid(); 30 | 31 | struct data_key key = {}; 32 | key.src_ip = htonl(saddr); 33 | key.dst_ip = htonl(daddr); 34 | key.src_port = sport; 35 | key.dst_port = htons(dport); 36 | 37 | struct data_value value = {}; 38 | value.pid = pid_tgid >> 32; 39 | value.uid = (u32)uid_gid; 40 | value.gid = uid_gid >> 32; 41 | bpf_get_current_comm(value.comm, 64); 42 | 43 | proc_http_datas.update(&key, &value); 44 | 45 | return 0; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /https/https_py_tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_BUFFER_SIZE 4000 7 | 8 | struct data_key { 9 | u32 pid; 10 | u32 tid; 11 | u32 uid; 12 | char comm[TASK_COMM_LEN]; 13 | }; 14 | 15 | struct data_value { 16 | char buf[MAX_BUFFER_SIZE]; 17 | }; 18 | 19 | struct https_data { 20 | u32 pid; 21 | u32 uid; 22 | u32 saddr; 23 | u32 daddr; 24 | u16 sport; 25 | u16 dport; 26 | char buf[MAX_BUFFER_SIZE]; 27 | }; 28 | 29 | struct session_key { 30 | u32 saddr; 31 | u32 daddr; 32 | u16 sport; 33 | u16 dport; 34 | }; 35 | 36 | 37 | struct Leaf { 38 | int timestamp; //timestamp in ns 39 | }; 40 | 41 | 42 | BPF_TABLE_PUBLIC("extern", struct data_key, struct data_value, https_data, 4096); 43 | BPF_HASH(sessions, struct session_key, struct Leaf, 1024); 44 | 45 | /*bypass 512 limit*/ 46 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 47 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 48 | 49 | BPF_HASH(bpf_context_2, u64, struct https_data, 2048); 50 | BPF_ARRAY(bpf_context_gen_2, struct https_data, 1); 51 | 52 | static struct data_value *make_event_1(){ 53 | int zero = 0; 54 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 55 | if (!bpf_ctx) return 0; 56 | u64 id = bpf_get_current_pid_tgid(); 57 | bpf_context_1.update(&id, bpf_ctx); 58 | return bpf_context_1.lookup(&id); 59 | } 60 | 61 | static struct https_data *make_event_2(){ 62 | int zero = 0; 63 | struct https_data *bpf_ctx = bpf_context_gen_2.lookup(&zero); 64 | if (!bpf_ctx) return 0; 65 | u64 id = bpf_get_current_pid_tgid(); 66 | bpf_context_2.update(&id, bpf_ctx); 67 | return bpf_context_2.lookup(&id); 68 | } 69 | 70 | 71 | BPF_PERF_OUTPUT(events_py_https); 72 | 73 | int trace_py_tcp_sendmsg(struct pt_regs *ctx, struct sock *sk) 74 | { 75 | 76 | u16 sport = sk->sk_num; 77 | u16 dport = sk->sk_dport; 78 | u32 saddr = sk->sk_rcv_saddr; 79 | u32 daddr = sk->sk_daddr; 80 | 81 | u64 pid_tgid = bpf_get_current_pid_tgid(); 82 | u32 pid = pid_tgid >> 32; 83 | u32 tid = (u32)pid_tgid; 84 | u32 uid = bpf_get_current_uid_gid(); 85 | 86 | 87 | struct session_key session_key = {}; 88 | session_key.saddr = htonl(saddr); 89 | session_key.daddr = htonl(daddr); 90 | session_key.sport = sport; 91 | session_key.dport = htons(dport); 92 | 93 | 94 | struct https_data *data = make_event_2(); 95 | if(!data) return 0; 96 | 97 | data->saddr = htonl(saddr); 98 | data->daddr = htonl(daddr); 99 | data->sport = sport; 100 | data->dport = htons(dport); 101 | data->pid = pid; 102 | data->uid = uid; 103 | 104 | struct data_key key = {}; 105 | key.pid = pid; 106 | key.tid = tid; 107 | key.uid = uid; 108 | bpf_get_current_comm(&key.comm, sizeof(key.comm)); 109 | 110 | struct data_value *value = make_event_1(); 111 | if(!value) return 0; 112 | 113 | value = https_data.lookup(&key); 114 | if (!value){ 115 | return 0; 116 | } 117 | 118 | bpf_probe_read(&(data->buf), MAX_BUFFER_SIZE, (char *)(value->buf)); 119 | 120 | struct Leaf zero = {0}; 121 | 122 | sessions.lookup_or_try_init(&session_key,&zero); 123 | struct Leaf * lookup_leaf = sessions.lookup(&session_key); 124 | if(lookup_leaf) { 125 | 126 | events_py_https.perf_submit(ctx, data, sizeof(struct https_data)); 127 | https_data.delete(&key); 128 | return 0; 129 | } 130 | 131 | https_data.delete(&key); 132 | return 0; 133 | 134 | } 135 | 136 | 137 | -------------------------------------------------------------------------------- /https/original_https.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_BUF_SIZE 4000 7 | 8 | 9 | struct data_key { 10 | u32 pid; 11 | u32 tid; 12 | u32 uid; 13 | char comm[TASK_COMM_LEN]; 14 | }; 15 | 16 | struct data_value { 17 | u32 len; 18 | int buf_filled; 19 | u8 buf[MAX_BUF_SIZE]; 20 | }; 21 | 22 | struct https_data { 23 | u32 pid; 24 | //u32 tid; 25 | u32 uid; 26 | //char comm[TASK_COMM_LEN]; 27 | u32 saddr; 28 | u32 daddr; 29 | u16 sport; 30 | u16 dport; 31 | u32 len; 32 | int buf_filled; 33 | u8 buf[MAX_BUF_SIZE]; 34 | }; 35 | 36 | struct session_key { 37 | u32 src_ip; 38 | u32 dst_ip; 39 | unsigned short src_port; 40 | unsigned short dst_port; 41 | }; 42 | 43 | struct Leaf { 44 | int timestamp; //timestamp in ns 45 | }; 46 | 47 | 48 | BPF_TABLE_PUBLIC("extern", struct data_key, struct data_value, https_data, 4096); 49 | BPF_HASH(sessions, struct session_key, struct Leaf, 1024); 50 | 51 | /*bypass 512 limit*/ 52 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 53 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 54 | 55 | BPF_HASH(bpf_context_2, u64, struct https_data, 2048); 56 | BPF_ARRAY(bpf_context_gen_2, struct https_data, 1); 57 | 58 | static struct data_value *make_event_1(){ 59 | int zero = 0; 60 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 61 | if (!bpf_ctx) return 0; 62 | u64 id = bpf_get_current_pid_tgid(); 63 | bpf_context_1.update(&id, bpf_ctx); 64 | return bpf_context_1.lookup(&id); 65 | } 66 | 67 | static struct https_data *make_event_2(){ 68 | int zero = 0; 69 | struct https_data *bpf_ctx = bpf_context_gen_2.lookup(&zero); 70 | if (!bpf_ctx) return 0; 71 | u64 id = bpf_get_current_pid_tgid(); 72 | bpf_context_2.update(&id, bpf_ctx); 73 | return bpf_context_2.lookup(&id); 74 | } 75 | 76 | BPF_PERF_OUTPUT(events_https); 77 | 78 | int trace_tcp_sendmsg(struct pt_regs *ctx, struct sock *sk) 79 | { 80 | 81 | u16 sport = sk->sk_num; 82 | u16 dport = sk->sk_dport; 83 | u32 saddr = sk->sk_rcv_saddr; 84 | u32 daddr = sk->sk_daddr; 85 | int ret; 86 | u64 pid_tgid = bpf_get_current_pid_tgid(); 87 | u32 pid = pid_tgid >> 32; 88 | u32 tid = (u32)pid_tgid; 89 | u32 uid = bpf_get_current_uid_gid(); 90 | 91 | struct https_data *data = make_event_2(); 92 | if(!data) return 0; 93 | 94 | data->saddr = htonl(saddr); 95 | data->daddr = htonl(daddr); 96 | data->sport = sport; 97 | data->dport = htons(dport); 98 | data->pid = pid; 99 | // data.tid = tid; 100 | data->uid = uid; 101 | // bpf_get_current_comm(&data.comm, sizeof(data.comm)); 102 | 103 | struct data_key key = {}; 104 | key.pid = pid; 105 | key.tid = tid; 106 | key.uid = uid; 107 | bpf_get_current_comm(&key.comm, sizeof(key.comm)); 108 | 109 | struct session_key session_key = {}; 110 | session_key.src_ip = htonl(saddr); 111 | session_key.dst_ip = htonl(daddr); 112 | session_key.src_port = sport; 113 | session_key.dst_port = htons(dport); 114 | 115 | 116 | 117 | struct data_value *value = make_event_1(); 118 | if(!value) return 0; 119 | 120 | value = https_data.lookup(&key); 121 | if(!value) return 0; 122 | 123 | int len = PT_REGS_RC(ctx); 124 | data->len = value->len; 125 | data->buf_filled = value->buf_filled; 126 | u32 buf_copy_size = min((size_t)MAX_BUF_SIZE, (size_t)len); 127 | ret = bpf_probe_read(&(data->buf), buf_copy_size, (char *)(value->buf)); 128 | 129 | 130 | struct Leaf zero = {0}; 131 | sessions.lookup_or_try_init(&session_key,&zero); 132 | struct Leaf * lookup_leaf = sessions.lookup(&session_key); 133 | if(lookup_leaf) { 134 | //send packet to userspace 135 | events_https.perf_submit(ctx, data, sizeof(struct https_data)); 136 | https_data.delete(&key); 137 | return 0; 138 | } 139 | 140 | https_data.delete(&key); 141 | return 0; 142 | } 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /https/uprobe_py_ssl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_BUFFER_SIZE 4000 5 | 6 | struct data_key { 7 | u32 pid; 8 | u32 tid; 9 | u32 uid; 10 | char comm[TASK_COMM_LEN]; 11 | }; 12 | 13 | struct data_value { 14 | char buf[MAX_BUFFER_SIZE]; 15 | }; 16 | 17 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 18 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 19 | 20 | 21 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, https_data, 4096); 22 | 23 | static struct data_value *make_event_1(){ 24 | int zero = 0; 25 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 26 | if (!bpf_ctx) return 0; 27 | u64 id = bpf_get_current_pid_tgid(); 28 | bpf_context_1.update(&id, bpf_ctx); 29 | return bpf_context_1.lookup(&id); 30 | } 31 | 32 | 33 | int probe_SSL_rw_ex_enter(struct pt_regs *ctx,int *s, const void *buf) { 34 | 35 | struct data_key data_k = {}; 36 | struct data_value *data_v = make_event_1(); 37 | if(!data_v) return 0; 38 | 39 | u64 pid_tgid = bpf_get_current_pid_tgid(); 40 | u32 pid = pid_tgid >> 32; 41 | u32 tid = (u32)pid_tgid; 42 | 43 | data_k.pid = pid; 44 | data_k.tid = tid; 45 | data_k.uid = bpf_get_current_uid_gid(); 46 | bpf_get_current_comm(&data_k.comm, sizeof(data_k.comm)); 47 | 48 | bpf_probe_read_user(&data_v->buf, sizeof(data_v->buf), buf); 49 | 50 | https_data.update(&data_k, data_v); 51 | 52 | return 0; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /https/uprobe_ssl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* For TASK_COMM_LEN */ 3 | 4 | #define MAX_BUF_SIZE 4000 5 | 6 | struct data_key { 7 | u32 pid; 8 | u32 tid; 9 | u32 uid; 10 | char comm[TASK_COMM_LEN]; 11 | }; 12 | 13 | struct data_value { 14 | u32 len; 15 | int buf_filled; 16 | u8 buf[MAX_BUF_SIZE]; 17 | }; 18 | 19 | struct probe_SSL_data_t { 20 | u64 timestamp_ns; 21 | u64 delta_ns; 22 | u32 pid; 23 | u32 tid; 24 | u32 uid; 25 | u32 len; 26 | int buf_filled; 27 | int rw; 28 | char comm[TASK_COMM_LEN]; 29 | u8 buf[MAX_BUF_SIZE]; 30 | }; 31 | 32 | #define BASE_EVENT_SIZE ((size_t)(&((struct probe_SSL_data_t*)0)->buf)) 33 | #define EVENT_SIZE(X) (BASE_EVENT_SIZE + ((size_t)(X))) 34 | 35 | BPF_PERCPU_ARRAY(ssl_data, struct probe_SSL_data_t, 1); 36 | 37 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, https_data, 4096); 38 | 39 | BPF_HASH(start_ns, u32); 40 | BPF_HASH(bufs, u32, u64); 41 | 42 | /*bypass 512 limit*/ 43 | BPF_HASH(bpf_context_1, u64, struct data_value, 2048); 44 | BPF_ARRAY(bpf_context_gen_1, struct data_value, 1); 45 | 46 | BPF_HASH(bpf_context_2, u64, struct probe_SSL_data_t, 2048); 47 | BPF_ARRAY(bpf_context_gen_2, struct probe_SSL_data_t, 1); 48 | 49 | static struct data_value *make_event_1(){ 50 | int zero = 0; 51 | struct data_value *bpf_ctx = bpf_context_gen_1.lookup(&zero); 52 | if (!bpf_ctx) return 0; 53 | u64 id = bpf_get_current_pid_tgid(); 54 | bpf_context_1.update(&id, bpf_ctx); 55 | return bpf_context_1.lookup(&id); 56 | } 57 | 58 | static struct probe_SSL_data_t *make_event_2(){ 59 | int zero = 0; 60 | struct probe_SSL_data_t *bpf_ctx = bpf_context_gen_2.lookup(&zero); 61 | if (!bpf_ctx) return 0; 62 | u64 id = bpf_get_current_pid_tgid(); 63 | bpf_context_2.update(&id, bpf_ctx); 64 | return bpf_context_2.lookup(&id); 65 | } 66 | 67 | int probe_SSL_rw_enter(struct pt_regs *ctx, void *ssl, void *buf, int num) { 68 | int ret; 69 | u32 zero = 0; 70 | u64 pid_tgid = bpf_get_current_pid_tgid(); 71 | u32 pid = pid_tgid >> 32; 72 | u32 tid = pid_tgid; 73 | u32 uid = bpf_get_current_uid_gid(); 74 | u64 ts = bpf_ktime_get_ns(); 75 | bufs.update(&tid, (u64*)&buf); 76 | start_ns.update(&tid, &ts); 77 | return 0; 78 | } 79 | 80 | static int SSL_exit(struct pt_regs *ctx, int rw) { 81 | int ret; 82 | u32 zero = 0; 83 | u64 pid_tgid = bpf_get_current_pid_tgid(); 84 | u32 pid = pid_tgid >> 32; 85 | u32 tid = (u32)pid_tgid; 86 | u32 uid = bpf_get_current_uid_gid(); 87 | u64 ts = bpf_ktime_get_ns(); 88 | u64 *bufp = bufs.lookup(&tid); 89 | if (bufp == 0) 90 | return 0; 91 | 92 | u64 *tsp = start_ns.lookup(&tid); 93 | if (tsp == 0) 94 | return 0; 95 | 96 | int len = PT_REGS_RC(ctx); 97 | if (len <= 0) // no data 98 | return 0; 99 | 100 | struct probe_SSL_data_t *data = make_event_2(); 101 | if(!data) return 0; 102 | 103 | data = ssl_data.lookup(&zero); 104 | if (!data) return 0; 105 | 106 | data->timestamp_ns = ts; 107 | data->delta_ns = ts - *tsp; 108 | data->pid = pid; 109 | data->tid = tid; 110 | data->uid = uid; 111 | data->len = (u32)len; 112 | data->buf_filled = 0; 113 | data->rw = rw; 114 | 115 | u32 buf_copy_size = min((size_t)MAX_BUF_SIZE, (size_t)len); 116 | bpf_get_current_comm(&data->comm, sizeof(data->comm)); 117 | if (bufp != 0) 118 | ret = bpf_probe_read_user(&data->buf, buf_copy_size, (char *)*bufp); 119 | bufs.delete(&tid); 120 | start_ns.delete(&tid); 121 | 122 | if (!ret) 123 | data->buf_filled = 1; 124 | else 125 | buf_copy_size = 0; 126 | 127 | struct data_key key = {}; 128 | key.pid = pid; 129 | key.tid = tid; 130 | key.uid = uid; 131 | bpf_get_current_comm(key.comm, sizeof(key.comm)); 132 | 133 | struct data_value *value = make_event_1(); 134 | if(!value) return 0; 135 | 136 | value->len = len; 137 | value->buf_filled = data->buf_filled; 138 | 139 | ret = bpf_probe_read_user(value->buf, buf_copy_size, (char *)*bufp); 140 | 141 | https_data.update(&key, value); 142 | 143 | return 0; 144 | } 145 | 146 | int probe_SSL_read_exit(struct pt_regs *ctx) { 147 | return (SSL_exit(ctx, 0)); 148 | } 149 | 150 | int probe_SSL_write_exit(struct pt_regs *ctx) { 151 | return (SSL_exit(ctx, 1)); 152 | } 153 | 154 | -------------------------------------------------------------------------------- /log/flow.log: -------------------------------------------------------------------------------- 1 | 2023 May 08 07:36:07 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '51974', 'dip': '110.242.68.4', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.81.0\r\nAccept: */*\r\n\r\n', 'pid': 908713, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00-X\x00POST\x00user=admin\x00https://www.baidu.com\x00'} 2 | 2023 May 08 07:47:22 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '57386', 'dip': '110.242.68.4', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.81.0\r\nAccept: */*\r\n\r\n', 'pid': 908955, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00-X\x00POST\x00user=admin\x00https://www.baidu.com\x00'} 3 | 2023 May 08 07:47:30 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '36812', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.81.0\r\nAccept: */*\r\n\r\n', 'pid': 908958, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00-X\x00POST\x00user=admin\x00https://www.baidu.com\x00'} 4 | 2023 May 08 07:48:06 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '46118', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.81.0\r\nAccept: */*\r\n\r\n', 'pid': 909050, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00-X\x00POST\x00user=admin\x00https://www.baidu.com\x00'} 5 | 2023 May 08 07:48:10 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '35506', 'dip': '110.242.68.4', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.81.0\r\nAccept: */*\r\n\r\n', 'pid': 909053, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00-X\x00POST\x00XXXsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbXXX\x00https://www.baidu.com\x00'} 6 | 2023 May 08 07:50:44 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '34906', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 1335\r\n\r\nuser=admindddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'pid': 909114, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 7 | 2023 May 08 07:50:44 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '34912', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'PUT / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 16\r\n\r\nfilename=xxx.php', 'pid': 909114, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 8 | 2023 May 08 07:50:45 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '40168', 'dip': '110.242.68.4', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n', 'pid': 909114, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 9 | 2023 May 08 07:55:12 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '50484', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 1335\r\n\r\nuser=admindddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'pid': 909287, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 10 | 2023 May 08 07:55:12 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '50494', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'PUT / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 16\r\n\r\nfilename=xxx.php', 'pid': 909287, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 11 | 2023 May 08 07:55:12 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '50518', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n', 'pid': 909287, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 12 | 2023 May 08 07:55:57 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '44776', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 1335\r\n\r\nuser=adminddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddXXX', 'pid': 909311, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 13 | 2023 May 08 07:55:57 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '51234', 'dip': '110.242.68.4', 'dport': '443', 'protocal': 'HTTPS', 'request': b'PUT / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 16\r\n\r\nfilename=xxx.php', 'pid': 909311, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 14 | 2023 May 08 07:55:58 ebpf: ebpf_data: {'sip': '10.122.0.17', 'sport': '44796', 'dip': '110.242.68.3', 'dport': '443', 'protocal': 'HTTPS', 'request': b'POST / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: python-requests/2.25.1\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n', 'pid': 909311, 'uid': 0, 'comm': 'python3', 'cmd': 'python3\x00py_https_test.py\x00'} 15 | 2023 Jul 09 00:42:21 ebpf: ebpf_data: {'sip': '198.18.24.171', 'sport': 50744, 'dip': '14.119.104.254', 'dport': 80, 'protocal': 'HTTP', 'request': b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.85.0\r\nAccept: */*\r\n\r\n\x00\x00\x00\x00\x00', 'pid': 295401, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00www.baidu.com\x00'} 16 | 2023 Jul 09 00:43:23 ebpf: ebpf_data: {'sip': '198.18.24.171', 'sport': 56572, 'dip': '14.119.104.189', 'dport': 80, 'protocal': 'HTTP', 'request': b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.85.0\r\nAccept: */*\r\n\r\n\x00\x00\x00\x00\x00', 'pid': 295832, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00www.baidu.com\x00'} 17 | 2023 Jul 09 00:48:29 ebpf: ebpf_data: {'sip': '198.18.24.171', 'sport': 58460, 'dip': '14.119.104.189', 'dport': 80, 'protocal': 'HTTP', 'request': b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.85.0\r\nAccept: */*\r\n\r\n\x00\x00\x00\x00\x00', 'pid': 297816, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00www.baidu.com\x00'} 18 | 2023 Jul 09 00:48:39 ebpf: ebpf_data: {'sip': '198.18.24.171', 'sport': 52264, 'dip': '14.119.104.254', 'dport': 80, 'protocal': 'HTTP', 'request': b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nUser-Agent: curl/7.85.0\r\nAccept: */*\r\n\r\n\x00\x00\x00\x00\x00', 'pid': 297870, 'uid': 0, 'comm': 'curl', 'cmd': 'curl\x00www.baidu.com\x00'} 19 | -------------------------------------------------------------------------------- /mygod.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | import threading 4 | 5 | yellow = '\033[01;33m' 6 | white = '\033[01;37m' 7 | green = '\033[01;32m' 8 | blue = '\033[01;34m' 9 | red = '\033[1;31m' 10 | end = '\033[0m' 11 | 12 | version = 'v0.1.0' 13 | message = white + '{' + red + version + ' #dev' + white + '}' 14 | 15 | Flowgod_banner = f""" 16 | FlowGod is a powerful process-level network flow sniffer tool{blue} 17 | ______ _ _____ _ {blue} 18 | | ____| | / ____| | |{blue} 19 | | |__ | | _____ _| | __ ___ __| |{blue} 20 | | __| | |/ _ \ \ /\ / / | |_ |/ _ \ / _` |{blue} 21 | | | | | (_) \ V V /| |__| | (_) | (_| |{blue} 22 | |_| |_|\___/ \_/\_/ \_____|\___/ \__,_|{message}{green} 23 | 24 | {green}[+] FlowGod supports a variety of common protocols:UDP & TCP & HTTP & HTTPS{end} 25 | {green}[+] Flowgod stores the captured traffic logs at ./log/flow.log {end} 26 | """ 27 | 28 | 29 | parser = argparse.ArgumentParser(description='[*] Please install and deploy the bcc environment before using FlowGod and confirm your libssl path!', 30 | usage='python3 mygod.py [options]\nUse examples:\n\ 31 | python3 mygod.py -h [--help] \n\ 32 | python3 mygod.py -l /lib/x86_64-linux-gnu/libssl.so.3 -i ens33\n\ 33 | python3 mygod.py -i ens33 -p 1234\n\ 34 | python3 mygod.py -i ens33 -f udp http https\n\ 35 | python3 mygod.py -i ens33 -f all\n\ 36 | python3 mygod.py -i ens33 --pyssl\n\ 37 | python3 mygod.py -i ens33 -f dns\n\ 38 | python3 mygod.py -f udp http --gotls /path/to/go_program\n\ 39 | \t\t\t......') 40 | 41 | parser.add_argument('-l', '--libssl' , type=str, dest='libssl_path', default='/lib/x86_64-linux-gnu/libssl.so.3', 42 | help= 'Choose the libssl.so file path, default [/lib/x86_64-linux-gnu/libssl.so.3]') 43 | 44 | parser.add_argument('-i', '--interface', type=str, default='ens3', dest='interface', 45 | help= 'Choose the interface you want to capture, default [ens33]') 46 | 47 | parser.add_argument('-p','--pid', type=str, default='all', dest='pid', 48 | help= 'Choose the pid you want to capture, default [all]') 49 | 50 | parser.add_argument('-f','--protocol', nargs='*', choices=['udp','http','https','all','dns'], action='append', dest='protocal', required=True, 51 | help= 'Choose the protocals you want to capture') 52 | 53 | parser.add_argument('--pyssl', action="store_true", dest='pyssl', 54 | help= 'Choose if you want to capture HTTPS request from python programs') 55 | 56 | parser.add_argument('--gotls', type=str, dest='go_program_path', default='None', 57 | help= 'Choose if you want to capture HTTPS request from the specified go program') 58 | 59 | #获得传入的参数 60 | args = parser.parse_args() 61 | 62 | print(Flowgod_banner) 63 | 64 | sys.path.append('./utils/') 65 | from tools import * 66 | 67 | global_arg = Global(args.libssl_path, args.interface, args.pid, args.go_program_path) 68 | 69 | print("[*] FlowGod is starting ...") 70 | print("[*] FlowGod will work with the following parameters:") 71 | print(f"{green}[+] Libssl_path: " + str(global_arg.libssl_path)) 72 | print(f"{green}[+] Interface: " + str(global_arg.interface)) 73 | print(f"{green}[+] Process: [pid] " + str(global_arg.pid)) 74 | print(f"{green}[+] protocal: " + str(args.protocal[0])) 75 | print(f"{green}[+] pyssl: " + str(args.pyssl)) 76 | print(f"{green}[+] gotls: " + str(global_arg.go_program_path)) 77 | 78 | 79 | sys.path.append('./user/') 80 | import user_go_https, user_http, user_https, user_py_https, user_udp, user_dns 81 | 82 | 83 | protocal_dict = {'udp':user_udp, 84 | 'http':user_http, 85 | 'https':user_https, 86 | 'pyhttps':user_py_https, 87 | 'gohttps':user_go_https, 88 | 'dns':user_dns, 89 | } 90 | 91 | 92 | 93 | if args.pyssl and args.go_program_path != 'None': 94 | print("[!] FlowGod does not support the composite form of HTTPS capture !") 95 | print(" Such as: python3 mygod.py -f https --pyssl ") 96 | print(" python3 mygod.py -f https --gotls /path/to/go_program ") 97 | print(" python3 mygod.py --pyssl --gotls /path/to/go_program ") 98 | 99 | else: 100 | 101 | if 'all' in args.protocal[0]: 102 | 103 | if args.pyssl or args.go_program_path != 'None': 104 | 105 | print("[!] FlowGod does not support the composite form of HTTPS capture !") 106 | print(" Such as: python3 mygod.py -f https --pyssl ") 107 | print(" python3 mygod.py -f https --gotls /path/to/go_program ") 108 | print(" python3 mygod.py --gotls /path/to/go_program ") 109 | 110 | else: 111 | print("[|] Wait for loading eBPF hooks...") 112 | 113 | udp = protocal_dict['udp'].init(global_arg) 114 | http = protocal_dict['http'].init(global_arg) 115 | https = protocal_dict['https'].init(global_arg) 116 | dns = protocal_dict['dns'].init(global_arg) 117 | 118 | print("--------------------------------------Start------------------------------------") 119 | 120 | threads = [] 121 | 122 | t1 = threading.Thread(target=user_udp.run, kwargs={"udp": udp}) 123 | t2 = threading.Thread(target=user_http.run, kwargs={"http": http}) 124 | t3 = threading.Thread(target=user_https.run, kwargs={"https": https}) 125 | t4 = threading.Thread(target=user_dns.run, kwargs={"dns": dns}) 126 | 127 | threads.append(t1) 128 | threads.append(t2) 129 | threads.append(t3) 130 | threads.append(t4) 131 | 132 | for i in range(4): 133 | threads[i].start() 134 | 135 | for i in range(4): 136 | threads[i].join() 137 | 138 | else: 139 | 140 | if ('https' in args.protocal[0] and args.pyssl) or \ 141 | ('https' in args.protocal[0] and args.go_program_path != 'None'): 142 | print("[!] FlowGod does not support the composite form of HTTPS capture !") 143 | print(" Such as: python3 mygod.py -f https --pyssl ") 144 | print(" python3 mygod.py -f https --gotls /path/to/go_program ") 145 | print(" python3 mygod.py --gotls /path/to/go_program ") 146 | 147 | else: 148 | 149 | if args.pyssl: # python + ex_https 150 | var = locals() 151 | 152 | threads = [] 153 | threads_len = len(args.protocal[0]) + 1 154 | 155 | print("[|] Wait for loading eBPF hooks...") 156 | 157 | for protocal in args.protocal[0]: 158 | protocal_str = protocal 159 | var[protocal] = protocal_dict[protocal].init(global_arg) 160 | var[protocal_str] = threading.Thread(target=protocal_dict[protocal].run, kwargs={protocal_str: var[protocal]}) 161 | 162 | threads.append(var[protocal_str]) 163 | 164 | pyhttps = protocal_dict['pyhttps'].init(global_arg) 165 | th_py = threading.Thread(target=user_py_https.run, kwargs={'pyhttps': pyhttps}) 166 | threads.append(th_py) 167 | 168 | for i in range(threads_len): 169 | threads[i].start() 170 | 171 | print("--------------------------------------Start------------------------------------") 172 | 173 | for i in range(threads_len): 174 | threads[i].join() 175 | 176 | 177 | elif args.go_program_path != 'None': # go + ex_https 178 | var = locals() 179 | 180 | threads = [] 181 | threads_len = len(args.protocal[0]) + 1 182 | 183 | print("[|] Wait for loading eBPF hooks...") 184 | 185 | for protocal in args.protocal[0]: 186 | protocal_str = protocal 187 | var[protocal] = protocal_dict[protocal].init(global_arg) 188 | var[protocal_str] = threading.Thread(target=protocal_dict[protocal].run, kwargs={protocal_str: var[protocal]}) 189 | 190 | threads.append(var[protocal_str]) 191 | 192 | gohttps = protocal_dict['gohttps'].init(global_arg) 193 | th_go = threading.Thread(target=user_go_https.run, kwargs={'gohttps': gohttps}) 194 | threads.append(th_go) 195 | 196 | for i in range(threads_len): 197 | threads[i].start() 198 | 199 | print("--------------------------------------Start------------------------------------") 200 | 201 | for i in range(threads_len): 202 | threads[i].join() 203 | 204 | 205 | else: 206 | var = locals() 207 | 208 | threads = [] 209 | threads_len = len(args.protocal[0]) 210 | 211 | print("[|] Wait for loading eBPF hooks...") 212 | 213 | for protocal in args.protocal[0]: 214 | protocal_str = protocal 215 | var[protocal] = protocal_dict[protocal].init(global_arg) 216 | var[protocal_str] = threading.Thread(target=protocal_dict[protocal].run, kwargs={protocal_str: var[protocal]}) 217 | 218 | threads.append(var[protocal_str]) 219 | 220 | for i in range(threads_len): 221 | threads[i].start() 222 | 223 | print("--------------------------------------Start------------------------------------") 224 | 225 | for i in range(threads_len): 226 | threads[i].join() 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | bcc 2 | datetime 3 | dnslib 4 | -------------------------------------------------------------------------------- /tcp/tcp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define IP_TCP 6 8 | #define ETH_HLEN 14 9 | 10 | struct data_key { 11 | u8 proto; 12 | u32 saddr; 13 | u32 daddr; 14 | u16 sport; 15 | u16 dport; 16 | }; 17 | 18 | struct data_value { 19 | u32 nic; 20 | u32 pid; 21 | u32 uid; 22 | u32 gid; 23 | char comm[64]; 24 | }; 25 | 26 | BPF_TABLE("extern", struct data_key, struct data_value, proc_datas, 20480); 27 | 28 | BPF_PERF_OUTPUT(events_tcp); 29 | 30 | int tcp_matching(struct __sk_buff *skb){ 31 | u8 *cursor = 0; 32 | struct ethernet_t *ethernet = cursor_advance(cursor,sizeof(*ethernet)); 33 | if(ethernet->type == 0x0800){ //type保存了二层协议类型,ETH_P_IP、ETH_P_ARP,ETH_P_ALL 34 | struct ip_t *ip = cursor_advance(cursor,sizeof(*ip)); 35 | if(ip->nextp == IP_TCP){ //IP_TCP(0x06)、IPPROTO_UDP 36 | struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp)); 37 | 38 | if (!tcp->flag_psh) { //过滤掉不携带数据的包 39 | return 0; 40 | } 41 | struct data_key key = {}; 42 | 43 | key.proto = 6; 44 | key.saddr = ip->src; 45 | key.daddr = ip->dst; 46 | key.sport = tcp->src_port; 47 | key.dport = tcp->dst_port; 48 | 49 | struct data_value *value; 50 | value = proc_datas.lookup(&key); 51 | 52 | if (!value){ 53 | return 0; 54 | } 55 | 56 | value->nic = skb->ifindex; 57 | events_tcp.perf_submit_skb(skb,skb->len,value,sizeof(struct data_value)); 58 | return 0; 59 | } 60 | } 61 | return 0; 62 | } 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /test/test_gohttps.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | sys.path.append('./utils/') 5 | import tools 6 | 7 | global_arg = tools.Global("all","ens3","all","/root/go/src/hello/hello_1.20.2") 8 | 9 | sys.path.append('./user/') 10 | import user_go_https 11 | 12 | gohttps = user_go_https.init(global_arg) 13 | user_go_https.run(gohttps) 14 | -------------------------------------------------------------------------------- /test/test_http.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append('./user/') 4 | sys.path.append('./utils/') 5 | import user_http 6 | 7 | global_arg = user_http.Global("all","ens3") 8 | print(1) 9 | user_http.run(global_arg) 10 | -------------------------------------------------------------------------------- /test/test_https.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append('./user/') 4 | sys.path.append('./utils/') 5 | import user_https 6 | 7 | global_arg = user_https.Global("all","ens3","/lib/x86_64-linux-gnu/libssl.so.3") 8 | 9 | user_https.run(global_arg) 10 | -------------------------------------------------------------------------------- /test/test_pyhttps.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append('./user/') 4 | sys.path.append('./utils/') 5 | import user_py_https 6 | 7 | global_arg = user_py_https.Global("all","ens3") 8 | 9 | user_py_https.run(global_arg) 10 | -------------------------------------------------------------------------------- /test/test_udp.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append('./user/') 4 | sys.path.append('./utils/') 5 | import user_udp 6 | 7 | global_arg = user_udp.Global("all","ens3") 8 | 9 | user_udp.run(global_arg) 10 | 11 | 12 | -------------------------------------------------------------------------------- /udp/kprobe_udp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define IP_TCP 6 4 | #define ETH_HLEN 14 5 | 6 | struct data_key { 7 | u8 proto; 8 | u32 saddr; 9 | u32 daddr; 10 | u16 sport; 11 | u16 dport; 12 | }; 13 | 14 | struct data_value { 15 | u32 pid; 16 | u32 uid; 17 | u32 gid; 18 | char comm[64]; 19 | }; 20 | 21 | BPF_TABLE_PUBLIC("hash", struct data_key, struct data_value, proc_udp_datas, 20480); 22 | 23 | int trace_udp_sendmsg(struct pt_regs *ctx, struct sock *sk) { 24 | u16 sport = sk->sk_num; 25 | u16 dport = sk->sk_dport; 26 | 27 | u32 saddr = sk->sk_rcv_saddr; 28 | u32 daddr = sk->sk_daddr; 29 | u64 pid_tgid = bpf_get_current_pid_tgid(); 30 | u64 uid_gid = bpf_get_current_uid_gid(); 31 | // Forming the key structure. 32 | // These strange transformations will be explained below. 33 | struct data_key key = {.proto = 17}; 34 | key.saddr = htonl(saddr); 35 | key.daddr = htonl(daddr); 36 | key.sport = sport; 37 | key.dport = htons(dport); 38 | // Forming a structure with the process properties: 39 | struct data_value value = {}; 40 | value.pid = pid_tgid >> 32; 41 | value.uid = (u32)uid_gid; 42 | value.gid = uid_gid >> 32; 43 | bpf_get_current_comm(value.comm, 64); 44 | //Writing the value into the eBPF table: 45 | proc_udp_datas.update(&key, &value); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /udp/udp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define IP_TCP 6 8 | #define ETH_HLEN 14 9 | 10 | struct data_key { 11 | u8 proto; 12 | u32 saddr; 13 | u32 daddr; 14 | u16 sport; 15 | u16 dport; 16 | }; 17 | 18 | struct data_value { 19 | u32 pid; 20 | u32 uid; 21 | u32 gid; 22 | char comm[64]; 23 | }; 24 | 25 | BPF_TABLE("extern", struct data_key, struct data_value, proc_udp_datas, 20480); 26 | 27 | BPF_PERF_OUTPUT(events_udp); 28 | 29 | int udp_matching(struct __sk_buff *skb){ 30 | u8 *cursor = 0; 31 | struct ethernet_t *ethernet = cursor_advance(cursor,sizeof(*ethernet)); 32 | if(ethernet->type == 0x0800){ //type保存了二层协议类型,ETH_P_IP、ETH_P_ARP,ETH_P_ALL 33 | struct ip_t *ip = cursor_advance(cursor,sizeof(*ip)); 34 | if(ip->nextp == IPPROTO_UDP){ //IP_TCP(0x06)、IPPROTO_UDP 35 | struct udp_t *udp = cursor_advance(cursor, sizeof(*udp)); 36 | struct data_key key = {}; 37 | key.proto = 17; 38 | 39 | key.saddr = ip->src; 40 | key.daddr = ip->dst; 41 | key.sport = udp->sport; 42 | key.dport = udp->dport; 43 | 44 | struct data_value *value; 45 | value = proc_udp_datas.lookup(&key); 46 | 47 | if (!value){ 48 | return 0; 49 | } 50 | 51 | 52 | events_udp.perf_submit_skb(skb,skb->len,value,sizeof(struct data_value)); 53 | return 0; 54 | } 55 | } 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /user/__pycache__/h.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/h.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_dns.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_dns.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_go_https.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_go_https.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_http.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_http.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_https.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_https.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_py_https.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_py_https.cpython-310.pyc -------------------------------------------------------------------------------- /user/__pycache__/user_udp.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/user/__pycache__/user_udp.cpython-310.pyc -------------------------------------------------------------------------------- /user/user_dns.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import socket 3 | import ctypes as ct 4 | import sys 5 | 6 | 7 | sys.path.append('../utils/') 8 | from tools import * 9 | 10 | pid = None 11 | 12 | 13 | def print_dns(cpu, data, size): 14 | import ctypes as ct 15 | class SkbEvent (ct.Structure): 16 | _fields_ = [ 17 | ("pid", ct.c_uint32), 18 | ("uid", ct.c_uint32), 19 | ("gid", ct.c_uint32), 20 | ("comm", ct.c_char * 64), 21 | ("raw", ct.c_ubyte * (size - ct.sizeof(ct.c_uint32 * 3) - ct.sizeof(ct.c_char * 64))) 22 | ] 23 | # We get our 'port_val' structure and also the packet itself in the 'raw' field: 24 | skb = ct.cast(data, ct.POINTER(SkbEvent)).contents 25 | packet_str = skb.raw[:] 26 | packet_bytearray = bytearray(packet_str) 27 | 28 | ip_header_length = packet_bytearray[ETH_HLEN] # load Byte 29 | ip_header_length = ip_header_length & 0x0F # mask bits 0..3 30 | ip_header_length = ip_header_length << 2 # shift to obtain length 31 | 32 | # calculate packet total length 33 | total_length = packet_bytearray[ETH_HLEN + 2] # load MSB 34 | total_length = total_length << 8 # shift MSB 35 | total_length = total_length + packet_bytearray[ETH_HLEN + 3] # ad+d LSB 36 | 37 | # retrieve ip source/dest 38 | ip_src_str = packet_str[ETH_HLEN + 12: ETH_HLEN + 16] # ip source offset 12..15 39 | ip_dst_str = packet_str[ETH_HLEN + 16:ETH_HLEN + 20] # ip dest offset 16..19 40 | ip_src = int.from_bytes(ip_src_str,"big") 41 | ip_dst = int.from_bytes(ip_dst_str,"big") 42 | port_src_str = packet_str[ETH_HLEN + ip_header_length:ETH_HLEN + ip_header_length + 2] 43 | port_dst_str = packet_str[ETH_HLEN + ip_header_length + 2:ETH_HLEN + ip_header_length + 4] 44 | port_src = int.from_bytes(port_src_str,"big") 45 | port_dst = int.from_bytes(port_dst_str,"big") 46 | 47 | 48 | 49 | udp_header_len = 14 + ip_header_length 50 | udp_packet = bytes(skb.raw[udp_header_len:]) 51 | dns_packet = udp_packet[8:] 52 | 53 | DNS_Q_TYPE = {1: "A", 28: "AAAA"} 54 | 55 | dns_data = dnslib.DNSRecord.parse(dns_packet) 56 | 57 | #print(dns_data) 58 | if dns_data.header.qr == 0: 59 | for q in dns_data.questions: 60 | print("[DNS] 原始数据报处理后提取的五元组信息:") 61 | print(int2ip(ip_src)+"[{}]".format(port_src)+"---->"+int2ip(ip_dst)+"[{}]".format(port_dst)) 62 | print("-------------------------------------------------------------------------------") 63 | print("[DNS] 原始数据报处理后提取的DNS请求信息:") 64 | print("-------------------------------------------------------------------------------") 65 | print("DNS QUESTION SECTION: ") 66 | print(str(q.qname) + "\t" + "IN\t" + DNS_Q_TYPE[q.qtype]) 67 | print("-------------------------------------------------------------------------------") 68 | 69 | try: 70 | with open(f'/proc/{skb.pid}/comm', 'r') as proc_comm: 71 | proc_name = proc_comm.read().rstrip() 72 | with open(f'/proc/{skb.pid}/cmdline', 'r') as proc_cmd: 73 | proc_cmd = proc_cmd.read().rstrip() 74 | except: 75 | proc_name = skb.comm.decode() 76 | proc_cmd = "NULL" 77 | 78 | print("PID\tUID\tCOMM\tCMD") 79 | print("{}\t{}\t{}\t{}".format(skb.pid,skb.uid,proc_name,proc_cmd)) 80 | print("-------------------------------------------------------------------------------") 81 | 82 | 83 | class Global(): 84 | def __init__(self, pid, interface): 85 | self.pid = pid 86 | self.interface = interface 87 | 88 | 89 | class DNS(): 90 | 91 | def __init__(self, global_arg): 92 | 93 | self.bpf_kprobe_dns = BPF(src_file = "./dns/dns_udp_pro.c") 94 | self.bpf_sock_dns = BPF(src_file = "./dns/dns_socket_pro.c") 95 | self.bpf_kprobe_dns.attach_kprobe(event="udp_sendmsg", fn_name="trace_udp_sendmsg") 96 | function_dns_matching = self.bpf_sock_dns.load_func("dns_matching", BPF.SOCKET_FILTER) 97 | BPF.attach_raw_socket(function_dns_matching, global_arg.interface) 98 | socket_fd_dns = function_dns_matching.sock 99 | sock_dns = socket.fromfd(socket_fd_dns,socket.PF_PACKET,socket.SOCK_RAW,socket.IPPROTO_IP) 100 | sock_dns.setblocking(True) 101 | self.bpf_sock_dns["events_dns"].open_perf_buffer(print_dns) 102 | 103 | print("[*] The DNS Hook is ready.") 104 | 105 | def dns_buffer_poll(self): 106 | while True: 107 | try: 108 | self.bpf_sock_dns.perf_buffer_poll() 109 | except KeyboardInterrupt: 110 | exit() 111 | 112 | 113 | 114 | def init(global_arg): 115 | libssl_path = global_arg.libssl_path 116 | interface = global_arg.interface 117 | global pid 118 | pid = global_arg.pid 119 | dns = DNS(global_arg) 120 | return dns 121 | 122 | def run(dns): 123 | dns.dns_buffer_poll() 124 | 125 | 126 | -------------------------------------------------------------------------------- /user/user_go_https.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import sys 3 | 4 | 5 | sys.path.append('../utils/') 6 | from tools import * 7 | 8 | pid = None 9 | go_https_sessions = None 10 | bpf_kprobe_go_https = None 11 | 12 | go_https_packet_count = 0 13 | go_https_packet_dictionary = {} 14 | 15 | 16 | def print_go_https(cpu,data,size): 17 | global bpf_kprobe_go_https 18 | event = bpf_kprobe_go_https["events_go_https"].event(data) 19 | buf_size = event.len 20 | payload_str = bytearray(event.buf[:buf_size]).decode() 21 | payload_bytes_str = bytes(payload_str,encoding='utf-8') 22 | 23 | current_Key = go_https_sessions.Key(event.saddr, event.daddr, event.sport, event.dport) 24 | 25 | if ((payload_bytes_str[:3] == b'GET') or (payload_bytes_str[:4] == b'POST') 26 | or (payload_bytes_str[:4] == b'HTTP') or (payload_bytes_str[:3] == b'PUT') 27 | or (payload_bytes_str[:6] == b'DELETE') or (payload_bytes_str[:4] == b'HEAD')): 28 | if crlf2 in payload_bytes_str: 29 | print("[HTTPS_GO] 原始数据报处理后提取的五元组信息:") 30 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 31 | print("-------------------------------------------------------------------------------") 32 | print("[HTTPS_GO] 原始数据报处理后提取的请求信息:") 33 | printUntilCRLF(payload_str,'str') 34 | print("-------------------------------------------------------------------------------") 35 | 36 | print("PID\tUID\tCOMM\tCMD") 37 | try: 38 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 39 | proc_name = proc_comm.read().rstrip() 40 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 41 | proc_cmd = proc_cmd.read().rstrip() 42 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 43 | print("-------------------------------------------------------------------------------") 44 | except: 45 | proc_name = "NULL" 46 | 47 | try: 48 | log_submit(str(int2ip(event.saddr)),str(event.sport),str(int2ip(event.daddr)),str(event.dport),"HTTPS",payload_str,event.pid,event.uid,proc_name,proc_cmd) 49 | except: 50 | print("Some Exceptions happen during logging.") 51 | 52 | try: 53 | del go_https_sessions[current_Key] 54 | except: 55 | print("error during delete from bpf map ") 56 | 57 | else: 58 | go_https_packet_dictionary[binascii.hexlify(current_Key)] = payload_bytes_str 59 | 60 | else: 61 | if (current_Key in go_https_sessions): 62 | if (binascii.hexlify(current_Key) in go_https_packet_dictionary): 63 | prev_payload_string = go_https_packet_dictionary[binascii.hexlify(current_Key)] 64 | if (crlf2 in payload_bytes_str): 65 | prev_payload_string += payload_bytes_str 66 | print("[*] 原始数据报处理后提取的五元组信息:") 67 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 68 | print("-------------------------------------------------------------------------------") 69 | print("[*] 原始数据报处理后提取的请求信息:") 70 | printUntilCRLF(prev_payload_string.decode(),'str') 71 | print("-------------------------------------------------------------------------------") 72 | 73 | print("PID\tUID\tCOMM\tCMD") 74 | try: 75 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 76 | proc_name = proc_comm.read().rstrip() 77 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 78 | proc_cmd = proc_cmd.read().rstrip() 79 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 80 | print("-------------------------------------------------------------------------------") 81 | except: 82 | proc_name = "NULL" 83 | 84 | try: 85 | log_submit(str(int2ip(event.saddr)),str(event.sport),str(int2ip(event.daddr)),str(event.dport),"HTTPS",payload_str,event.pid,event.uid,proc_name,proc_cmd) 86 | except: 87 | print("Some Exceptions happen during logging.") 88 | 89 | try: 90 | del go_https_sessions[current_Key] 91 | del go_https_packet_dictionary[binascii.hexlify(current_Key)] 92 | 93 | except: 94 | print("error deleting from map or dictionary") 95 | else: 96 | prev_payload_string += payload_bytes_str 97 | if (len(prev_payload_string) > MAX_URL_STRING_LEN): 98 | print("url too long") 99 | try: 100 | del go_https_sessions[current_Key] 101 | del go_https_packet_dictionary[binascii.hexlify(current_Key)] 102 | except: 103 | print("error deleting from map or dict") 104 | go_https_packet_dictionary[binascii.hexlify(current_Key)] = prev_payload_string 105 | else: 106 | try: 107 | del go_https_sessions[current_Key] 108 | except: 109 | print("error del https_session") 110 | 111 | global go_https_packet_count 112 | go_https_packet_count += 1 113 | if (((go_https_packet_count) % CLEANUP_N_PACKETS) == 0): 114 | cleanup(go_https_sessions) 115 | 116 | 117 | 118 | class GOHTTPS(): 119 | 120 | def __init__(self, global_arg): 121 | self.bpf_uprobe_go_ssl = BPF(src_file = "./gotls/uprobe_go_ssl.c") 122 | 123 | if get_go_version(global_arg.go_program_path): 124 | self.bpf_uprobe_go_ssl.attach_uprobe(name=global_arg.go_program_path, sym="crypto/tls.(*Conn).writeRecordLocked", fn_name="go_https_register") 125 | else: 126 | self.bpf_uprobe_go_ssl.attach_uprobe(name=global_arg.go_program_path, sym="crypto/tls.(*Conn).writeRecordLocked", fn_name="go_https_stack") 127 | 128 | self.bpf_kprobe_go_https = BPF(src_file = "./gotls/https_go_tcp.c") 129 | self.bpf_kprobe_go_https.attach_kprobe(event="tcp_sendmsg", fn_name="trace_go_tcp_sendmsg") 130 | 131 | global bpf_kprobe_go_https 132 | bpf_kprobe_go_https = self.bpf_kprobe_go_https 133 | global go_https_sessions 134 | go_https_sessions = bpf_kprobe_go_https.get_table("sessions") 135 | 136 | print("[*] The HTTPS Hook for Go is ready.") 137 | 138 | def go_https_buffer_poll(self): 139 | self.bpf_kprobe_go_https["events_go_https"].open_perf_buffer(print_go_https) 140 | while True: 141 | try: 142 | self.bpf_kprobe_go_https.perf_buffer_poll() 143 | except KeyboardInterrupt: 144 | exit() 145 | 146 | 147 | 148 | def init(global_arg): 149 | libssl_path = global_arg.libssl_path 150 | interface = global_arg.interface 151 | global pid 152 | pid = global_arg.pid 153 | gohttps = GOHTTPS(global_arg) 154 | return gohttps 155 | 156 | def run(gohttps): 157 | gohttps.go_https_buffer_poll() 158 | 159 | -------------------------------------------------------------------------------- /user/user_http.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import socket 3 | import ctypes as ct 4 | import sys 5 | 6 | sys.path.append('../utils/') 7 | from tools import * 8 | 9 | pid = None 10 | http_sessions = None 11 | http_packet_count = 0 12 | http_packet_dictionary = {} 13 | 14 | def print_http(cpu,data,size): 15 | class skbuffer_event(ct.Structure): # 兼容 16 | _fields_ = [ 17 | ("pid", ct.c_uint32), 18 | ("uid", ct.c_uint32), 19 | ("gid", ct.c_uint32), 20 | ("comm", ct.c_char * 64), 21 | ("raw", ct.c_ubyte * (size - ct.sizeof(ct.c_uint32 * 3) - ct.sizeof(ct.c_char * 64))) 22 | ] 23 | skb = ct.cast(data, ct.POINTER(skbuffer_event)).contents 24 | packet_str = skb.raw[:] 25 | global pid 26 | #print(pid,type(pid),skb.pid,type(skb.pid)) 27 | if pid == 'all' or pid == str(skb.pid): 28 | if not is_dns_query(packet_str): # 暂时排除dns请求 29 | packet_bytearray = bytearray(packet_str) 30 | 31 | ip_header_length = packet_bytearray[ETH_HLEN] # load Byte 32 | ip_header_length = ip_header_length & 0x0F # mask bits 0..3 33 | ip_header_length = ip_header_length << 2 # shift to obtain length 34 | 35 | # calculate packet total length 36 | total_length = packet_bytearray[ETH_HLEN + 2] # load MSB 37 | total_length = total_length << 8 # shift MSB 38 | total_length = total_length + packet_bytearray[ETH_HLEN + 3] # add LSB 39 | 40 | # retrieve ip source/dest 41 | ip_src_str = packet_str[ETH_HLEN + 12: ETH_HLEN + 16] # ip source offset 12..15 42 | ip_dst_str = packet_str[ETH_HLEN + 16:ETH_HLEN + 20] # ip dest offset 16..19 43 | ip_src = int.from_bytes(ip_src_str,"big") 44 | ip_dst = int.from_bytes(ip_dst_str,"big") 45 | port_src_str = packet_str[ETH_HLEN + ip_header_length:ETH_HLEN + ip_header_length + 2] 46 | port_dst_str = packet_str[ETH_HLEN + ip_header_length + 2:ETH_HLEN + ip_header_length + 4] 47 | port_src = int.from_bytes(port_src_str,"big") 48 | port_dst = int.from_bytes(port_dst_str,"big") 49 | 50 | tcp_header_length = packet_bytearray[ETH_HLEN + ip_header_length + 12] 51 | tcp_header_length = tcp_header_length & 0xF0 52 | tcp_header_length = tcp_header_length >> 2 53 | 54 | payload_header = ETH_HLEN + ip_header_length + tcp_header_length 55 | try: 56 | payload_str = packet_bytearray[payload_header:(len(packet_bytearray))].decode() 57 | payload_str = bytes(payload_str,encoding='utf8') 58 | except: 59 | pass 60 | 61 | current_Key = http_sessions.Key(ip_src, ip_dst, port_src, port_dst) 62 | 63 | try: 64 | if ((payload_str[:3] == b'GET') or (payload_str[:4] == b'POST') 65 | or (payload_str[:4] == b'HTTP') or (payload_str[:3] == b'PUT') 66 | or (payload_str[:6] == b'DELETE') or (payload_str[:4] == b'HEAD')): 67 | 68 | if (((payload_str[:3] == b'GET' or payload_str[:4] == b'HEAD' or payload_str[:6] == b'DELETE') and (crlf2_0 in payload_str)) 69 | or ((payload_str[:4] == b'POST' or payload_str[:3] == b'PUT') and (crlf2 in payload_str) and (crlf2_0 not in payload_str))): 70 | #print("3333333333333333333333") 71 | # print(payload_str.decode()) 72 | print("[HTTP] 原始数据报处理后提取的五元组信息:") 73 | print(int2ip(ip_src)+"[{}]".format(str(port_src))+"---->"+int2ip(ip_dst)+"[{}]".format(str(port_dst))) 74 | print("-------------------------------------------------------------------------------") 75 | print("[HTTP] 原始数据报处理后提取的请求信息:") 76 | print("-------------------------------------------------------------------------------") 77 | printUntilCRLF(payload_str,'bytestr') 78 | print("-------------------------------------------------------------------------------") 79 | 80 | 81 | print("PID\tUID\tCOMM\tCMD") 82 | with open(f'/proc/{skb.pid}/comm', 'r') as proc_comm: 83 | proc_name = proc_comm.read().rstrip() 84 | with open(f'/proc/{skb.pid}/cmdline', 'r') as proc_cmd: 85 | proc_cmd = proc_cmd.read().rstrip() 86 | print("{}\t{}\t{}\t{}".format(skb.pid,skb.uid,proc_name,proc_cmd)) 87 | print("-------------------------------------------------------------------------------") 88 | 89 | 90 | try: 91 | del http_sessions[current_Key] 92 | except: 93 | print("error during delete from bpf map") 94 | else: 95 | 96 | http_packet_dictionary[binascii.hexlify(current_Key)] = payload_str 97 | else: 98 | 99 | if (current_Key in http_sessions): 100 | 101 | if (binascii.hexlify(current_Key) in http_packet_dictionary): 102 | http_pre_string = http_packet_dictionary[binascii.hexlify(current_Key)] 103 | if (crlf not in payload_str): 104 | payload_str = http_pre_string + payload_str 105 | 106 | print("[*] 原始数据报处理后提取的五元组信息:") 107 | print(int2ip(ip_src)+"[{}]".format(str(port_src))+"---->"+int2ip(ip_dst)+"[{}]".format(str(port_dst))) 108 | print("-------------------------------------------------------------------------------") 109 | print("[*] 原始数据报处理后提取的请求信息:") 110 | print("-------------------------------------------------------------------------------") 111 | printUntilCRLF(payload_str,'bytestr') 112 | print("-------------------------------------------------------------------------------") 113 | 114 | print("PID\tUID\tCOMM\tCMD") 115 | with open(f'/proc/{skb.pid}/comm', 'r') as proc_comm: 116 | proc_name = proc_comm.read().rstrip() 117 | with open(f'/proc/{skb.pid}/cmdline', 'r') as proc_cmd: 118 | proc_cmd = proc_cmd.read().rstrip() 119 | print("{}\t{}\t{}\t{}".format(skb.pid,skb.uid,proc_name,proc_cmd)) 120 | print("-------------------------------------------------------------------------------") 121 | # log_submit(int2ip(ip_src),port_src,int2ip(ip_dst),port_dst,"TCP",skb.pid,skb.uid,proc_name,proc_cmd) 122 | try: 123 | del http_sessions[current_Key] 124 | del http_packet_dictionary[binascii.hexlify(current_Key)] 125 | except: 126 | print("[*] error deleting from map or dictionary") 127 | else: 128 | http_pre_string += payload_str 129 | if (len(http_pre_string) > MAX_URL_STRING_LEN): 130 | print("[*] request too large!") 131 | try: 132 | del http_sessions[current_Key] 133 | del http_packet_dictionary[binascii.hexlify(current_Key)] 134 | except: 135 | print("error deleting from map or dict") 136 | http_packet_dictionary[binascii.hexlify(current_Key)] = http_pre_string 137 | else: 138 | try: 139 | del http_sessions[current_Key] 140 | except: 141 | print("error del http_session") 142 | if (((http_packet_count) % CLEANUP_N_PACKETS) == 0): 143 | cleanup(http_sessions) 144 | except: 145 | proc_name = skb.comm.decode() 146 | try: 147 | log_submit(int2ip(ip_src),port_src,int2ip(ip_dst),port_dst,"HTTP",payload_str,skb.pid,skb.uid,proc_name,proc_cmd) 148 | except: 149 | print("Some Exceptions happen during logging.") 150 | 151 | class HTTP(): 152 | 153 | def __init__(self, global_arg): 154 | 155 | self.bpf_kprobe_http = BPF(src_file = "./http/kprobe_http.c") 156 | self.bpf_sock_http = BPF(src_file = "./http/http.c") 157 | self.bpf_kprobe_http.attach_kprobe(event="tcp_sendmsg", fn_name="trace_tcp_sendmsg") 158 | function_http_matching = self.bpf_sock_http.load_func("http_matching", BPF.SOCKET_FILTER) 159 | BPF.attach_raw_socket(function_http_matching, global_arg.interface) 160 | socket_fd_http = function_http_matching.sock 161 | sock_http = socket.fromfd(socket_fd_http,socket.PF_PACKET, socket.SOCK_RAW,socket.IPPROTO_IP) 162 | sock_http.setblocking(True) 163 | global http_sessions 164 | http_sessions = self.bpf_sock_http.get_table("sessions") 165 | self.bpf_sock_http["events_http"].open_perf_buffer(print_http) 166 | 167 | print("[*] The HTTP Hook is ready.") 168 | 169 | def http_buffer_poll(self): 170 | 171 | while True: 172 | try: 173 | self.bpf_sock_http.perf_buffer_poll() 174 | except KeyboardInterrupt: 175 | exit() 176 | 177 | 178 | def init(global_arg): 179 | libssl_path = global_arg.libssl_path 180 | interface = global_arg.interface 181 | global pid 182 | pid = global_arg.pid 183 | http = HTTP(global_arg) 184 | return http 185 | 186 | def run(http): 187 | http.http_buffer_poll() 188 | 189 | -------------------------------------------------------------------------------- /user/user_https.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import socket 3 | import ctypes as ct 4 | import sys 5 | 6 | sys.path.append('../utils/') 7 | from tools import * 8 | 9 | pid = None 10 | https_sessions = None 11 | bpf_kprobe_https = None 12 | 13 | https_packet_count = 0 14 | https_packet_dictionary = {} 15 | 16 | def print_https(cpu, data, size,): 17 | 18 | event = bpf_kprobe_https["events_https"].event(data) 19 | buf_size = event.len 20 | 21 | global pid 22 | if pid == 'all' or pid == event.pid: 23 | if event.buf_filled == 1: 24 | payload_str = bytearray(event.buf[:buf_size]).decode() 25 | payload_bytes_str = bytes(payload_str,encoding='utf-8') 26 | 27 | current_Key = https_sessions.Key(event.saddr, event.daddr, event.sport, event.dport) 28 | 29 | if ((payload_bytes_str[:3] == b'GET') or (payload_bytes_str[:4] == b'POST') 30 | or (payload_bytes_str[:4] == b'HTTP') or (payload_bytes_str[:3] == b'PUT') 31 | or (payload_bytes_str[:6] == b'DELETE') or (payload_bytes_str[:4] == b'HEAD')): 32 | if crlf in payload_bytes_str: 33 | print("[HTTPS] 原始数据报处理后提取的ip/端口信息:") 34 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 35 | print("-------------------------------------------------------------------------------") 36 | print("[HTTPS] 原始数据报处理后提取的payload信息:") 37 | printUntilCRLF(payload_str,'str') 38 | print("-------------------------------------------------------------------------------") 39 | 40 | try: 41 | del https_sessions[current_Key] 42 | except: 43 | print("error during delete from bpf map ") 44 | else: 45 | https_packet_dictionary[binascii.hexlify(current_Key)] = payload_bytes_str 46 | else: 47 | if (current_Key in https_sessions): 48 | if (binascii.hexlify(current_Key) in https_packet_dictionary): 49 | prev_payload_string = https_packet_dictionary[binascii.hexlify(current_Key)] 50 | if (crlf in payload_bytes_str): 51 | prev_payload_string += payload_bytes_str 52 | print("[*] 原始数据报处理后提取的五元组信息:") 53 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 54 | print("-------------------------------------------------------------------------------") 55 | print("[*] 原始数据报处理后提取的请求信息:") 56 | printUntilCRLF(prev_payload_string.decode(),'str') 57 | print("-------------------------------------------------------------------------------") 58 | 59 | try: 60 | del https_sessions[current_Key] 61 | del https_packet_dictionary[binascii.hexlify(current_Key)] 62 | 63 | except: 64 | print("error deleting from map or dictionary") 65 | else: 66 | prev_payload_string += payload_bytes_str 67 | if (len(prev_payload_string) > MAX_URL_STRING_LEN): 68 | print("url too long") 69 | try: 70 | del https_sessions[current_Key] 71 | del https_packet_dictionary[binascii.hexlify(current_Key)] 72 | except: 73 | print("error deleting from map or dict") 74 | https_packet_dictionary[binascii.hexlify(current_Key)] = prev_payload_string 75 | else: 76 | try: 77 | del https_sessions[current_Key] 78 | except: 79 | print("error del https_session") 80 | global https_packet_count 81 | https_packet_count += 1 82 | #print(https_packet_count) 83 | if (((https_packet_count) % CLEANUP_N_PACKETS) == 0): 84 | cleanup(https_sessions) 85 | 86 | else: 87 | buf_size = 0 88 | buf = b"" 89 | 90 | print("PID\tUID\tCOMM\tCMD") 91 | try: 92 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 93 | proc_name = proc_comm.read().rstrip() 94 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 95 | proc_cmd = proc_cmd.read().rstrip() 96 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 97 | print("-------------------------------------------------------------------------------") 98 | except: 99 | proc_name = "NULL" 100 | try: 101 | log_submit(str(int2ip(event.saddr)),str(event.sport),str(int2ip(event.daddr)),str(event.dport),"HTTPS",payload_bytes_str,event.pid,event.uid,proc_name,proc_cmd) 102 | except: 103 | print("Some Exceptions happen during logging.") 104 | 105 | 106 | class HTTPS(): 107 | 108 | def __init__(self, global_arg): 109 | 110 | self.bpf_uprobe_ssl = BPF(src_file = "./https/uprobe_ssl.c") 111 | self.bpf_uprobe_ssl.attach_uprobe(name=global_arg.libssl_path, sym="SSL_write",fn_name="probe_SSL_rw_enter") 112 | self.bpf_uprobe_ssl.attach_uretprobe(name=global_arg.libssl_path, sym="SSL_write",fn_name="probe_SSL_write_exit") 113 | 114 | self.bpf_kprobe_https = BPF(src_file = "./https/original_https.c") 115 | self.bpf_kprobe_https.attach_kprobe(event="tcp_sendmsg", fn_name="trace_tcp_sendmsg") 116 | global bpf_kprobe_https 117 | bpf_kprobe_https = self.bpf_kprobe_https 118 | global https_sessions 119 | https_sessions = self.bpf_kprobe_https.get_table("sessions") 120 | 121 | print("[*] The HTTPS Hook is ready.") 122 | 123 | def https_buffer_poll(self): 124 | self.bpf_kprobe_https["events_https"].open_perf_buffer(print_https) 125 | while True: 126 | try: 127 | self.bpf_kprobe_https.perf_buffer_poll() 128 | except KeyboardInterrupt: 129 | exit() 130 | 131 | def init(global_arg): 132 | libssl_path = global_arg.libssl_path 133 | interface = global_arg.interface 134 | global pid 135 | pid = global_arg.pid 136 | 137 | https = HTTPS(global_arg) 138 | return https 139 | 140 | 141 | def run(https): 142 | https.https_buffer_poll() 143 | 144 | 145 | -------------------------------------------------------------------------------- /user/user_py_https.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import socket 3 | import ctypes as ct 4 | import sys 5 | 6 | sys.path.append('../utils/') 7 | from tools import * 8 | 9 | pid = None 10 | py_https_sessions = None 11 | bpf_kprobe_py_https = None 12 | 13 | py_https_packet_count = 0 14 | py_https_packet_dictionary = {} 15 | 16 | 17 | def print_py_https(cpu,data,size): 18 | event = bpf_kprobe_py_https["events_py_https"].event(data) 19 | # print("%d\n" % event.num) 20 | current_Key = py_https_sessions.Key(event.saddr, event.daddr, event.sport, event.dport) 21 | #print(event.buf) 22 | #print("[*] 原始数据报处理后提取的ip/端口信息:") 23 | #print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 24 | payload_str = event.buf[:] 25 | # print(payload_str) 26 | if ((payload_str[:3] == b'GET') or (payload_str[:4] == b'HEAD') or (payload_str[:6] == b'DELETE')): 27 | if payload_str[-4:] == crlf2: 28 | print("[HTTPS_PY] 原始数据报处理后提取的五元组信息:") 29 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 30 | print("-------------------------------------------------------------------------------") 31 | print("[HTTPS_PY] 原始数据报处理后提取的请求信息:") 32 | printUntilCRLF(payload_str, 'bytestr') 33 | print("-------------------------------------------------------------------------------") 34 | 35 | print("PID\tUID\tCOMM\tCMD") 36 | try: 37 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 38 | proc_name = proc_comm.read().rstrip() 39 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 40 | proc_cmd = proc_cmd.read().rstrip() 41 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 42 | print("-------------------------------------------------------------------------------") 43 | except: 44 | proc_name = "NULL" 45 | 46 | try: 47 | del py_https_sessions[current_Key] 48 | except: 49 | print("error during delete from bpf map") 50 | else: 51 | py_https_packet_dictionary[binascii.hexlify(current_Key)] = payload_str 52 | 53 | elif ((payload_str[:4] == b'POST') or (payload_str[:3] == b'PUT')): 54 | 55 | if payload_str[-4:] == crlf2: 56 | for header in payload_str.split(b'\r\n'): 57 | if b'Content-Length' in header: 58 | if header.split(b': ')[1] == b'0': 59 | print("[*] 原始数据报处理后提取的ip/端口信息:") 60 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 61 | print("-------------------------------------------------------------------------------") 62 | print("[*] 原始数据报处理后提取的payload信息:") 63 | printUntilCRLF(payload_str,'bytestr') 64 | print("-------------------------------------------------------------------------------") 65 | print("PID\tUID\tCOMM\tCMD") 66 | try: 67 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 68 | proc_name = proc_comm.read().rstrip() 69 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 70 | proc_cmd = proc_cmd.read().rstrip() 71 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 72 | print("-------------------------------------------------------------------------------") 73 | except: 74 | proc_name = "NULL" 75 | 76 | log_submit(str(int2ip(event.saddr)),str(event.sport),str(int2ip(event.daddr)),str(event.dport),"HTTPS",payload_str,event.pid,event.uid,proc_name,proc_cmd) 77 | else: 78 | py_https_packet_dictionary[binascii.hexlify(current_Key)] = payload_str 79 | else: 80 | print("nb") 81 | 82 | else: 83 | 84 | if (current_Key in py_https_sessions): 85 | 86 | if (binascii.hexlify(current_Key) in py_https_packet_dictionary): 87 | 88 | prev_payload_string = py_https_packet_dictionary[binascii.hexlify(current_Key)] 89 | if (crlf not in payload_str): 90 | 91 | prev_payload_string += payload_str 92 | print("[*] 原始数据报处理后提取的ip/端口信息:") 93 | print(str(int2ip(event.saddr))+"[{}]".format(str(event.sport))+"---->"+str(int2ip(event.daddr))+"[{}]".format(str(event.dport))) 94 | print("-------------------------------------------------------------------------------") 95 | print("[*] 原始数据报处理后提取的payload信息:") 96 | printUntilCRLF(prev_payload_string, 'bytestr') 97 | print("-------------------------------------------------------------------------------") 98 | print("PID\tUID\tCOMM\tCMD") 99 | try: 100 | with open(f'/proc/{event.pid}/comm', 'r') as proc_comm: 101 | proc_name = proc_comm.read().rstrip() 102 | with open(f'/proc/{event.pid}/cmdline', 'r') as proc_cmd: 103 | proc_cmd = proc_cmd.read().rstrip() 104 | print("{}\t{}\t{}\t{}".format(event.pid,event.uid,proc_name,proc_cmd)) 105 | print("-------------------------------------------------------------------------------") 106 | except: 107 | proc_name = "NULL" 108 | 109 | log_submit(str(int2ip(event.saddr)),str(event.sport),str(int2ip(event.daddr)),str(event.dport),"HTTPS",prev_payload_string,event.pid,event.uid,proc_name,proc_cmd) 110 | 111 | try: 112 | del py_https_sessions[current_Key] 113 | del py_https_packet_dictionary[binascii.hexlify(current_Key)] 114 | except: 115 | print("error deleting from map or dictionary") 116 | else: 117 | 118 | prev_payload_string += payload_str 119 | if (len(prev_payload_string) > MAX_URL_STRING_LEN): 120 | print("url too long") 121 | try: 122 | del py_https_sessions[current_Key] 123 | del py_https_packet_dictionary[binascii.hexlify(current_Key)] 124 | except: 125 | print("error deleting from map or dict") 126 | py_https_packet_dictionary[binascii.hexlify(current_Key)] = prev_payload_string 127 | else: 128 | 129 | try: 130 | del py_https_sessions[current_Key] 131 | except: 132 | print("error del bpf_session") 133 | 134 | global py_https_packet_count 135 | py_https_packet_count += 1 136 | #print(https_packet_count) 137 | if (((py_https_packet_count) % CLEANUP_N_PACKETS) == 0): 138 | cleanup(py_https_sessions) 139 | 140 | 141 | 142 | class Global(): 143 | def __init__(self, pid, interface): 144 | self.pid = pid 145 | self.interface = interface 146 | 147 | class PYHTTPS(): 148 | 149 | def __init__(self, global_arg): 150 | 151 | self.bpf_uprobe_py_ssl = BPF(src_file = "./https/uprobe_py_ssl.c") 152 | self.bpf_uprobe_py_ssl.attach_uprobe(name=global_arg.libssl_path, sym="SSL_write_ex",fn_name="probe_SSL_rw_ex_enter") 153 | self.bpf_kprobe_py_https = BPF(src_file = "./https/https_py_tcp.c") 154 | self.bpf_kprobe_py_https.attach_kprobe(event="tcp_sendmsg", fn_name="trace_py_tcp_sendmsg") 155 | 156 | global bpf_kprobe_py_https 157 | bpf_kprobe_py_https = self.bpf_kprobe_py_https 158 | global py_https_sessions 159 | py_https_sessions = self.bpf_kprobe_py_https.get_table("sessions") 160 | 161 | print("[*] The HTTPS Hook for Python is ready.") 162 | 163 | def py_https_buffer_poll(self): 164 | self.bpf_kprobe_py_https["events_py_https"].open_perf_buffer(print_py_https) 165 | while True: 166 | try: 167 | self.bpf_kprobe_py_https.perf_buffer_poll() 168 | except KeyboardInterrupt: 169 | exit() 170 | 171 | 172 | 173 | def init(global_arg): 174 | libssl_path = global_arg.libssl_path 175 | interface = global_arg.interface 176 | global pid 177 | pid = global_arg.pid 178 | pyhttps = PYHTTPS(global_arg) 179 | return pyhttps 180 | 181 | def run(pyhttps): 182 | pyhttps.py_https_buffer_poll() 183 | 184 | 185 | -------------------------------------------------------------------------------- /user/user_udp.py: -------------------------------------------------------------------------------- 1 | from bcc import BPF 2 | import socket 3 | import ctypes as ct 4 | import sys 5 | 6 | 7 | sys.path.append('../utils/') 8 | from tools import * 9 | 10 | pid = None 11 | 12 | 13 | def print_udp(cpu,data,size): 14 | class skbuffer_event(ct.Structure): # 兼容结构体 15 | _fields_ = [ 16 | ("pid", ct.c_uint32), 17 | ("uid", ct.c_uint32), 18 | ("gid", ct.c_uint32), 19 | ("comm", ct.c_char * 64), 20 | ("raw", ct.c_ubyte * (size - ct.sizeof(ct.c_uint32 * 3) - ct.sizeof(ct.c_char * 64))) 21 | ] 22 | skb = ct.cast(data, ct.POINTER(skbuffer_event)).contents 23 | packet_str = skb.raw[:] 24 | 25 | global pid 26 | 27 | if pid == 'all' or pid == skb.pid: 28 | if not is_dns_query(packet_str): # 暂时排除dns请求 29 | packet_bytearray = bytearray(packet_str) 30 | # calculate ip header length 31 | ip_header_length = packet_bytearray[ETH_HLEN] # load Byte 32 | ip_header_length = ip_header_length & 0x0F # mask bits 0..3 33 | ip_header_length = ip_header_length << 2 # shift to obtain length 34 | 35 | # calculate packet total length 36 | total_length = packet_bytearray[ETH_HLEN + 2] # load MSB 37 | total_length = total_length << 8 # shift MSB 38 | total_length = total_length + packet_bytearray[ETH_HLEN + 3] # add LSB 39 | 40 | # retrieve ip source/dest 41 | ip_src_str = packet_str[ETH_HLEN + 12: ETH_HLEN + 16] # ip source offset 12..15 42 | ip_dst_str = packet_str[ETH_HLEN + 16:ETH_HLEN + 20] # ip dest offset 16..19 43 | 44 | ip_src = int.from_bytes(ip_src_str,"big") 45 | ip_dst = int.from_bytes(ip_dst_str,"big") 46 | 47 | port_src_str = packet_str[ETH_HLEN + ip_header_length:ETH_HLEN + ip_header_length + 2] 48 | port_dst_str = packet_str[ETH_HLEN + ip_header_length + 2:ETH_HLEN + ip_header_length + 4] 49 | 50 | port_src = str(int.from_bytes(port_src_str,"big")) 51 | port_dst = str(int.from_bytes(port_dst_str,"big")) 52 | 53 | print("[UDP] 原始数据报处理后提取的五元组信息:") 54 | print(int2ip(ip_src)+"[{}]".format(port_src)+"---->"+int2ip(ip_dst)+"[{}]".format(port_dst)) 55 | print("-------------------------------------------------------------------------------") 56 | 57 | payload_header = ETH_HLEN + ip_header_length + UDP_HLEN 58 | print("[UDP] 原始数据报处理后提取的payload信息:") 59 | payload_str_bytes = packet_str[payload_header:(len(packet_bytearray))] 60 | 61 | print("-------------------------------------------------------------------------------") 62 | try: 63 | payload_str = bytearray(payload_str_bytes).decode('utf-8') 64 | print(payload_str) 65 | print("-------------------------------------------------------------------------------") 66 | print("PID\tUID\tCOMM\tCMD") 67 | with open(f'/proc/{skb.pid}/comm', 'r') as proc_comm: 68 | proc_name = proc_comm.read().rstrip() 69 | with open(f'/proc/{skb.pid}/cmdline', 'r') as proc_cmd: 70 | proc_cmd = proc_cmd.read().rstrip() 71 | print("{}\t{}\t{}\t{}".format(skb.pid,skb.uid,proc_name,proc_cmd)) 72 | print("-------------------------------------------------------------------------------") 73 | log_submit(int2ip(ip_src),port_src,int2ip(ip_dst),port_dst,"UDP",payload_str_bytes,skb.pid,skb.uid,proc_name,proc_cmd) 74 | except: 75 | proc_name = skb.comm.decode() 76 | 77 | 78 | class Global(): 79 | def __init__(self, pid, interface): 80 | self.pid = pid 81 | self.interface = interface 82 | 83 | 84 | class UDP(): 85 | 86 | def __init__(self, global_arg): 87 | 88 | self.bpf_kprobe_udp = BPF(src_file = "./udp/kprobe_udp.c") 89 | self.bpf_sock_udp = BPF(src_file = "./udp/udp.c") 90 | self.bpf_kprobe_udp.attach_kprobe(event="udp_sendmsg", fn_name="trace_udp_sendmsg") 91 | function_udp_matching = self.bpf_sock_udp.load_func("udp_matching", BPF.SOCKET_FILTER) 92 | BPF.attach_raw_socket(function_udp_matching, global_arg.interface) 93 | socket_fd_udp = function_udp_matching.sock 94 | sock_udp = socket.fromfd(socket_fd_udp,socket.PF_PACKET,socket.SOCK_RAW,socket.IPPROTO_IP) 95 | sock_udp.setblocking(True) 96 | self.bpf_sock_udp["events_udp"].open_perf_buffer(print_udp) 97 | 98 | print("[*] The UDP Hook is ready.") 99 | 100 | def udp_buffer_poll(self): 101 | while True: 102 | try: 103 | self.bpf_sock_udp.perf_buffer_poll() 104 | except KeyboardInterrupt: 105 | exit() 106 | 107 | 108 | 109 | def init(global_arg): 110 | libssl_path = global_arg.libssl_path 111 | interface = global_arg.interface 112 | global pid 113 | pid = global_arg.pid 114 | udp = UDP(global_arg) 115 | return udp 116 | 117 | def run(udp): 118 | udp.udp_buffer_poll() 119 | 120 | 121 | -------------------------------------------------------------------------------- /utils/__pycache__/tools.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Your7Maxx/FlowGod/1a1f6c83dc16818ad165796baa03c007ec71a405/utils/__pycache__/tools.cpython-310.pyc -------------------------------------------------------------------------------- /utils/tools.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import calendar 3 | from datetime import datetime 4 | import time 5 | import subprocess 6 | import re 7 | import binascii 8 | import dnslib 9 | 10 | crlf2 = b'\r\n\r\n' 11 | crlf2_0 = b'\r\n\r\n\x00' 12 | crlf = b'\r\n' 13 | ETH_HLEN = 14 14 | UDP_HLEN = 8 15 | 16 | CLEANUP_N_PACKETS = 50 # cleanup every CLEANUP_N_PACKETS packets received 17 | MAX_URL_STRING_LEN = 8192 # max url string len (usually 8K) 18 | MAX_AGE_SECONDS = 30 19 | 20 | 21 | 22 | class Global(): 23 | def __init__(self, libssl_path, interface, pid, go_program_path): 24 | self.libssl_path = libssl_path 25 | self.interface = interface 26 | self.pid = pid 27 | self.go_program_path = go_program_path 28 | 29 | 30 | def int2ip(rawip): 31 | result = [] 32 | for i in range(4): 33 | rawip, mod = divmod(rawip, 256) 34 | result.insert(0,mod) 35 | return '.'.join(map(str,result)) 36 | 37 | def is_dns_query(packet_str): 38 | ip_src_str = packet_str[ETH_HLEN + 12: ETH_HLEN + 16] # ip source offset 12..15 39 | ip_dst_str = packet_str[ETH_HLEN + 16:ETH_HLEN + 20] # ip dest offset 16..19 40 | 41 | ip_src = int.from_bytes(ip_src_str,"big") 42 | ip_dst = int.from_bytes(ip_dst_str,"big") 43 | if int2ip(ip_dst) == '114.114.114.114': 44 | return True 45 | else: 46 | return False 47 | 48 | def printUntilCRLF(s,type): 49 | if type == 'str': 50 | crlf = '\r\n' 51 | s = s.split(crlf) 52 | for i in range(len(s)): 53 | print(s[i]) 54 | 55 | elif type == 'bytestr': 56 | crlf = b'\r\n' 57 | s = s.split(crlf) 58 | for i in range(len(s)): 59 | print(s[i].decode()) 60 | 61 | 62 | def log_submit(sip,sport,dip,dport,protocal,request,pid,uid,comm,cmd): 63 | try: 64 | now = datetime.now() 65 | dt_string = str(now.strftime("%Y %m %d %H:%M:%S")) 66 | dt_str = dt_string.split(" ") 67 | 68 | if list(dt_string.split(" ")[1])[0] == '0': 69 | mon = int(list(dt_string.split(" ")[1])[1]) 70 | dt_str[1] = calendar.month_abbr[mon] 71 | else: 72 | mon = int(dt_string.split(" ")[1]) 73 | dt_str[1] = calendar.month_abbr[mon] 74 | 75 | dt_str_final = " ".join(str(i) for i in dt_str) 76 | 77 | data = {"sip":sip, 78 | "sport":sport, 79 | "dip":dip, 80 | "dport":dport, 81 | "protocal":protocal, 82 | "request":request, 83 | "pid":pid, 84 | "uid":uid, 85 | "comm":comm, 86 | "cmd":cmd} 87 | 88 | # print(str(data)) 89 | bpf_event_log = dt_str_final + ' ebpf: ebpf_data: ' + str(data) + '\n' 90 | 91 | with open('./log/flow.log','a') as fd: 92 | fd.write(bpf_event_log) 93 | 94 | except IOError: 95 | with open('./log/flow.log','w') as fd: 96 | fd.write(bpf_event_log) 97 | except: 98 | print("Error during logging.") 99 | 100 | 101 | def get_go_version(binary_file): 102 | output = subprocess.check_output(["strings", binary_file]).decode() 103 | pattern = r"go\d+\.\d+\.\d+" 104 | matches = re.findall(pattern, output) 105 | version_nums = matches[0][2:].split('.') 106 | version_ints = [int(num) for num in version_nums] 107 | 108 | if version_ints < [1,17,0]: 109 | print("[*] 检测到目标程序的go编译版本小于1.17.0") 110 | return 0 111 | else: 112 | print("[*] 检测到目标程序的go编译版本大于1.17.0") 113 | return 1 114 | 115 | def cleanup(bpf_sessions): 116 | current_time = int(time.time()) 117 | for key, leaf in bpf_sessions.items(): 118 | try: 119 | current_leaf = bpf_sessions[key] 120 | if (current_leaf.timestamp == 0): 121 | bpf_sessions[key] = bpf_sessions.Leaf(current_time) 122 | else: 123 | # delete older entries 124 | if (current_time - current_leaf.timestamp > MAX_AGE_SECONDS): 125 | del bpf_sessions[key] 126 | except: 127 | print("cleanup exception.") 128 | return 129 | --------------------------------------------------------------------------------