1. OSI 7계층



- 응용프로그램 계층 (Application Layer) 

사용자가 네트워크에 접근할 수 있도록 해주는 계층. 사용자 인터페이스, 전자우편, 데이터베이스 관리 등 서비스를 제공한다.

- 표현 계층 (Presentation Layer)

운영체제의 한 부분으로 입력 또는 출력되는 데이터를 하나의 표현 형태로 변환한다. 필요한 번역을 수행하여 두 장치가 일관되게 전송 데이터를 서로 이해할 수 있도록 한다.

- 세션 계층 (Session Layer)

통신 세션을 구성하는 계층으로, 포트 연결이라고도 할 수 있다. 통신장치 간의 상호작용을 설정하고 유지하며 동기화한다.

- 전송 계층 (Transport Layer)

전체 메시지를 발신지 대 목적지(종단 대 종단)간 제어와 에러를 관리한다. 패킷들의 전송이 유효한지 확인하고 실패한 패킷은 다시 보내는 등 신뢰성 있는 통신을 보장하며, 머리말에는 세그먼트가 포함된다.

- 네트워크 계층 (Network Layer)

다중 네트워크 링크에서 패킷을 발신지로부터 목적지로 전달할 책임을 갖는다. 2계층은 노드 대 노드 전달을 감독하는 것이고 3계층은 각 패킷이 시작 시점에서 최종 목적지까지 성공적이고 효과적으로 전달되도록 한다.

- 데이터 링크 계층 (Data Link Layer)

오류없이 한 장치에서 다른 장치로 프레임을 전달하는 역할. 스위치 같은 장비의 경우 MAC 주소를 이용하여 정확한 장치로 정보 전달. 3계층에서 정보를 받아 주소와 제어정보를 시작(헤더)와 끝(테일)에 추가

- 물리 계층 (Physical Layer)

물리적 매체를 통해 비트흐름을 전송하기 위해 요구되는 기능들을 조정. 케이블, 연결 장치 등과 같은 기본적인 물리적 연결기의 전기적 명세를 정하고 네트워크의 두 노드를 물리적으로 연결시켜주는 신호방식을 다룸


* 물리 계층 (Physical Layer)



- 기능 : 전기적, 기계적 특성을 이용하여 통신 케이블로 전기적 신호를 전송한다.

- 비트, 1/0의 인코딩 전압 및 케이블 사양 핀의 수 등을 정의한 계층이다.

- 단지 데이터 전달의 역할을 한다.

- 1계층의 장비로는 케이블, 리피터, 허브가 있다.


* 데이터 링크 계층 (Dtat-Link Layer)

- 기능 : 물리적인 연결을 통하여 인접한 두 장치간의 신뢰성 있는 정보 전송을 담당한다.

- 프레임은 2계층에서의 전송단위이며, 주소와 제어정보를 가지고 있다.

- 정보의 오류와 흐름을 관리하여 안정된 정보를 전달한다.

- 2계층 장비로는 비리지와 스위치가 있다.


* 네트워크 계층 (Network Layer)



- 기능 : 중계 노드를 통하여 전송하는 경우 어떻게 중계할 것인가를 규정한다.

- 패킷은 3계층 전송단위이며, 패킷을 목적지까지 경로 설정을 한다.

- 데이터를 목적지까지 가장 안전하고 빠르게 전달하도록 한다. 이것을 라우팅이라 한다.

- 3계층 장비는 라우터와 L3 스위치가 있다.


* 전송 계층 (Transport Layer)


- 기능 : 종단 간(End-to-End)에 신뢰성 있고 정확한 데이터 전송을 담당한다.

- 4계층에서 전송되는 단위는 세그먼트이며, 종단 간의 에러복구와 흐름제어를 담당한다.

- 4계층 장비로 L4 스위치를 두는 경우가 있는데, 3계층에서 온 트래픽을 분석하여 서비스 종류를 구분해주는 역할을 한다.


* 세션 계층 (Session Layer)



- 기능 : 통신장치 간 상호작용 및 동기화를 제공한다.

