시스템 공부에 들어서면서
바이너리 분석에 들어가 볼 것이다.

* 바이너리(실행파일)란?
 - 우리가 흔히 보는 윈도우즈의 .exe 확장자의 실행파일이라고 생각하면 된다.
 - 0과 1로 되어있는 기계어로 번역되있는 파일이다.

이 바이너리분석을 하기 위해서는 실행 파일이 어떻게 만들어지는지 공부할 필요가 있다.
즉,
다시말하면
프로그래밍된 코드가 어떻게 기계어로 번역되는지 이런 과정을 크게 Compile이라고 한다.
이 Compile 과정에 대해 알아보겠다.
우리는 C언어로 작성된 코드가 실행파일이 되는 과정을 살펴볼 것이다.

먼저! 간단하게 C코드를 작성한다. 



(sample.c 작성)



* gcc는 확장자를 보기 때문에 파일 이름 뒤에 .c를 붙여줘야한다.

만든 후 gcc를 이용해 컴파일을 해볼 것이다. gcc는 GNU C Compiler의 약자로 리눅스에서 제공하는 컴파일러이다.
아래처럼 컴파일 해본다.



(컴파일)



컴파일 완료되면 위와 같이 실행파일이 생성된것을 확인 해 볼 수 있다.
또 이 실행파일을 실행시키면 우리가 작성한 대로 Hello World 문구가 나오는 것을 확인 할 수 있다.

이 실행파일은 바이너리로 되어있기 때문에 vi 편집기 혹은 cat으로 볼 수 없고
헥스값을 볼 수 있는 xxd 데몬을 이용해서 볼 수 있다.



(바이너리 파일)



* gcc 뒤에 -o 옵션을 주어 우리가 원하는 파일이름으로 컴파일하여 실행파일을 만들 수 있다.



(-o 옵션)



* gcc 뒤에 -v 옵션을 주면 컴파일 과정이 화면에 그대로 출력된다.
우리는 gcc -v 옵션을 주어 컴파일이 이루어지는 과정을 그대로 살펴볼 것이다.



(-v 옵션)



위 화면을 보면 컴파일 과정이 주르르륵 나온 것을 볼 수 있다.
하나하나 과정을 짚어가며 살펴보겠다.

* 컴파일 과정

(1) 전처리 과정 : 컴파일 중 가장 먼저 이뤄지는 작업으로 매크로, #include 문장 해석을 한다.
전처리 : precompile


출력 화면에 해당하는 문구

 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cpp -lang-c -v -undef -D__GNUC__=2 -D__GNUC_MINOR__=91 -D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__i386__ -D__linux__ -D__unix -D__i386 -D__linux -Asystem(posix) -Asystem(unix) -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -D__tune_i386__ sample.c /tmp/ccmsu4yd.i



cpp -> 전처리기이다. 즉 cpp명령이 보이고 뒤에 -어쩌구들 해서 많은 옵션들이 보인다. 뒤에


sample.c /tmp/ccmsu4yd.i 이 보이는데 sample.c를 임시디렉터리에 .i파일을 만드는 과정이다.


하지만 /tmp 디렉토리에 들어가면 .i 파일을 확인할 수 없는데 그 이유는 컴파일이 끝나면 삭제시키기 때문이다. 우리는 이 파일들을 보면서 확인할 것이므로 이러한 파일들이 삭제되지 않는 추가적인 옵션을 주어야한다.

-save-temps 옵션을 주어 임시파일 .i 파일을 삭제 하지 않게 하겠다.



(-save-temps 옵션)



옵션을 추가하니 여러 부산(?)물들 파일이 생긴것을 확인 할 수 있다.

우리가 먼저 확인해볼 것은 sample.i (전처리 과정에서 생기는 파일) 이다.!



(sample.i 파일)



큰 변화가 없어보인다?...

전처리 과정에서 어떤 일이 일어나는지 직접 눈으로 확인해보기 위해 c코드를 조금 수정해보겠다.!
define문장을 추가해보자!



(define 문장 추가)




다시 컴파일 하겠다!




(재컴파일)



재컴파일 후
sample.i 파일을 확인해본다.



(sample.i 파일)



