SMALL
패킷 구조를 알아 볼겸 raw socket 관련 내용 찾아 보았다.
좀 더 정확하게 만들어 봐야겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <linux/ip.h> #include <linux/tcp.h> //ipheader의 기본 크기는 20 byte //But Option 헤더의 크기가 존재 //Option Header의 크기를 0~ 40 까지 조정 할 수있다. ##########################################설명###############################################33 struct iphdr { 위의 define 된 부분은 리틀 엔디언이냐 빅엔디언이냐 커널? 빌드인가 그때 설정되는 거같다. 헤더를 분석하는데 기본적으로 큰 문제는 없다. #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4 , //4bits IPv4, 6 선택 version:4; //Internet Header Length : IP헤더의 크기 //IP 헤더의 크기는 4바이트 단위 //만약에 1111 == 0xf 15*4 = 60byte 최대 #elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4 #else #error "Please fix <asm/byteorder.h>" #endif __u8 tos; //전송 우선순위 정보 __u16 tot_len; //'이더넷 헤더'를 제외한 전체 패킷의 길이 __u16 id; //패킷의 ID, 패킷 단편화일 때 __u16 frag_off; //[1bit] [1bit] [1bit] [13bit] // 예비 DF MF Fragment offset [기존 데이터에서 offset] __u8 ttl; //경유 할 수있는 라우터수 __u8 protocol; //6 = TCP //0x11 = UDP //0x01 = ICMP __u16 check; //checksum 에러 확인 __u32 saddr; //출발지 주소 __u32 daddr; //목적지 주소 <-- 이 이후로는 Option이다. ihl에 따라달림 }; struct tcphdr { __u16 source; //출발지 포트 번호 __u16 dest; //도착지 포트번호 __u32 seq; //순서 번호 [전송된 순서] __u32 ack_seq; //다음 수신 예상 번호 #if defined(__LITTLE_ENDIAN_BITFIELD) __u16 res1:4, //데이터의 위치 == TCP 헤더의 크기 //헤더가 끝이 나고나면 데이터이다. doff:4, //예비 비트 //여기서 부터는 이제 flag 비트들 fin:1, //연결을 끊음 syn:1, //syn packet rst:1, //연결 끊음 psh:1, //버퍼링된 자료 푸쉬 ack:1, //응답 urg:1, //긴급 메시지 ece:1, //ECN-ECHO? cwr:1; //Congestion Window reduced #elif defined(__BIG_ENDIAN_BITFIELD) __u16 doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; #else #error "Adjust your <asm/byteorder.h> defines" #endif __u16 window; //TCP 흐름 제어를 위한 버퍼 크기 __u16 check; //체크섬 __u16 urg_ptr; //긴급한 데이터가 시작되는 위치 정보 <-- 헤더의 크기에 따라서 옵션 0~40 바이트 가능 <-- 이후부터는 실제 데이터 }; 0 번지 IPHEADER [20byte] --> 옵션 추가x 20 번지 TCPHEADER [20byte] --> 옵션 추가x 40 번지 실제 데이터들 ##########################################설명###############################################33 int main() { //0 - 19 ipheader //20 - 39 tcpheader //40 - 59 data //packet 하나 unsigned char packet[60]; struct sockaddr_in address; //setsockopt val int val = 1; //raw socket descriptor int raw_socket = 0; //ip header struct iphdr *iphdr; //tcp header struct tcphdr *tcphdr; //sending data unsigned char *data; //RAW SOCKET CREATE raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); //socket option change //이친구와 쌍으로 getsockop 함수 setsockopt( raw_socket, IPPROTO_IP, IP_HDRINCL, (char *)&val, sizeof(val) ); //pointer set iphdr = (struct iphdr*) packet; //ip header 초기화 memset((char*)iphdr, 0, 20); //ipv4 setting iphdr->version = 4; //ip header len 설정 iphdr->ihl = 5; //5*4 = 20byte //ip protocl setting iphdr->protocol = IPPROTO_TCP; //ip total packet len iphdr->tot_len = 60; //ip 패킷 id 설정 iphdr->id = htons(666); //ip ttl 설정 iphdr->ttl = 60; //ip check sum //계산하는 함수 존재 iphdr->check = 1; //ip src ip 설정 iphdr->saddr = inet_addr("192.168.0.1"); //ip dst ip 설정 iphdr->daddr = inet_addr("192.168.137.161"); /* * ip setting end */ //ip[20] + tcp pointer setting tcphdr = (struct tcphdr*)((char*)packet + 20); //tcp header 초기화 memset((char*)tcphdr, 0, 20); //tcp src port 설정 tcphdr->source = htons( 8888 ); //tcp dst port 설정 tcphdr->dest = htons( 9999 ); //tcp seq number 설정 tcphdr->seq = htonl( 77777 ); //tcp ack number 설정 tcphdr->ack_seq = htonl( 666666 ); //tcp offset 설정 tcphdr->doff = 5; //tcp syn flag 설정 tcphdr->syn = 1; //tcp windows size 설정 tcphdr->window = htons( 256 ); //tcp check sum tcphdr->check = 1; /* * tcp setting end */ data =(unsigned char*)((unsigned char*)packet + 40); strcpy(data , "richong!!"); address.sin_family = AF_INET; address.sin_port = htons( 10000 ); address.sin_addr.s_addr = inet_addr( "127.0.0.1" ); sendto( raw_socket, &packet, sizeof(packet), 0x0,(struct sockaddr *)&address, sizeof(address)); } | cs |
[출처] http://research.hackerschool.org/study/SS_1.htm
LIST
'reversing > rootkit' 카테고리의 다른 글
Why use system call? (0) | 2018.03.12 |
---|---|
rootkit - packet sniff[2] (0) | 2017.07.15 |
rootkit - packet sniff[0] (0) | 2017.06.21 |
rootkit - root [2] (0) | 2017.06.13 |
rootkit - root [1] (0) | 2017.06.02 |