- 연결 세션에서 데이터 교환과 에러 발생 시의 복구를 관리한다. 즉, 논리적 연결을 담당한다.

- 포트를 생각할 수 있으나, 4계층과 5계층의 경계 사이의 모호한 위치이다.


* 표현 계층 (Presentation Layer)


- 기능 : 데이터 표현에 차이가 있는 응용처리에서의 제어 구조를 제공한다.

- 데이터 표현의 차이란 ASCII, JPEG, MPEG 등의 번역을 말한다.

- 전송하는 데이터의 인코딩, 암호화, 코드 변환 등을 수행한다.


* 응용 계층 (Application Layer)


- 기능 : 응용 프로세스 간의 정보 교환

- 사용자와 가장 밀접한 계층이며, 인터페이스 역할을 한다.


* 데이터 패킷 구성



Application 계층에서 데이터를 생성해 Transport 계층으로 보낸다. 이때 데이터를 자르고(Segmentation) 각 데이터 앞에 TCP 헤더를 붙여 네트워크 계층에 보낸다. 네트워크 계층에서는 각 패킷에 앞에 출발지 주소와 목적지 주소에 대한 정보 등을 앞에 붙인다(IP 헤더). 그리고 데이터 링크 계층으로 보내며 이 계층에서는 MAC 주소를 앞에, CRC 코드를 뒤에 붙여 물리계층으로 보낸다.

MAC 주소는 다음에 보낼 곳(라우터) 의 주소를 갖는다. CRC 코드는 데이터에 문제가 있는지를 판단하는 코드이다.



Posted by Imp3rio

파이썬은 1991년 프로그래머인 귀도 반 로섬이 발표한 고급 프로그래밍 언어로, 플랫폼 독립적이며 인터프리터식, 객체지향적, 동적 타이핑 대화형 언어이다.

파이썬은 비영리의 파이썬 소프트웨어 재단이 관리하는 개방형, 공동체 기반 개발 모델을 가지고 있다. C언어로 구현된 C파이썬 구현이 사실상의 표준이다.


1. 개요

파이썬은 초보자부터 전문가까지 사용자층을 보유하고 있다. 동적 타이핑 범용 프로그래밍 언어로, 펄 및 루비와 자주 비교된다. 다양한 플랫폼에서 쓸 수 있고, 라이브러리(모듈)가 풍부하여, 대학을 비롯한 여러 교육 기관, 연구 기관 및 산업계에서 이용이 증가하고 있다. 또 파이썬은 순수한 프로그램 언어로서의 기능 외에도 다른 언어로 쓰인 모듈들을 연결하는 풀언어(glue language)로써 자주 이용된다. 실제 파이썬은 많은 상용 프로그램에서 스크립트 언어로 채용되고 있다. 도움말 문서도 정리가 잘 되어 있으며, 유니코드 문자열을 지원해서 다양한 언어의 문자 처리에도 능하다.


2. 특징

- 파이썬은 인간다운 언어이다.

프로그래밍이란 이낙ㄴ이 생각하는 것을 컴퓨터에 지시하는 행위라고 할 수 있다. 파이썬은 사람이 생각하는 방식을 그대로 표현할 수 있는 언어이다. 따라서 프로그래머는 굳이 컴퓨터의 사고 체계에 맞추어서 프로그래밍을 하려고 애쓸 필요가 없다.


- 파이썬은 문법이 쉬워 빠르게 배울 수 있다.

파이썬은 문법 자체가 아주 쉽고 간결하며 사람의 사고 체계와 매우 닮아 있다. 유명한 프로그래머인 에릭 레이먼드(Eric Raymond)는 파이썬을 공부한 지 단 하루 만에 자신이 원하는 프로그램을 작성할 수 있었다고 한다.


- 파이썬은 무료이지만 강력하다

오픈 소스인 파이썬은 당연히 무료이다. 사용료 걱정없이 언제 어디서든 파이썬을 다운로드하여 사용할 수 있다.