- define 문장이 사라지고 소스코드 안에 썻던 define이 100(우리가 설정했던 값)
으로 모두 치환되어 있는 것을 확인 할 수 있다.
-> 바로 이게 전처리기의 역할이다.

2. 어셈블 과정 : 전처리된 파일을 어셈블리 형태로 변환

해당 문구

 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/cc1 /tmp/ccmsu4yd.i -quiet -dumpbase sample.c -version -o /tmp/cc0q9vPg.s


.i 파일을 .s 파일로 바꿔준다. 이때 어셈블(기계어)형태로 바꿔준다.

왜 기계어라고 해도 무관하냐면 어셈블언어와 기계어가 1:1로 매칭되기 때문에 어셈블언어를 기계어라고도 한다. 즉 바이너리로 바꾸기 직전의 파일 .s 파일을 만들어준다.



(sample.s 파일)



sample.s 파일을 확인해보면 어셈블 언어로 바뀐것을 확인할 수 있다.

3. 컴파일 과정 : 어셈블 파일을 기계어(숫자)로 번역하는 과정이다. 정확히말하면 컴파일 과정은 이부분이지만 크게 말해 이 모든 과정을 컴파일이라고 통상적으로 말하곤 한다.

해당문구

as -V -Qy -o /tmp/ccs3N70j.o /tmp/cc0q9vPg.s


as : 어셈블러를 뜻한다. 즉 as 명령으로 -o옵션으로 .s파일을 .o 파일로 만든다.
.o 파일 (기계어로 뽑아낸 파일, 오브젝트 파일)



(sample.o 파일)



파일을 보면 이제부터는 vi 편집기로 볼 수 없다. 이제부터는 바이너리이기 때문에 xxd 혹은 objdump 등 바이너리를 다루는 도구를 통해 봐야한다. objdump를 이용해 확인해보겠다.



(sample.o 파일 확인)



파일을 보면 .s 파일에서 봤던 어셈블 언어가 모두 바이너리로 바뀐것을 확인 할 수 있다.

4. 링크 단계 : 완벽한 실행파일을 생성한다. 이 때 필요한 라이브러리를 모두 합친다.

해당 문구

 /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66 -L/usr/i386-redhat-linux/lib /tmp/ccs3N70j.o -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/crtend.o /usr/lib/crtn.o


: 오브젝트 파일과 라이브러리 오브젝트를 전부 합쳐서 하나의 실행파일로 만든다.



(a.out 파일 확인)




그렇다면 a.out 파일을 확인해보겠다.




(a.out 바이너리)



파일을 보면 왼쪽에는 메모리 주소인데 파일내용에서 해당 내용을 찾으려면(보통 파일구조 그대로 메모리로 올라가기 때문에) 대략 뒤 3자리를 참조하면된다. (항상 그런것은 아니다.)
확인해보면 3d0의 위치를 보자 



(3d0 위치)



3d0 위치에 우리가 확인했던 바이너리 문자를 볼 수 있다.

* 어셈블 언어로 코드를 작성해보고 컴파일 해보자!
Hellow World 를 출력하는 실행파일을 만들것이다. :)
nasm을 이용할 것이다! 그러기위해 .asm 확장자로 작성한다.



(sample.asm 파일 작성)




(sample.asm 내용)



컴파일 과정에서 어셈블 언어로 바꾸는 과정까지 우리가 직접 한 셈이다.
그러니 그 후 나머지 작업만 해주면 된다.

먼저 오브젝트 파일을 생성해야한다.(바이너리로 바꿔준 파일)
nasm을 이용하여 -f옵션 파일 타입 elf 로 명시한 후 sample.asm을 입력한다.



(sample.o 파일 생성)



그 후 우리가 printf 함수를 사용했으므로 이 함수의 라이브러리를 연결해주어야한다.
바로 링크단계이다.
여기서는 간단하게 static으로 구현해 볼것이다.



(링크 작업)



링크 작업이 끝나면 실행파일이 만들어지게 된다.



(실행파일)



실행 파일이 만들어진 것을 확인 할 수 있고
실행되는 것 또한 확인 할 수 있었다.



오늘은 취약점 스캐너 툴을 이용해 볼 것이다.

