네트워크 프로그래밍2장연습문제1. 4바이트로 표현된 숫자의 바이트 순서를 바꾸는 프로그램을 작성하시오. 예를 들어 16진수 0x12345678를 입력하면 0x78563412를 출력하도록 하시오, 순서를 바꾸는 함수의 프로토타입을 아래와 같이 작성하시오. 아래에서 before 인자는 바이트 순서를 바꾸기 전의 값이고 함수의 리턴 값은 바이트 순서가 바뀐 후의 값이다.unsigned int convert_order32(unsigned int before);//ex2_1.c#include#include#include#include#includeunsigned int convert_order32(unsigned int before);main(){unsigned int before, after;printf("Enter : ");scanf("%x", &before);printf("Before : %xn", before);after = convert_order32(before);printf("After : %xn", after);}unsigned int convert_order32(unsigned int before){return htonl(before);}{2. 자신이 사용하는 시스템의 호스트 바이트 순서가 big endian인지 little endian인지를 확인하는 프로그램을 작성하시오.//ex2_2.c#include#include#include#include#includeunsigned int convert_order32(unsigned int before);main(){unsigned int before, after;printf("Enter : ");scanf("%x", &before);printf("Before : %xn", before);after = convert_order32(before);printf("After : %xn", after);}unsigned int convert_order32(unsigned int before){return ntohl(before);}{3. 한 프로세스가 개설할 수 있는 소켓의 최대 수는 몇 개이지를 확인하는 프로그램을 작성하시오.#include#includemain(){int max;max=getdtablesize();printf("getdatablesize : %d n", max);}{4. 임의의 호스트의 도메인 이름을 인자로 받아서 호스트의 ip주소를 출력하는 프로그램 get_hostent.c를 작성하되 gethostbyname() 함수를 이용하시오.// get_hostent.c#include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) {struct hostent *hp;struct in_addr in;int i;char buf[20];if(argch_addr_list[i]; i++) {memcpy(&in.s_addr, hp->h_addr_list[i],sizeof(in.s_addr));inet_ntop(AF_INET, &in, buf, sizeof(buf));printf("IP 주소(%d 번째) : %sn",i+1,buf);}puts("");return 0;}{5. bind() 함수를 잘못 사용하는 경우 발생하는 에러코드를 확인해 보시오. 아래의 테스트 항목별로 bind()함수를 실행하고 bind() 함수가 실패한 경우 perror() 함수를 사용하여 에러의 내용을 출력하시오.int bind(int s, struct sockaddr *addr, int len);*테스트 항목1) 인자 s에 현재 존재하지 않는 소켓번호를 입력한 경우2) 인자 s에 소켓이 아닌 정규(regular) 파일 디스크립터를 입력한 경우3) 소켓주소 구조체 인자에 이미 사용 중인 포트번호를 중복 사용한 경우4) 1~1023번 중 현재 시스템이 사용하지 않는 포트번호를 사용한 경우5) 테스트 프로그램을 root 권한과 일반 사용자 권한으로 각각 실행해 보시오6. UDP 에코 클라이언트 프로그램을 수정하여 연결된(connected) UDP를 사용하도록 변경하시오, 아래 순서대로 작성하되 각 단계에서 함수의 성공 및 실패 여부를 점검하시오.*작성절차1) UDP 소켓 개설2) 서버 소켓주소 구조체 작성3) 서버 소켓주소를 인자로 하여 connect() 호출4) write() 또는 send()로 에코 메시지 전달5) read() 또는 recv()로 에코 메시지 수신6) 연결된 UDP 종료7) close()로 UDP 소켓 닫기
nmap 사용법 익히기사용법 : nmap [Scan Type(s)] [Options] Scan Type{=> nmap -sT -PT -PI -F -T 3 61.255.3.57135/tcp port는 open 되었고, loc-srv를 제공한다. 139/tcp port는 netbios-ssn를 제공한다. 445/tcp port는 microsoft-ds를, 1025/tcp는 NFS-or-IIS를 5000/tcp 는 UPnP를 제공한다. 스캔에 302초가 걸렸다.1. -sTTCP connect() scan : TCP scannning의 가장 기초적인 형태로 connect() 함수를 사용해서 모든 포트에 대해 스캔하는 방식이다. 만약 포트가 listening 상태라면 connect()는 성공할 것이고, 그렇지 않으면 reachable 되지 않는다.2. -sSTCP SYN scan : full TCP 접속을 하지 않으므로 half-open"스캐닝이라 한다. 하나의 SYN 패킷을 보내어 SYN/ACK 응답이 오면 그 포트는 listening 상태임을 나타내며, RST 응답이 오면 non-listener임을 나타낸다. 이 기술은 하나의 패킷을 보내어 SYN/ACK 응답을 받으면 그 즉시 RST 패킷을 보내서 접속을 끊어버린다. 이렇게 하면 접속이 이루어지지 않은 상태에서 접속을 끊었기 때문에 로그를 남기지 않는 경우가 대부분이다. custom SYN packet을 만들기 위해서는 루트 권한이 필요하다.3. -sF, -sX, -sNStealth FIN, Xmas Tree, Null Scan : 이들은 SYN 패킷을 막아놓은 방화벽이나 패킷 필터 또는 Synlogger와 Courtney 같은 스캔을 탐지하는 프로그램을 무사히 통과할 수 있다. open 포트로 FIN 패킷을 보내면 이 패킷을 무시하고, closed 포트로 보내면 RST 패킷이 온다. 이들 스캔은 주로 유닉스계열 OS에서만 사용 가능하며, 루트권한이 필요하다.4. -sPPing scanning : 네트워크의 어느 호스트가 살아있는지를 알고 싶을 때 사용한다. nmap은 명시 한 네트워크의 모든 IP 주소로 ICMP echo request packet을 보내어 이것을 행한다. 호스트가 살아 있다면 응답을 보낸다. 하지만 microsoft.com 같은 일부 사이트는 echo request packet을 방해한다. 따라서 nmap은 포트번호 80(default)으로 TCP ack packet을 보낸다. 만약 RST back을 받았다면 이 시스템은 살아있는 것이다.5. -sUUDP scans : 이것은 호스트의 어떠한 UDP 포트가 open 되어 있는지를 결정하기 위해 사용된다. 이 기술은 시스템의 각 포트에 0 바이트 udp 패킷을 보낸다. 만일 ICMP port unreachable 메시지를 받았다면 이 포트는 closed 상태이며, 다른 경우라 open 상태라고 할 수 있다. 일부에서는 UDP 스캐닝이 무의미하다라고 말한다. 하지만 최근의 Solaris rcpbind hole을 보면 Rpcbind가 32770 이상의 정의되지 않은 UDP 포트에서 발견되고 있다. 이것은 111 포트가 방화벽에서 차단되어지는 것과는 별개의 문제이다. 따라서 UDP 스캐너로 30,000번 이상의 high 포트들이 listening 상태인지를 점검해봐야 한다. 이것은 루트만이 실행가능하다.6. -sAACK scan : 이 방법은 방화벽의 룰셋을 정밀하게 계획하기 위해 사용된다. 특히 방화벽이 stateful한지 아니면 단순히 들어오는 SYN 패킷을 차단하는 패킷필터인지를 점검하는데 도움이 된다. 포트에 ACK 패킷을 보내어 RST 응답을 받으면 그 포트는 unfiltered"이며, 아무런 응답이 없으면 "filtered"이다, nmap은 unfiltered" 포트는 프린트하지 않는다.7. -sWWindow scan : TCP Window 크기의 변칙 때문에 filtered/nonfiltered 뿐만 아니라 open 포트도 스캔할 수 있다는 점을 제외하면 ACK scan과 매우 유사하다.8. -sRRPC scan : 이 스캔 방법은 nmap의 다양한 포트 스캔 방법을 조합해서 이루어진다. 이것은 열려져있는 TCP/UDP 포트에 대해 그들이 RPC 포트인지, 서비스를 제공하는 프로그램은 무엇이며, 버전은 무엇인지 등을 확인하기 위해 SunRPC program NULL commands를 계속 보내게 된다. 따라서 호스트의 portmaper가 방화벽(또는 TCP wrapper)안에 있다 하더라도 rpcinfo -p'와 같은 정보를 얻을 수 있다.9. -sLList scan : 이 스캔 방법은 포트 스캐닝이나 ping 없이 호스트 네임이나 ip address를 간단히 출력한다.10. -b FTP bounce attack : 익명 FTP 서버를 이용해 그 FTP 서버를 경유해서 호스트를 스캔한다. 이를 FTP 바운스 스캔이라 한다.Scan Option{=>nmap -sS -PT -PI -p 20-30, 139, 60000- -I -T 3 61.255.3.5720에서 30사이의 포트와 139번 포트, 60000번 이상의 포트에 대해 스캔하였는데 139번 포트만이 open 되어 있다.1. -p 점검하고자 하는 포트를 지정하는 옵션이다. 예로 들면 23번 포트를 점검하려면 -p 23'하면 된다. 또한 -p 20-30, 139, 60000-'은 20에서 30사이의 포트와 139번 포트, 60000번 이상의 포트에 대해 스캔하라는 뜻이다.2. -e 네트워크의 인터페이스를 지정한다.3. -S 패킷의 source 주소를 지정한다.4. -g 패킷의 source 포트번호를 지정한다.Discover{=> nmap -sW -PT -PI -F -T 3 61.255.3.57포트가 닫혀 있다.1. -P0이것은 방화벽에 의해 ICMP echo requests (or responses)를 막아놓은 네트워크의 스캔을 가능하게 한다. pinf을 막아놓은 호스트를 스캔하기 위해서는 -P0나 -PT80을 사용해야 한다.2. -PT [portlist]어느 호스트가 살아 있는지를 알기 위해 TCP "ping"을 사용한다. 이것은 ICMP echo request 패킷을 보내고 응답을 기다리는 대신에, 네트워크에 TCP ACK를 보내어 응답이 오기를 기다린다. RST 응답이 오면 호스트는 살아있는 것이다. 이 옵션은 ping 패킷을 차단하는 네트워크나 호스트를 스캔하는 동안은 호스트가 살아 있는 것과 같다. -PT를 사용하며, 디폴트 포트는 80이다.3. -PI이 옵션은 오리지날 ping (ICMP echo request) packet을 사용한다. 이것은 살아있는 호스트를 찾으며 또한 네트워크의 subnet-directed broadcast addresses를 찾는다. 이들은 들어오는 IP 패킷을 컴퓨터의 서브넷으로 브로트캐스트하기 위한 IP 주소이다. 따라서 denial of service attacks (Smurf is the most common) 가능성이 있다면 이들은 제거되어야 한다.Option{=> nmap -sS -PT -PI -I -O -v -T 3 61.255.3.57open port 5000/tcp, 139/tcp, 445/tcp, 135/tcp, 1025/tcp를 추가 하였다. SYN stealth 스캔하는데 1초 걸렸다. 135/tcp port는 open 되었고, loc-srv를 제공한다. 139/tcp port는 netbios-ssn를 제공한다. 445/tcp port는 microsoft-ds를, 1025/tcp는 NFS-or-IIS를 5000/tcp 는 UPnP를 제공한다. 리모트 OS는 아마 Windows NT 5 Beta2 또는 Beta3, Windows Millennium Edition (Me), Win 2000, 또는 WinXP, MS Windows2000 Professional RC1/W2K Advance Server Beta3일 것이다.
인터럽트입출력을 수행하기 위해 중앙처리장치가 장치 제어기의 적절한 레지스터에 자료를 적재하면 장치 제어기는 수행할 동작을 결정하기 위해 레지스터의 내용을 조사한다. 예를 들어, 중앙처리장치의 판독 요청이라면 제어기는 장치로부터 자신의 버퍼로 자료를 전송한 후 이를 중앙처리장치에 통보한다. 이와 같은 자료의 전송은 인터럽트에 의하여 수행된다.일반적으로 사용자 프로세스의 입출력 요청도 이와 동일하게 처리하는 데 사용자 프로세스가 입출력을 요청할 때 두 가지의 경우가 가능하다. 첫째는 입출력이 시작되어 입출력이 끝난 이후 제어가 사용자 프로세스로 넘어오는 경우로 이를 동기식 입출력이라 한다. 둘째로 입출력이 끝나지 않은 상태에서 사용자 프로그램으로 제어가 넘어가는 경우로 이를 비동기식 입출력이라 한다. 따라서 비동기식 입출력은 다른 시스템 동작이 수행되는 동안에도 입출력을 계속할 수 있다.입출력 완료를 기다리는 것은 두 가지 방법이 있다. 어떤 컴퓨터는 다음 인터럽트가 발생할 때까지 중앙처리장치를 쉬게 하는 특수한 대기 명령을 가지고 있다. 그러한 명령이 없는 기계는 대기 루프로 대신할 수 있다.이 루프는 인터럽트가 발생하여 제어가 운영체제의 다른 부분으로 넘어갈 때까지 계속된다. 이와 같은 루프는 인터럽트 구조를 지원하지 않는 모든 입출력장치에 대해서 폴링하고자 할 때 필요하다. 즉, 장치에 대해 연속적인 폴링을 하는 것보다 간단히 레지스터 중 하나에 플래그를 설정하고 운영체제로 하여금 이 플로그를 인식하도록 한다.만약에 중앙처리장치가 항상 입출력 완료를 위해 대기한다면, 어느 순간이든지 수행해야할 입출력 요청은 기껏해야 하나라는 것이다. 따라서 입출력 인터럽트가 일어날 때마다 운영체제는 어느 장치가 인터럽트를 호출하고 있는지 정확히 알고 있다. 반면에 이 방법에서는 여러 장치에 대해 동시 입출력 처리를 배제하며, 또한 입출력 연산의 시간적 중복 가능성도 배제한다.보다 향상된 방법은 입출력을 시작한 즉시 사용자 프로그램에게 제어를 돌려주는 것이다. 이 때 사용자가 입출력 종료를 기다릴 수 있도록 하는 시스템 호출이 필요하다. 따라서 앞서 필요한 대기 코드가 여전히 필요하며, 동시에 많은 입출력 요청을 기억할 수 있어야 한다. 이러한 목적을 위해 운영체제는 각 입출력장치에 대한 엔트리가 들어 있는 테이블 즉, 장치 상태 테이블을 사용한다. 각 테이블 엔트리는 장치의 유형, 장치 주소와 상태를 나타낸다. 만약 장치가 요청으로 인해 바쁘다면 그 장치에 대한 테이블 엔트리에 요청의 형태와 다른 매개변수가 저장된다. 한 프로그램이 같은 장치를 여러 번 요청할 수 있기 때문에 기다리고 있는 요청들의 리스트나 체인을 가질 수 있다. 따라서 입출력장치 테이블과 더불어 운영체제는 각 장치에 대해 요청 리스트를 가질 수 있다.입출력장치는 서비스가 필요할 때 인터럽트를 발생한다. 인터럽트가 발생하면 운영체제는 우선 어떤 입출력장치가 인터럽트를 발생하였는지 조사한 수, 그 장치의 상태를 나타내는 입출력장치 테이블로 들어가서 인터럽트 발생을 나타내는 테이블 엔트리를 수정한다. 대부분장치에서 인터럽트는 입출력의 종료를 나타낸다. 만약 이 장치를 위해 기다리고 있는 추가적인 요청이 있으면, 운영체제는 요청을 처리하기 시작한다.끝으로 제어가 입출력 인터럽트로부터 복귀된다. 어떤 프로그램이 요청이 종료되기를 기다리고 있었다면, 제어를 대기 중인 프로그램에게 넘겨준다. 그렇지 않으면 입출력 인터럽트 전에 수행하고 있던 곳 즉, 사용자 프로그램의 실행 혹은 대기 루프로 제어를 다시 넘겨준다.