1.SYN ( 동기화응답 보내기 ) sock.send()
! RST 패킷 차단
iptables 방화벽을 이용해야 한다.
[root@localhost ~]# iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
# 나가는 패킷 차단
[root@localhost ~]# iptables --list Chain INPUT (policy ACCEPT) target prot opt source destination
Chain FORWARD (policy ACCEPT) target prot opt source destination
Chain OUTPUT (policy ACCEPT) target prot opt source destination DROP tcp -- anywhere anywhere tcp flags:RST/RST
[ #vi tcp.py ]
tcp.py 접기
import struct
class Tcp: def __init__(self,data=None): if data != None: (self.src,)=struct.unpack('!H',data[:2]) (self.dst,)=struct.unpack('!H',data[2:4]) (self.sq_num,)=struct.unpack('!L',data[4:8]) (self.ack_num,)=struct.unpack('!L',data[8:12]) self.len=data[12] self.len>>=2 self.flag=data[13] (self.window,)=struct.unpack('!H',data[14:16]) (self.chksum,)=struct.unpack('!H',data[16:18]) (self.un,)=struct.unpack('!H',data[18:20])
self.data=data[20:] else: self.src=b'' self.dst=b'' self.sq_num=b'' self.ack_num=b'' self.len=b'' self.flag=b'' self.window=b'' self.chksum=b'' self.un=b''
self.data=b''
def get_header(self): return self.src+self.dst+self.sq_num+self.ack_num+self.len+self.flag+self.window+self.chksum+self.un def set_src(self,src): self.src=struct.pack('!H',src) def set_dst(self,dst): self.dst=struct.pack('!H',dst) def set_sq_num(self,sq_num): self.sq_num=struct.pack('L',sq_num)
def set_ack_num(self,ack_num): self.ack_num=struct.pack('!L',ack_num) def set_len(self,len): self.len=struct.pack('!B',len<<2 ) def set_flag(self,flag): self.flag=struct.pack('!B',flag) def set_window(self,window): self.window=struct.pack('!H',window) def set_chksum(self,chksum): self.chksum=struct.pack('!H',chksum) def set_un(self,un): self.un=struct.pack('!H',un)
def set_data(self,data):
self.data=data.encode()
접기
[ # vi raw_tcp_client.py ]
1) syn 를 보내고 syn/ack 받아오기
syn 신호 접기
from socket import* import struct import ip as _ip import eth as _eth import tcp as _tcp
def make_chksum(header):
size=len(header) if (size %2) !=0 : header=header+b'\x00' size=len(header)
header=struct.unpack('!'+str(size//2)+'H',header) chksum=sum(header)
carry=chksum & 0b_1111_1111_0000_0000_0000_0000 carry = chksum >> 16 while carry !=0: chksum =chksum & 0b_0000_0000_1111_1111_1111_1111 chksum =chksum +carry carry=chksum & 0b_1111_1111_0000_0000_0000_0000 carry = chksum >> 16 chksum =chksum ^ 0b_1111_1111_1111_1111 return chksum
sock = socket(AF_PACKET,SOCK_RAW) sock.bind(('eth0',SOCK_RAW))
client_port=1111 server_port=10000
client_seq=1 server_seq=0
ip=_ip.Ip() eth=_eth.Eth() tcp=_tcp.Tcp()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(0) tcp.set_len(20) tcp.set_flag(2) tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header()
tcp.set_chksum(make_chksum(pseudo))
eth.set_dst('00:0c:29:6e:09:cb') eth.set_src('00:0c:29:d1:80:e5') eth.set_type(0x0800)
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
접기
>> 실행 결과
1) 115 에서 sniffer.py 를 켠다
2) 130 에서 tcp_server.py 를 실행
3) 115 에서 raw_tcp_client.py 를 실행
>> 방화벽을 제거 했으므로 응답이 올 때까지 010010 이 게속 온다
2) ack 보내기 ( 3 way handshack )
ack 보내기 접기
# syn/ack 뒤에다 추가
client_seq +=1
#recv 받아오기 ( 응답기다리기 )
while True :
(raw,_)=sock.recvfrom(65535) tmp_eth=_eth.Eth(raw[:14]) if tmp_eth.type=='0x0800' and (tmp_eth.dst=='00:0c:29:6e:09:cb'or tmp_eth.src=='00:0c:29:6e:09:cb'): tmp_ip=_ip.Ip(raw[14:34]) if tmp_ip.type==6: tmp_tcp=_tcp.Tcp(raw[34:]) if client_seq ==tmp_tcp.ack: server_seq =tmp_tcp.seq break server_seq +=1
tcp=_tcp.Tcp() ip=_ip.Ip()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(16) tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header() tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
접기
>> 실행 결과
1) 실행방법 syn/ack 와 동일
#더이상의 응답이 오지 않아야 성공
3) data 보내기 ( psh )
psh 접기
1) syn/ack + 2) ack 뒤에 추가
d ata= b'KOREA' tcp=_tcp.Tcp() ip=_ip.Ip()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(24) tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20+5 ) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',25 ) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header()+data tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header()+ data )
접기
>> 실행 결과
1) flag : 011000 뒤에 flag : 010000 응답이 와야함
2) 010000 응답 오고 난후 ack/fin 이 계속 와야 함
4) finsh 보내기 (ack/fin)
fin/ack 접기
1) syn/ack + 2) ack +3) psh 뒤에 추가
from socket import* import struct import ip as _ip import eth as _eth import tcp as _tcp
def make_chksum(header):
size=len(header) if (size %2) !=0 : header=header+b'\x00' size=len(header)
header=struct.unpack('!'+str(size//2)+'H',header) chksum=sum(header)
carry=chksum & 0b_1111_1111_0000_0000_0000_0000 carry = chksum >> 16 while carry !=0: chksum =chksum & 0b_0000_0000_1111_1111_1111_1111 chksum =chksum +carry carry=chksum & 0b_1111_1111_0000_0000_0000_0000 carry = chksum >> 16 chksum =chksum ^ 0b_1111_1111_1111_1111 return chksum
sock = socket(AF_PACKET,SOCK_RAW) sock.bind(('eth0',SOCK_RAW))
client_port=3333 server_port=10001 # tcp_server.py의 포트번호와 같게 해줘야함
client_seq=1 server_seq=0
#syn ip=_ip.Ip() eth=_eth.Eth() tcp=_tcp.Tcp()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(0) tcp.set_len(20) tcp.set_flag(2) #flag : 000010 tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header() tcp.set_chksum(make_chksum(pseudo))
eth.set_dst('00:0c:29:6e:09:cb') eth.set_src('00:0c:29:d1:80:e5') eth.set_type(0x0800)
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
client_seq +=1 while True: (raw,_)=sock.recvfrom(65535) tmp_eth=_eth.Eth(raw[:14]) if tmp_eth.type=='0x0800' and (tmp_eth.dst=='00:0c:29:6e:09:cb'or tmp_eth.src=='00:0c:29:6e:09:cb'): tmp_ip=_ip.Ip(raw[14:34]) if tmp_ip.type==6: tmp_tcp=_tcp.Tcp(raw[34:]) if client_seq==tmp_tcp.ack: server_seq=tmp_tcp.seq break server_seq +=1
#ack tcp=_tcp.Tcp() ip=_ip.Ip() tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(16) #flag : 010000 tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header() tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
#psh data=b'KOREA' tcp=_tcp.Tcp() ip=_ip.Ip()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(24) #flag: 011000 tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20+5) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130')
ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',25) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header()+data tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header()+data)
client_seq +=5 while True: (raw,_)=sock.recvfrom(65535) tmp_eth=_eth.Eth(raw[:14])
if tmp_eth.type=='0x0800' and (tmp_eth.dst=='00:0c:29:6e:09:cb'or tmp_eth.src=='00:0c:29:6e:09:cb'): tmp_ip=_ip.Ip(raw[14:34]) if tmp_ip.type==6: tmp_tcp=_tcp.Tcp(raw[34:]) if client_seq==tmp_tcp.ack: server_seq=tmp_tcp.seq break
server_seq +=1
#fin/ack tcp=_tcp.Tcp() ip=_ip.Ip()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(16) tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set_chksum(0) ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header() tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
#fin tcp=_tcp.Tcp() ip=_ip.Ip()
tcp.set_src(client_port) tcp.set_dst(server_port) tcp.set_seq(client_seq) tcp.set_ack(server_seq) tcp.set_len(20) tcp.set_flag(17) tcp.set_window(65535) tcp.set_chksum(0) tcp.set_dummy(0)
ip.set_ver(4) ip.set_len(20) ip.set_total_len(len(tcp.get_header())+20) ip.set_id(0) ip.set_type(6) ip.set_ttl(64) ip.set_flag(0) ip.set_offset(0) ip.set _ chksum(0)ip.set_src('192.168.219.115') ip.set_dst('192.168.219.130') ip.set_chksum(make_chksum(ip.get_header()))
len2=struct.pack('!H',len(tcp.get_header())) pseudo=ip.src+ip.dst+b'\x00'+ ip.type+len2+tcp.get_header() tcp.set_chksum(make_chksum(pseudo))
sock.send(eth.get_header()+ip.get_header()+tcp.get_header())
접기
>> 실행결과
1) 130에서 tcp_server.py 실행
2) 115에서 sniffer.py 실행
3) 115 에서 raw_tcp_client.py 실행
#> netstat -ant
포트 연결 확인
-> 연결이 끊긴 상태여야 함
>>>> 실습
1) 서버 변경
tcp_server.py
tcp_server2.py 접기
import socket
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.bind(('',9999)) server_socket.listen(1)
while True: client_socket = server_socket.accept() print( client_socket )
data = client_socket[0].recv(65535) print( 'receive:', data.decode()) client_socket[0].send(data) client_socket[0].close()
접기
// netstat -ant 에서 바로 연결이 끊기지 않고 time-wait 뜨는 것 해결하기
// fin/ack 순서 상관없는지 확인
// 실습 응답 오지 않도록 해결