본문 바로가기

reversing/rootkit

rootkit - packet sniff[1]

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,  020);
    //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, 020);
    //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