* 취약점 스캐너
 - nesus scanner
  : nesus는 nesus server를 이용해 취약점을 스캔한다.
  : 여러사용자가 nesus server를 이용해 취약점을 분석할 수 있다.
  : 이제 우리는 nesus server를 리눅스에 설치할 것이다.
  : 무료로 제공되는 취약점 점검 도구중에 가장 유명하다.

Nessus 스캐너는 다른 스캐너와 조금 다르다.
Nessus 서버를 만든 후 그 서버가 스캔을 하고 호스트에 결과를 알려주는 식이다.
Nessus 서버를 다른 호스트들이 이용할 수 있다.

만들어두었던 리눅스에 Nessus 서버를 설치할 것이다.



(Nessus 서버 설치)



Nessus 서버를 실행시켜 준다.



(Nessus 서버 실행)



실행되었고 8834번 포트가 열려있는 것을 확인 할 수 있다.

호스트에서 이 서버에 접속해서 사용해야한다.
window 호스트에서
https:서버아이피:8834 로 접속한다.
안전하지 않음으로 뜨는 것은 해당 브라우저가 해당 인증서가 없기 때문에
안전하지 않다고 뜨는 것일 뿐이다.



(컨티뉴 클릭)



Continue를 클릭하고
계정을 만들어야한다.
간단하게 admin으로 설정했다.



(계정설정)



그리고 Activation Code를 받아야한다.
그러기 위해서는 등록해야한다.



(Activataion 코드 입력창)



홈페이지에 들어간다!



(Get an activation 클릭)



클릭하면 회원가입창이 나오고
회원가입을 하면
적은 email주소에 Activation 코드가 온다.
그 코드를 입력해주면 된다.



(Activation 코드 입력)



들어오면 처음 화면이 아래와 같다.
Scans, Polices 화면이 있다.



(Scans 화면)





(Policies 화면)



- Scans 에서는 스캔하는 화면이고
Policies에서는 직접 정책, 룰을 설정하는 곳이다.

Policies에서 Policy를 만들어보겠다.



(기본 정책들)



기본 룰 중 Basic Network Scan으로 클릭해서
이름 등을 설정해준다.




(TEST로 설정했다.)




(Policy 생성된 모습)



이렇게 설정된 TEST Policy로 스캔을 할 수 있다.
TEST 정책에 들어가보면
세부적인 설정을 할 수 있다.




(세부 설정 모습)



이제 스캔을 해보겠다.
New Scan을 누른다.



(New Scan)



아까 만들었던 정책을 이용해도 되고
기본적으로 설정되있던 정책을 사용해도 된다.
들어오면
스캔의 이름 타겟을 적는 페이지가 나온다.
Target에는 스캔을 할 대상을 입력하면 된다.



(스캔 입력)



Save를 누르면 스캔 목록이 나온다.
여기서 재생 버튼을 클릭하면 스캔을 시작한다.



(스캔 목록)



스캔을 하는 모습이다.
다 되면 결과가 정리되서 나오지만 실시간으로도 볼 수 있다.



(분석 화면)



취약점의 심각성정도에 따라 표시도 다르게 나온다.
치명적이거나 심각한 취약점은 표시가 되어서 나온다.



(취약점 분석 화면)



추가적인 Open Source Scanner
 - GIMP
 - SAINT
 - Nikto
이런 것들이 있다. :)




* HTTP 패킷의 구조에서
Body가 존재하면 헤더에는
content-type
content size 이 반드시 있어야한다.

HTTP 패킷을 전송해볼 것이다.

HTTP는 TCP 위에서 동작하는 것이다.
이 때 좋은 툴이 있다. NetCat이라는 프로그램이다.
이 프로그램은 TCP 통신을 하는 프로그램이다.

* NetCat
 - telnet과 유사한 프로그램
 - TCP 통신을 할 수 있는 프로그램

1. 리눅스용
 - nmap 패키지에 포함
 - ncat
 - 서버로 실행 가능
 - 클라이언트로 실행 가능

2. 윈도우즈용
 - netcat
 - nc.exe
- 내용은 리눅스용과 같다.

NetCat을 설치할 것이다.
리눅스에서 ncat은 nmap 패키지에 포함되어있으므로 nmap을 설치해준다.




(nmap 설치)



ncat의 옵션을 확인해본다.