또한 프로그래머는 만들고자 하는 프로그램의 대부분을 파이썬으로 만들 수 있다. 물론 시스템 프로그래밍이나 하드웨어 제어와 같은 매우 복잡하고 반복 연산이 많은 프로그램은 파이썬과 어울리지 않는다. 하지만 파이썬은 이러한 약점을 극복할 수 있게끔 다른 언어로 만든 프로그램을 파이썬 프로그램에 포함시킬 수 있다.

파이썬과 C는 찰떡궁합이란 말이 있다. 즉, 프로그램의 전반적인 뼈대는 파이썬으로 만들고, 빠른 실행 속도를 필요로 하는 부분은 C로 만들어서 파이썬 프로그램 안에 포함시키는 것이다.


- 파이썬은 간결하다

귀도는 파이썬을 의도적으로 간결하게 만들었다. 만약 펄(Perl)과 같은 프로그래밍 언어가 100가지 방법으로 하나의 일을 처리할 수 있다면 파이썬은 가장 좋은 방법 1가지만 이용하는 것을 선호한다. 이 간결함의 철학은 파이썬 문법에도 그대로 적용되어 파이썬 프로그래밍을 하는 사람들은 잘 정리되어 있는 소스 코드를 볼 수 있다. 다른 사람이 작업한 소스 코드도 한눈에 들어와 이해하기 쉽기 때문에 공동 작업과 유지 보수가 아주 쉽고 편하다.



Posted by Imp3rio

다음 어셈블리 코드를 한줄씩 살펴보고 C코드를 추측해본다.

 

1.

 

- push ebp, mov ebp, esp : 이 부분은 Prolog 영역으로 스택프레임을 생성하는 부분이다.

- sub esp, 0x14 : esp가 가리키는 주소를 0x14 만큼 뺌으로써 스택 사용을 준비한다.

- mov DWORD PTR [ebp-0x4], 0xa : ebp가 가리키는 주소로부터 0x4만큼 떨어진 곳에 0xa를 저장

- mov DWORD PTR [ebp-0x8], 0x14 : ebp가 가리키는 주소로부터 0x8만큼 떨어진 곳에 0x14를 저장

- mov DWORD PTR [ebp-0xc], 0x0 : ebp가 가리키는 주소로부터 0xc만큼 떨어진 곳에 0x0을 저장

- mov eax, DWORD PTR [ebp-0x8] : eax레지스터에 ebp-0x8 주소에 저장된 데이터를 복사

- mov edx, DWORD PTR [ebp-0x4] : edx레지스터에 ebp-0x4 주소에 저장된 데이터를 복사

- add eax, edx : eax레지스터에 eax에 저장된 데이터와 edx에 저장된 데이터의 합을 저장

- mov DWORD PTR [ebp-oxc], eax : eax에 저장된 데이터를 ebp-oxc 주소에 복사

- mov eax, DWORD PTR [ebp-0xc] : ebp-0xc 주소에 저장된 데이터를 eax에 복사

- mov DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax에 저장된 데이터를 복사

- mov DWORD PTR [esp], 0x80484f0 : esp가 가리키는 주소에 0x80484f0을 복사

- call 0x80482f0 <printf@plt> : 0x80482f0 주소를 호출하며 해당 주소는 printf 함수이다.

- leave : leave는 move esp, ebp; pop ebp의 두 명령어를 하나의 어셈블리어로 합친 것이다.

- ret : ret는 pop eip 를 수행하며 이전의 함수로 돌아간다.

 

위 어셈블리 코드를 보면 4바이트 데이터 3개를 스택에 저장(<+6>, <+13>, <+20>)하며 printf 함수를 호출(<+52>)하는 것을 알 수 있다.

이를 바탕으로 C코드를 추측해 보면 다음과 같다.

 

int main()

{

int a = 10, b = 20, c;

c = a + b;

printf("%d", c);

return 0;

}

 

2.

 

- and esp, 0xfffffff0 : esp레지스터를 최적화 하는 코드

- sub esp, 0x20 : esp가 가리키는 주소를 0x20만큼 빼 스택을 준비한다.

