본문 바로가기

리눅스 커널

(42)
Kernel hooking packet capture #include #include #include #include #include #include #include struct nf_hook_ops hook; unsigned int hook_func(void * priv, struct sk_buff * skb, const struct nf_hook_state * state) { struct iphdr * ip = ip_hdr(skb); printk("caller: %s\n", current->comm); printk("ip protocol: %d\n", ip->protocol); printk("%pI4 -> %pI4\n", &ip->saddr, &ip->daddr); return NF_ACCEPT; } int start(void) { hook.hook =..
Raw socket outgoing packet capture 앞서 작성한 글에서는 raw socket을 이용해서 incoming packet을 스니핑하는 방법에 대해 다루어보았다. 그러나 테스트 시 한가지 문제가 있음을 볼 수 있다. outgoing packet에 대해서는 제대로 스니핑 되지 않는 것이다. 그래서 이번에는 raw socket 사용 시 outgoing packet을 스니핑 하는 방법에 대해서 살펴보겠다. #include #include #include #include #include #include #include #include "pktfilter.c" int main(void) { int sock; unsigned char buf[65536]; struct sockaddr_ll sll; sock = socket(PF_PACKET, SOCK_RAW..
Raw socket incoming packet capture 시스템으로 들어오는 패킷을 캡쳐하는 방식은 크게 세가지가 있다. 여기서는 유저레벨에서 할 수 있는 raw socket을 이용하여 패킷을 스니핑 해보겠다. raw socket에 대한 개념은 따로 언급하지 않고 사용 방법에 대해서만 정리해보겠다. 먼저 네트워크 계층 까지만 다룰 수 있는 raw socket과 데이터 링크 계층까지 전부 다룰 수 있는 raw socket 이렇게 두가지 가 있다는 것을 이해하고 아래 코드를 살펴보겠다. #include #include #include #include #include "pktfilter.c" //패킷을 뜯어서 터미널에 출력하는 함수가 정의된 파일. int main(void) { int sock; unsigned char buf[65536]; //domain, typ..
Ethernet & ARP Header 첫번째는 이더넷 헤더이다. #include struct ethhdr { unsigned charh_dest[ETH_ALEN];/* destination eth addr*/ unsigned charh_source[ETH_ALEN];/* source ether addr*/ __be16h_proto;/* packet type ID field*/ } __attribute__((packed)); h_dest: 도착지 MAC주소 h_source: 출발지 MAC주소 h_proto: 상위 계층 헤더의 프로토콜 다음은 ARP 헤더이다. #include struct arphdr { __be16ar_hrd;/* format of hardware address*/ __be16ar_pro;/* format of protocol..
IP & ICMP Header 먼저 IP헤더이다. #include struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8ihl:4, version:4; #elif defined (__BIG_ENDIAN_BITFIELD) __u8version:4, ihl:4; #else #error"Please fix " #endif __u8tos; __be16tot_len; __be16id; __be16frag_off; __u8ttl; __u8protocol; __sum16check; __be32saddr; __be32daddr; /*The options start here. */ }; ihl: ip헤더의 길이, 4바이트 단위 (ex, 5 -> 20바이트, 옵션 포함 시 최대 15 -> 60바이트 까지..
TCP & UDP Header C에서 구현한 TCP 헤더 #include struct tcphdr { __be16source; __be16dest; __be32seq; __be32ack_seq; #if defined(__LITTLE_ENDIAN_BITFIELD) __u16res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; #elif defined(__BIG_ENDIAN_BITFIELD) __u16doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else #error"Adjust your defines" #endif __be16window; __sum16check; __be16ur..
ioctl - socket ioctl 호출 시 file descriptor, command, args 가 필요한데, 일반적인 eth0 장치에 대해서는 세번째 인자로 아래의 자료구조를 사용하며, struct ifreq { #define IFHWADDRLEN6 union { charifrn_name[IFNAMSIZ];/* if name, e.g. "en0" */ } ifr_ifrn; union { structsockaddr ifru_addr; structsockaddr ifru_dstaddr; structsockaddr ifru_broadaddr; structsockaddr ifru_netmask; struct sockaddr ifru_hwaddr; shortifru_flags; intifru_ivalue; intifru_mtu; s..
struct net_device example #include #include #include #include char * if_name = NULL; module_param(if_name, charp, 0644); static int print_info(void) { struct net_device * dev = dev_get_by_name(&init_net, if_name); struct in_ifaddr * addrs = NULL; struct wireless_dev * wdev = NULL; if (!dev) return -1; printk("-----net_device info-----\n"); printk("name: %s\n", dev->name); //interface name printk("ifindex: %d\n", dev->ifi..
Kernel wait queue #include #include #include #include #include #include #include #include static struct task_struct * ts = NULL; static DECLARE_WAIT_QUEUE_HEAD(wq); //static wait_queue_head_t wq; static int cond; static int ts_routine(void * ptr) { unsigned long remain; //allow_signal(SIGUSR1); while (1) { //remain = msleep_interruptible(5000); cond = 0; remain = wait_event_interruptible_timeout(wq, cond == 1, 5 ..
Kernel thread & signal #include #include #include #include #include #include #include static struct task_struct * ts = NULL; static int ts_routine(void * ptr) { unsigned long remain; allow_signal(SIGUSR1); while (1) { remain = msleep_interruptible(5000); //signal을 기다리면서 ms동안 sleep if (kthread_should_stop()) //쓰레드 종료 요청을 받는 함수 break; printk("wake up, remain time: %lums\n", remain); } printk("remain time: %lums\n", rema..