(ncat 옵션)



ncat으로 10000번 포트를 listen 상태로 열어둔다.




(10000번 포트 개방)



호스트에서 접속을 해볼 것이다.
윈도우에서는 nc.exe로 실행한다. 뒤에 IP주소와 포트번호를 적어주면 연결이된다.



(연결된 모습)



(리눅스 모습)


텍스트를 주고받을 수 있는 모습을 볼 수 있다.

netcat으로 http 통신을 확인해볼 것이다.
* 네이버에 페이지 요청을 하는 request패킷을 전송해볼것이다!

netcat을 이용해서 아래의 패킷을 보낼것이다. \r\n   캐리지리턴이 꼭 들어가야한다.
한줄 띤것까지 복사해서 보내본다.
-----------------------
GET / HTTP/1.1
Host: www.naver.com

-----------------------



(naver.com 연결)




(http 응답)



http의 웹 코드를 받은 것을 확인할 수 있다.

이제부터 실습을 naver.com에 직접하기는 조금 그러니
http 웹 서버를 리눅스에서 설치해서 그 페이지를 대상으로 패킷을 주고받아 볼 것이다.

리눅스에서 httpd를 설치한다.



(httpd 설치된 모습)



설치된 httpd에서 기본 설정된 페이지는 /var/www/html  에 들어있다.
여기에 기본 페이지 index.html을 만들어줄것이다.



(기본페이지 경로)




(간단한 페이지 작성)



페이지까지 작성을 했으면
웹서버를 실행시켜준다.




(웹서버 실행)



이제 호스트에서 인터넷 브라우저로 접속해본다.




(실험 타겟 페이지)



페이지가 잘 나온 것을 확인할 수 있다.

ncat을 이용해서 아까와 똑같이 get요청을 하여
응답을 받아봤다. 



(응답 모습)





(와이어샤크 분석)



와이어 샤크로 본 모습도 추가했다. 위와같은 메세지를 주고받은 것을 확인 할 수 있다.


여기서 헤더에 구성을 살펴보면 헤더를 이용한 취약점을 발견할 수 있다.

* DDos
 - GET Flooding : 대량의 GET패킷을 보낸다. 서버의 부하를 높인다.
 - CC Attack
   ( CC : Cache Control )
 - GET Flooding은 CC Attack과 함께 같이 사용한다.
 헤더의 Cache-Control에 no cache 등으로 설정해서
 캐시를 쓰지 않겠다해서 서버에 부하를 더 높이기 위한 방법이다.
 

 - Slow attack
1) slowloris attack
 
 - 헤더의 끝을 포함하지 않은 상태로 요청
 - 서버에서는 헤더가 완전히 도착하지 않았다고
    간주하여 세션을 계속 열어둔 상태로 둔다.

2) slow read attack
 -> body가 있어야하기 때문에 GET으로는 못한다.
 - 메세지 Body를 이용한다.

slowloris 공격과 slow read 공격을 직접 해보겠다.

1) slowloris 공격
이 공격은 마지막 캐리지 리턴을 빼서 보내는 것이다. 그렇게 되면
서버는 아직 패킷이 다 오지 않은줄 알고 다음 패킷을 계속 기다린다.
원래 웹서버는 통신이 끝난후 바로 연결을 끊는다.(사용자가 많기 때문에)
하지만 이렇게 계속 열어두게 되면
이런 패킷들이 많다면? -> 서버는 다운될 수 밖에 없다.

파이썬으로 프로그램을 작성했다.



(slowloris 공격 코드)



코드를 보면 50초마다 fake 헤더를 보내주는데
이유는 웹서버가 기다리다가 끊으려고 할 때쯤
헤더인것처럼 하나 더 보내주면 서버는 ' 아! 아직 더 있었구나!' 하고 기다린다.
그러다 또 끊으려고 하다가 또! 아! 더있구나! 하고 이런식으로 계속 기다리게 하는것이다.

와이어샤크로 분석해보았다.




(디도스 공격 패킷)




(웹 서버 포트 창)



웹서버의 포트 상태를 확인하면 ESTABLISHED로 되어있다.
웹서버에서는 이 상태는 비정상적인 것이다. 왜냐하면 웹서버에서는 통신을 하고 바로 끊기 때문이다.
이런 상태로 계속, 여러개 수가 많아지면 웹서버는 부하가 엄청날 것이다.