- mov DWORD PTR [esp+0x1c], 0x0 : esp+0x1c 주소에 0을 저장

- jmp 0x8048450 <main+51> : 0x8048450 주소로 점프

- cmp DWORD PTR [esp+0x1c], 0x2 : esp+0x1c 주소에 저장된 데이터와 0x2와 비교

- jne 0x804844b <main+46> : esp+0x1c 주소에 저장된 데이터와 0x2가 같지 않으면 0x804844b 주소로 점프

- mov eax, DWORD PTR [esp+0x1c] : eax레지스터에 esp+0x1c 주소에 저장된 데이터를 복사

- mov DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax레지스터에 저장된 데이터를 복사

- mov DWORD PTR [esp], 0x80484f0 : esp레즈서터가 가리키는 주소에 0x80484f0를 복사

- call 0x80482f0 <printf@plt> : 0x80482f0 주소를 호출하며 해당 주소는 printf()함수의 주소이다.

- add DWORD PTR [esp+0x1c], 0x1 : esp+0x1c 주소에 저장된 데이터에 1을 더함

- cmp DWORD PTR [esp+0x1c], 0x4 : esp+0x1c 주소에 저장된 데이터와 0x4를 비교

- jle 0x8048430 <main+19> : 비교 결과 esp+0x1c가 0x4보다 작거나 같으면 0x8048430 주소로 점프

- mov eax, 0x0 : eax 레지스터 초기화

 

위 어셈블리 코드를 보면 데이터를 비교하여 되돌아가는(<+51> <+56>) 부분이 반복되는 것을 알 수 있으며 데이터를 비교하여 처리하는(<+19> <+24) 부분이 있는 것을 알 수 있다.

이를 바탕으로 C코드를 추측해 보면 다음과 같다.

 

int main()

{

int i;

for( i = 0; i < 5; i++ )

{

if( i == 2 )

printf("%d", i);

}

return 0;

}

 

3.

- sub esp, 0x20 : esp가 가리카는 주소를 0x20만큼 빼 스택을 준비

- mov DWORD PTR [esp+0x18], 0xa : esp+0x18 주소에 0xa를 저장

- mov DWORD PTR [esp+0x1c], 0x14 : esp+0x1c 주소에 0x14를 저장

- mov eax, DWORD PTR [esp+0x1c] : eax에 esp+0x1c에 저장된 데이터를 복사

- DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax에 저장된 데이터를 복사

- mov eax, DWORD PTR [esp+0x18] : eax에 esp+0x18에 저장된 데이터를 복사

- mov DWORD PTR [esp], eax : esp가 가리키는 주소에 eax 데이터를 저장

- call 0x804841d <addVal> : 0x804841d 주소를 호출하며 addVal() 함수의 주소이다.

- mov DWORD PTR [esp+0x4], eax : addVal() 함수의 리턴값을 가진 eax의 데이터를 esp+0x4 주소에 복사

- mov DWORD PTR [esp], 0x8048500 : esp가 가리키는 주소에 0x8048500을 저장

- call 0x80482f0 <print@plt> : 0x80482f0 주소를 호출하며 printf() 함수의 주소이다.

 

- mov eax, DWORD PTR [ebp+0xc] : eax 레지스터에 ebp+0xc에 저장된 데이터를 복사( 첫번째 인자)

- mov edx, DWORD PTR [ebp+0x8] : edx 레지스터에 ebp+0x8에 저장된 데이터를 복사( 두번째 인자)

- add eax, edx : eax에 저장된 값과 edx에 저장된 값을 더해 eax에 저장

- pop ebp : 함수 종료

 

위 2개의 어셈블리 코드를 바탕으로 C코드를 추측해보면 다음과 같다.

 

#include <stdio.h>

 

int addVal(int a, int b);

 

int main()

{

int a = 10, b = 20, c = 0;

c = addVal(a, b);

printf("%d", c);

 

return 0;

}

 

int addVal(int a, int b)

{

return a + b;

}

Posted by Imp3rio