>

CPU에 정해진 기능을 사용하지 않고 Task Switching을 할 수도 있다.

이 방법은 Protected Mode에서 TR 레지스터와 TSS 영역 등을 세팅한 후 유저 모드인 것처럼 가장하여 IRET 명령을 통해 유저 모드의 태스크를 실행시킨다.

mov ax, UserDataSelector ; 데이터 세그먼트를 유저 모드로 지정

mov ds, ax

mov es, ax

mov fs, ax

mov gs, ax


lea esp, [PM_Start-256] ; PM_Start 이전 부분은 더이상 쓸 일이 없으므로 스택으로 쓴다.


push dword UserDataSelector ; SS

push esp    ; ESP

push dword 0x200 ; EFLAGS

push dword UserCodeSelector ; CS

lea eax, [user_process]

push eax ; EIP

iretd ; 유저 모드 태스크로 점프

이 방식은 유저모드에서 인터럽트가 걸려 커널 모드에서 인터럽트 핸들러를 수행하고 다시 유저모드 Task로 돌아가는 것처럼 흉내낸 것이다.


user_process:

mov edi, 80*2*7

push edi

lea eax, [msg_user_parameter1]

push eax

call 0x38:0

jmp $


msg_user_parameter1 db "This is User Parametr1", 0

유저 모드의 Task가 실행되면 여기부터 실행하는데 80*2*7 과 msg_user_parameter1의 주소를 인자로 넣고(스택에 PUSH) 하고 커널 모드의 함수를 호출하기 위해 '콜게이트 디스크립터'의 셀렉터인 0x38 사용하여 call 한다.


이때 콜게이트 디스크립터는 다음과 같이 설정되어있다.

descriptor7: 

dw 0

dw SysCodeSelector

db 0x02

db 0xec

db 0

db 0

그리고 디스크립터 설정 하는 부분은 다음과 같다.

xor eax, eax

lea eax, [printf]

add eax, 0x10000

mov [descriptor7], ax

shr eax,16

mov [descriptor7+6], al

mov [descriptor7+7], ah

콜게이트 디스크립터에 printf 함수(메세지를 출력하는 사용자 정의 함수) 에 대한 정보를 기입한다.

그러므로 call 0x38:0은 커널 모드 함수 printf를 호출하게 되는 것이다.


printf:

mov ebp,esp

push es

push eax

mov ax, VideoSelector

mov es, ax

mov esi, [ebp+8] ; 첫번째 인자

mov edi, [ebp+12] ; 두번째 인자


printf_loop:

mov al, byte [esi]

mov byte [es:edi], al

inc edi

mov byte [es:edi], 0x06

inc esi

inc edi

or al, al

jz printf_end

jmp printf_loop


printf_end:

pop eax

pop es

ret ; 복귀


'Study > Kenrel' 카테고리의 다른 글

a20게이트 & 페이징  (0) 2015.10.06
여러개의 Task 일때 Task Switching  (0) 2015.10.01
Protected Mode에서의 보호  (0) 2015.09.30
Task Switching in Kernel  (0) 2015.09.25
PIC 초기화  (0) 2015.09.24
Posted by Mungsul
,

[Pwnable.kr] uaf

2015. 9. 30. 20:14

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

커널에서는 유저와 커널을 구분하고 유저가 함부로 커널을 침범할 수 없도록 하고 최대한 많은 프로그램이 공평하게 원활하게 동작할 수 있도록 한다.


Limit 체크

Type 체크

특권 레벨 체크

명령 세트 체크


이러한 체크 포인트를 통해 CPU가 모든 유저 레벨의 프로그램이 잘 동작하게 만들고 원하는 결과를 얻을 수 있도록 한다.


Limit 체크 - 세그먼트 디스크립터의 G비트가 0 일때는 0~0xFFFFF까지 선택 가능이고 1일때는 0xFFF~0xFFFFFFFF 까지 선택 가능이다.

유효 Limit는 전체 세그먼트 영역의 크기에서 1바이트를 뺀 것과 같다. 만약 넘어간다면 CPU는 일반 보호 예외(#GP)를 발생시킨다.


Type 체크 - 플래그 세팅 여부에 따라 권한을 체크한다.



특권레벨 - CPU의 특권 레벨은 0 ~ 3으로 4개가 있다. 주로 0과 3 두개만 사용한다. 낮은 레벨의 Task가 높은 레벨의 Task 데이터를 참조하려고 하면 일반 보호 에러가 발생한다.


CPL(Current Privilege Level) - 현재 실행되고 있는 Task의 특권 레벨, 다른 특권 레벨의 코드 세그먼트로 넘어가면 이 값이 변경된다.

DPL(Description Privilege Level) - 세그먼트의 특권 레벨을 나타냄.

RPL(Requested Privilege Level) -  어느 레벨에서 루틴이 불러졌는지, 누가 요구했는지를 나타내는 값.


콜게이트 - 낮은 특권 레벨의 프로그램이 높은 특권 레벨의 루틴을 잠깐 사용하는 것(소프트웨어 인터럽트도 해당한다.)

GDT에 디스크립터로서 포함이 되고, 상위 특권 레벨로 통하는 창구 세그먼트의 역할을 한다.


'Study > Kenrel' 카테고리의 다른 글

여러개의 Task 일때 Task Switching  (0) 2015.10.01
유저모드 Task Switching  (0) 2015.10.01
Task Switching in Kernel  (0) 2015.09.25
PIC 초기화  (0) 2015.09.24
IDT(Interrupt Descriptor Table)  (0) 2015.09.24
Posted by Mungsul
,