2) slow read 공격
content-length 헤더를 엄청 크게 잡아준다.
그리고 body의 내용을 찔끔찔끔 보내주는 것이다.
그러면 웹서버의 입장에서는 계속 기다려줘야하는 상황이 발생한다.
이런 패킷들이 많다면
웹 서버는 다운되게 된다.
body를 포함해야하므로 post 메소드를 이용해 패킷을 전송한다.




(slow read 공격 코드)




(패킷 상태)





(공격받은 모습)



이 공격도 마찬가지로 established가 되어있음을 확인 할 수 있다.




DNS의 동작 까지 확인해보았고
오늘은
DNS 동작을 이루는 패킷이 어떻게 이루어져 있는지 분석해보겠다.

호스트의 DNS IP주소를 확인해보겠다.




(DNS 서버 주소)



164.124.101.2 로 되어있다. 아래 IP주소도 맞다.
DNS 캐시 서버이다.

이제 패킷을 덤프해서 확인해보겠다.
와이어샤크 실행
간단하게 캡쳐 필터링 룰을 설정하였다.




(캡쳐 필터링 룰 설정)



멀티캐스트를 제거하였다.
멀티캐스트와 브로드캐스트를 제거해야하는데 지금보니
위에 오타가 있었다. :)

간단한 룰을 설정해주고 naver.com에 접속하였다.
(도메인 네임을 가지고)




(naver.com 입력)



그리고 디스플레이 필터 룰을 dns 로 설정하여
dns 패킷만 확인하였다.
아래 화면에
같은 Trx Id 를 가진 패킷들을 빨간색 표시해두었다.




(DNS 패킷)



디스플레이 필터링 룰을 dns.id == 0x0e68 로 설정하여
해당 아이디의 패킷만 필터링 하였다. (보기 좋게)



(필터링 룰 적용)



이제 query (Qeustion) 패킷부터 살펴보겠다.




(Trx ID)



DNS query 패킷의 첫번째 요소는
Transaction ID 이다.
UDP 통신이기 때문에 패킷을 구별할 수 없다. 그렇기 때문에 이 ID가 존재하고
이 ID로 해당 질문에 대한 답변을 구분 한다.




(Flag)



두번 째는 Flag이다.
질문, 응답 등의 패킷 타입을 결정한다.




(Question)



Question 필드에는 물어보는 도메인 네임의 수이다.
보통 한개가 생기면 바로 물어보기 때문에
한개 이상의 패킷을 보기는 힘들다.




(나머지 필드)



나머지로 Answer , Authority, Addional 이 있다.
Answer는 질문에 대한 답이고
Authority는 그 답에대한 근거(?) 출처(?) 정도이다.
Additional은 추가적인 내용이 붙는다.

정리하자면
DNS Header
 1. transaction id (2바이트)
 2. Flag (2바이트)
 3. qeustion(2바이트)
  - 질의 갯수
 4. answer(2바이트)
 5. authority(2바이트)
 6. additional(2바이트)

이렇게 구성되어있다.
도메인 네임의 전송을 살펴보겠다.



(www.naver.com 이 담겨져 있는 모습)



살펴보면
먼저 문자의 수가 나온다. 03, 그 뒤로 www (77 77 77) 이 나온다.
그리고 다시 문자의 수 05, 그리고 naver 5글자가 나오고
마지막으로 03 , com 3글자가 나온다.




(응답 패킷)



응답 패킷을 보면
DNS 헤더의 똑같은 양식에
응답부분이 채워져서 전송되었음을 확인 할 수 있다.

그러면 위에서 작성했던 도메인 네임을 여러번 쓸까?

그렇지 않다.
패킷을 잘 보면 c0 이 보이는데
c0은 포인터라는 뜻이다.
c0 뒤에 2b는 43이라는 숫자로 DNS 헤더의 43번째에 있는 주소를 나타내는 뜻이다.



(포인터 표시)



지금까지 DNS 패킷을 분석해보았다.

이제 DNS 패킷을 조작하여 할 수 있는 공격기법을 살펴보겠다.

