본문 바로가기
프로그래밍/NETWORK HACKING

[네트워크 보안] TCP 포트 스캔 / TCP SYN 패킷 전송

by B T Y 2017. 7. 14.
반응형

TCP 포트 스캔 / TCP SYN 패킷 전송에 대해서 정리한다.



TCP는 플래그에 따라서 다양한 통신이 존재



1. 열린 포트에 대한 검색


1). half-open 방식( 스텔스 방식 )

  - 로그에 남지 않으면서 포트를 스캔 할 수 있는 방식

    ( 완벽하게 세션을 맺지 않는다 )


  - 포트가 열려있는 경우: SYN + ACK(18) 응답이 온다

  - 포트가 닫혀 있는 경우: RST + ACK(20) 응답이 온다 

  ( 표준 동작은 응답을 안해주도록 되있는데 운영체제마다 동작이 다르다 )


2). full-scan 방식

  - 세션을 완전히 맺는 방식

  - 로그에 기록이 남는다.

   ( 방화벽이나 다른 상황 때문에 세션이 완전히 맺어지지 않는 경우도 있다 )



2. 닫힌 포트에 대한 검색

  - 닫혀있는 경우에만 응답이 온다.

  - fin scan, null scan( flag를 하나도 설정하지 않는 방식 ), x-mas scan( flag를 fin,psh,urg 설정하는 방식 ) - 3가지 방식 모두 스텔스 기반 방식

  - null scan, x-mas scan은 예전에 방화벽을 우회하기 위해 사용됬다.

   ( 요즘은 방화벽 룰셋 설정에 의해 대부분 막힌다 )



3. 호스트를 검색하는 방법

  - 보통은 ping을 사용

  - syn-ack 플래그를 이용

    - 호스트가 살아있다면 RST 응답이 온다



- TCP SYN 패킷 전송을 위한 구성 코드


syn.py


import struct

import socket

from header.eth import *

from header.ip import *

from header.tcp import *


def make_chksum( header ):


  size = len( header )

  if size % 2:

    header = header + b'\x00'

    size = len( header )


  size = size // 2

  header = struct.unpack('!' + str(size) + 'H', header )

  chksum = sum( header )


  carry = chksum & 0xFF0000

  carry = carry >> 16

  while carry != 0:

    chksum = chksum & 0xFFFF

    chksum = chksum + carry

    carry = chksum & 0xFF0000

    carry = carry >> 16


  chksum = chksum ^ 0xFFFF

  return chksum



eth = Eth()

ip = Ip()

tcp = Tcp()


tcp.src = 20000

tcp.dst = 22

tcp.seq = 33333

tcp.ack = 0

tcp.length = 20

tcp.flag = 2

tcp.window_size = 0

tcp.chksum = 0

tcp.point_or_dummy = 0


ip.ver = 4

ip.length = 20

ip.service = 0

ip.total = 20 + len( tcp.header )

ip.id = 0x1234

ip.flag = 0

ip.offset = 0

ip.ttl = 64

ip.type = 6

ip.chksum = 0

ip.src = '192.168.6.112'

ip.dst = '192.168.6.200'

ip.chksum = make_chksum( ip.header )


length = struct.pack('!H', tcp.length)


pseudo = ip._src + ip._dst + b'\x00' + ip._type + length + tcp.header

tcp.chksum = make_chksum( pseudo )


eth.dst = '00:50:56:31:A8:43'

eth.src = '00:50:56:3B:25:F8'

eth.type = 0x0800



sock = socket.socket( socket.AF_PACKET, socket.SOCK_RAW )

sock.bind( ('eth0', socket.SOCK_RAW) )


sock.send( eth.header + ip.header + tcp.header )



( 서버에 열려 있는 포트로 TCP 통신을 구성해서 SYN 패킷을 보내게 되면 서버로부터 SYN + ACK 응답이 오게되고 

SYN 패킷만 구성했기 때문에 RST를 서버에게 보내게 된다 )


* 이점을 이용해서 TCP Half-open scan(스텔스 방식)을 할수 있고 스텔스 방식을 사용하게 되면 

포트 스캔을 한 정보가 로그에 남지 않게 된다.



( 서버에 열려 있지 않은 포트에 SYN 패킷을 보내게되면 RST + ACK 응답이 돌아오게 된다 )


* 표준 동작은 아무 응답도 안해주지만 운영체제마다 동작이 다르고 리눅스에서는 해준다는걸 알수 있다.



반응형

댓글