* DNS Spoofing
- DNS를 속이는 공격 기법
 - trx id와 포트번호를 맞춰야한다.
 - Birthday Attack(추측성 공격, trx id를 추측하는 공격기법)
 - 그래서 보통 ARP Spoofing과 함께 공격을한다. (클라이언트가 대상일때)
 - 스푸핑 환경을 만든 후에 공격을 한다.
 - 공격자와 피해자가 같은 환경에 있어야한다.


DNS Spoofing을 해볼 것이다.

우리가 작성해야할 프로그램
1. ARP spoofing (pcap library를 이용)
 1) arp cache poisoning
 * ARP request 메세지를 작성하여 스푸핑
 * 브로드 캐스팅은 사용하지 않는다
 * 유니 캐스팅을 할 수 있도록 작성
target : 192.168.3.99
 - mac : 90-9f-33-ec-cc-37
attacker : 192.168.3.100
 - mac : 90-9F-33-EC-CB-0B
게이트웨이
 00-10-f3-4e-58-40

2. DNS spoofing (pcap library를 이용)
 
0) packet forwarding
  - 자기 패킷이 아니라면 원래 목적지로 포워딩
 1) DNS Query 패킷을 모니터링
 2) 타겟 도메인(www.daum.net) 모니터링
 3) 속이려고 하는 도메인에 대한 DNS 쿼리
     패킷이 검출되면 가짜 응답을 만들어서 전송해준다.
  - 출발지 포트번호와 TRX id 정보를 알아야 한다.

먼저 ARP Spoofing도구를 만들것이다.
(이건 우리가 전에 작성했던 코드로 바로 여기서 사용하겠다.)




(ARP Spoofing 코드)



이 프로그램으로 ARP 스푸핑이 된 결과를 확인 할 수 있었다.

두번째로
DNS Spoofing을 해주는 프로그램을 만들 것이다.
우리가 ARP 스푸핑을 해서 스니핑을 할 때 포워딩 기능이 없었다.
그래서 DNS Spoofing 코드에 포워딩 기능을 추가할 것이다.

먼저 포워딩 기능 부터 구현해보겠다.

arp_cache_table 변수는
subprocess를 이용해 arp table을 받아 가지고 있는 arp table이다.
IPv4 패킷만 걸러내보겠다.




(IPv4 필터링)




(결과 화면)



끝에 2048이 16진수로 0x800이다. IPv4만 걸러낼 수 있다.

여기서 IP 주소를 보고 구별 할 것이다.

나에게 오는 것이 아닌것 그리고 브로드캐스팅 되는 것 멀티캐스팅되는것을 제외하고는
포워딩을 해줘야할 필요가 있다.
그 패킷들만 필터링 해보겠다.



(포워딩할 패킷 필터링)



자 여기까지 포워딩이 되야할 필터링을 마쳤다.
이제 ARP 스푸핑과 지금까지 작성됬던 프로그램을 동작시켜서
포워딩 해야할 패킷들이 잘 필터링 되는지 확인해 보겠다.
두개 같이 동작 시킨후
피해자가 8.8.8.8 외부 IP로 핑 메세지를 보냈다.



(결과화면)




결과 화면을 보면
99(피해자)가 보낸 핑 메세지들이 필터링 되서 내 화면에 출력되고 잇는 것을 확인할 수 있다.

이제 여기서 포워딩을 추가해주고
DNS Spoofing 프로그램을 만들어 보겠다.


저번주까지 UDP 패킷분석, 그리고 IP 패킷을 분석하였다.

오늘은 TCP 패킷을 분석해보았다.

TCP는 UDP와 달리 조금 까다로운 부분이 많았다.

포함관계를 다시 정리하자면

IP 패킷안에 TCP 혹은 UDP가 들어가는 것이다.

저번주 까지 했던 패킷을 덤프받는 프로그램에서
이제 IP헤더를 분석할 수 있었고
그에 따라
소스 IP주소와 목적지 IP주소를 파악할 수 있었으므로

조금 더 정교한 필터링을 할 수 있게 되었다.



(조건 문에 IP주소로 필터링 하는 코드)


또, IP 헤더에서 Protocol 타입을 알아낼 수 있으므로
TCP, UDP, ICMP를 구분하기로 했다.



(Protocol 필드로 구분하는 모습)


위 코드를 보면 이제 TCP 헤더를 분석해볼 것이므로
처음에 list를 이용해 16진수로 표현해보았다.




(오른쪽화면은 저번주에 만들었던 TCP 메세지전송 프로그램.)


위 화면을 보면 TCP 데이터가 나오는 것을 확인 할 수 있다.

UDP와 다른점은 UDP는 메세지 하나 보내면 끝이었는데
TCP는 그 전에 많은 패킷들이 왔다 갔다 한다.
자세한 특징은 다음에 더 알아보겠다.
우선,
TCP 패킷의 헤더를 분석하는 것이 먼저다.

우리가 덤프받은 TCP 패킷의 헤더
['0xc3', '0x29', '0xea', '0x60', '0x2a', '0x4', '0x15',
'0x1a', '0x0', '0x0', '0x0', '0x0', '0x80', '0x2', '0x20', '0x0',
 '0xd9', '0x88', '0x0', '0x0', '0x2', '0x4', '0x5', '0xb4', '0x1', '0x3',
'0x3', '0x2', '0x1', '0x1', '0x4', '0x2']

내용은 이렇다.
1. 출발지 포트번호(2바이트) : '0xc3', '0x29' = 0xc329 = 49961
2. 도착지 포트번호(2바이트) : '0xea', '0x60' = 0xea60 = 60000
3.  Sequence Number(4바이트) : '0x2a', '0x4', '0x15', '0x1a'
- 운영체제에 의하여 랜덤하게 시작된다. Session을 표현하는 고유값이다.
4. Acknowledge Number(4바이트) : '0x0', '0x0', '0x0', '0x0'
*'0x80' -> 8과 0으로 본다.
5. TCP 헤더의 길이 (4비트) -> 8 (x4) = 32바이트
6.  예약된 영역 : 0 (사용하지 않는 필드이다.)
7. Flag : '0x2' = 2 (여기서는 SYN패킷, 동기화요청)
Flag 종류
1 : FIN
2: SYN
4: RST(reset)
8: PSH(push)
16: ACK(응답)
32: URG(urgent) 
(만약 동시에 설정된다면, 예를들어 SYN과 ACK가 같이 설정되면 두개의 합이된다.)
(ex. SYN-ACK 은 18번이 된다.)

8. window size (2바이트) : '0x20', '0x0'
9. TCP의 Checksum(2바이트) : '0xd9', '0x88'
10. Urgent Pointer(2바이트) : '0x0', '0x0'
---- 여기까지 딱 20바이트다.-----------------

그 이후로 옵션이 더 붙어서 패킷이 보내질 수도 있다.

자. 그러면 이제 이 내용을 바탕으로 헤더내용을
분석하여 출력해보겠다.


(TCP 패킷 분석코드)


(TCP 헤더 분석 내용)



여기서
Header 길이를 표현하려면 아까 한 바이트를 4비트로 나누어야한다.
이제 그 작업을 시작하겠다.

0x45를 4와 5로 분리하는 것이다.
먼저 0x45를 2진수로 변환한다. (bin()함수 사용)

그 후 슬라이스로 4개씩 자르고 int로 형변환 해준다.
아래와 같다.


(분리된 모습)



이걸 이용해
IP 헤더의 버젼과 헤더길이를 나누고
TCP의 길이를 구하겠다.

또 IP헤더에서 헤더길이를 정확하게 구할 수 있고 그러면
UDP,TCP 패킷이 어디서부터 시작하는지 또한 정확하게 표현할 수 있다.

(지금까지는 그냥 IP헤더가 20바이트라고 가정하고 했었다.)




(헤더 길이를 분리하는 코드)



(UDP의 시작 슬라이스와 TCP 헤더 길이, 또 flag를 표현해 수정해주었다.)



flag를 dictionary로 정의하여 키값을 대입하면 그에 대응하는 값이 출력된다.



(결과 화면)



지금 까지 TCP패킷을 분석해보았고

IP헤더도 더 정밀하게 분석하였다.

내일은 현재 진행중인 패킷 분석 프로그램을 조금 더 수정하고
본격적으로 패킷을 확인하고 변조해 보겠다.









+ Recent posts