[yummyHitOS] 8 day (2017.07.16)

8 분 소요

우왕 우리 드디어 64bit로 진입하는거예여? 이거 레알 참트루예여? 우왕 싱기하다!!!

... 제가 이 부분에서 총 6일걸렸다는건 안비밀-☆

아니 제가말이에여 이거 정말 하... 눈물나네여 징짜... 여기서부터 제가 우분투 환경이랑 윈7 환경을 같이 시도하게 되었지요...T^T

그래서 윈7에서 안돌아가는 부분을 제가 팍팍 찝어드릴게요!! 저만 믿고 따라오세요!!



우리는 16비트 리얼 모드에서 → 32비트 보호 모드로 들어와 세그먼트 디스크립터와 세그먼트 셀렉터를 초기화 시켜주고 → 각 컨트롤 레지스터를 설정하여 페이징 활성화를 시켜주었고 → 마침내 IA-32e 모드로 전환하는 부분에 도달하였어요.

마삿카.. IA-32e 모드가 무엇인지 기억 안나시는 분이 계시다면 6일차에서 모래반지 빵야빵야랑 같이 읽어보세여!! 넘나 황당하게 간단해서 야미녀석에게 악플을 달아주실지 모르겠지만 T^T 저 야미는 이겨낼거예여!!



기부니가 넘나 좋아서 그런지 잡담이 참 길었네여... 헤헿 우리는 우선 프로세서의 제조사를 확인한대여!! 하드웨어 장비에도 명령어가 직접 들어가있나봐요!! 어셈블리어에서 cpuid 라고만 적어주면 알아서 척척 확인해주나.. 하고 봤더니 전혀 그렇지는 않네여.. 기본 CPU 프로세서 정보조회는 EAX레지스터에 0x00000000 값을 넣어서 확인하구, 확장 기능은 0x80000001이라구 하는군녀!!

참!! 언젠간 레지스터 및 어셈블리어에 대하여 포스팅을 할 계획이예여!! '언.젠.간' 이요 ^3 ^

자신의 CPU 프로세서 정보를 한 번 확인해보면 요로케 나와요.



난 AMD가 싫다!! 난 INTEL충이다!! 하시는 분들께 한가지 꿀~팁을 드릴게여!!

혹시 Nehalem Architecture 라고 들어보셨나여!? 못들어보셨다구요?! 그렇다면 Intel Core i7 CPU는 들어보셨나요?!

위키백과를 막 읽다보면.. 전력 소비량이.. 하이퍼쓰레딩이.. 모놀리딕으로 설계가.. 한 다이에 4개의 코어가..

뭐 그렇다고 하네요! 제가 이해를 못하는게 아니라 이건 이해를 하지 말라고 적혀있어서 그냥 이해하지 않았어여! 핳하핳하핳하

우리가 실행하는 Qemu 배치파일에 한 옵션만 추가해주면 INTEL이라고 뜰거예요!! 뭔가 감이 오시나요?!


-cpu Nehalem


이 옵션만 넣어주시면!! 아래와 같이 뙇!!


CPU processor


네? 옵션 넣는 방법을 모르시겠다구여? 친절한 야미는 모든 궁금증과 질문을 좋아한답니다~! 모르시다면 알려드리는게 인.지.상.정!!!



눈이 침침해진 느륵야미는 밝아야 잘 보인다고 해요. 경기도에 서식중이구요. 이 느륵야미는 잡식성 동물로 알코올을 가장 조아한다고 하는군여.

배치파일로 정의된 Qemu의 옵션에 대해 설명해드린 적이 없던 것 같네여!! 우선 우리가 쓸 옵션들만 나열해드릴게여!!


QEMU

options

-L <Path> : set Directory for the BIOS and VGA BIOS(경로 설정)

-m <Size> : set Virtual RAM Size. Default 128MB(메모리 용량 설정)

-fda <File> : use "File" Floppy disk image(파일 이미지 설정)

-localtime : set the Real Time Clock to local time(UTC로 시간 설정)

-M <Machine> : select the Emulated Machine(어느 환경에서 실행할지 설정, -M ? 을 치면 Machine List 출력)

-cpu <Model> : select CPU Model(어느 모델 환경으로 실행할지 설정, -cpu help 치면 Model List 출력)


요기까지가 저희가 사용하는 옵션이예여!! 이미지 파일 경로와, 파일과, 메모리와, 시간과, 실행 환경을 정의해 주었던 것이었네요!!

저 맨뒤에 gdb는 이따가 아래에서 설명드릴게요!! 나의 4일 밤샘을... 후... 또 눙물이 날 것만 같네여ㅠㅜㅠㅜ

(더 많은 옵션을 원하시는 분께서는 https://manpages.debian.org/jessie/qemu-system-x86/qemu-system-x86_64.1.en.html 페이지를 참고해주시면 됩니다. 검색/찾기 기능을 이용하여 필요한 옵션을 검색해 보아요! 막 hda와 같은 IDE image도 있고, 제가 쓰는 -gdb도 있고 넘나 다양한 것~~)

아하 ! 그렇다면 저기에 -cpu Nehalem이 들어가서 GenuineIntel 이라고 출력되었고, 저게 없으면 내 기본 CPU 프로세서인 AuthenticAMD가 출력되는구나 !

조흔 깨달음을 얻어갑니다 후훗...


책을 열씸히 공부하다보니... 어셈블리어 코드에 global이 나타났어여!! 어디서 많이 본 것 같지 않나요?! 객체지향을 하시는 분들께서는 public 지시어로 보셨을테고, C언어를 하시는 분들께서는 함수 바깥의 변수로 만나셨을거예요!! 이거슨 바로 전☆역☆변☆수!?

C

symbols

하.지.만 어셈블리어 global 이 친구는 그런 전역의 의미가 아닌 Export의 의미가 있다는 사아시일!!

나중에 extern도 등장하겠지만, 지금 미리 설명드리고 훅 훅 지나가버려야 똑같은 말을 빙글빙글 쳇바퀴 돌 듯 하지 않을 것 같아서 미리 말해드릴게여!


global <Symbols> : 별도의 객체 및 라이브러리 파일에 있는 기호 참조를 확인하기 위해 링커에서 사용할 수 있는 기호를 선언합니다.

extern <Symbols> : 현재 어셈블리에서 기호를 참조하는 경우에만 기호를 가져옵니다.


이말인 즉슨.. global은 사용될 함수를 내보내는 지시어이고, extern은 사용할 함수를 가져오는 지시어라는 거네요!! extern은 꼭 #include 나 import 지시어와 흡사하군요!! 이 외의 지시어나 더 궁금한 점이 있으신 분들을 위해 참조 페이지를 드릴게여!!


GNU Assembler : http://tigcc.ticalc.org/doc/gnuasm.html#SEC70

ARM : http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ik/Babcjehh.html


그런데 GNU Assembler에 설명된 것보다 ARM에 설명된 것이 좀 더 자세하더라구요.. GNU 쓰레기네!! 아닙니다 제가 감히 제 사랑스러운 C언어 관리 협회 그누님들께 무슨말씀을 그렇게 하겠습니다 핳하핳ㅎ



정말 이거 레전드인거같아여 ㅋㅋㅋ박준형 워너비 헤이 매앤!! 빼애앰!!

이제 CPU 프로세서 정보를 읽는 명령어가 지나가면 엔트리 포인트에 IA-32e 디스크립터를 작성합니다. 여기서 의미하는 Limit, Base, P, DPL 등의 필드는 여윾시 3일차에 시.공.조.아와 함께 나와있겠죠!? 까먹으셨다면 다시 복습복습!!

또한 바로 전 포스팅에서 보여주었던 리얼 모드와 보호 모드에서의 메모리 관리기법에 나타난 세그먼트 셀렉터들의 주소! 코드 세그먼트 디스크립터가 0x08 / 데이터 세그먼트 디스크립터가 0x10에 있었는데, 64bit로 전환하면서 0x18 / 0x20으로 변경되네여!! 둒흔둒흔!! 심장이..


PAE

뛰다 말았어여.. 나닛!? 물리 메모리 확장.. PAE.. Physical Address Extensions.. 기능? 머져? 오랜만에 먹는게 나왔나여? 쿰척쿰척


컴퓨팅에서 4 GB 이상의 물리 메모리를 32 비트 시스템에서 사용할 수 있도록 만들어 주는 x86, x86-64 프로세서의 기능이다. 이 기능을 사용하려면, 먼저 운영 체제에서도 지원되는지 확인해 보아야 한다.


라고 위키백과께서 설명해주시네영!! 데스크탑 PC 혹은 놋북에서는 32bit OS에서 4GB까지의 메모리가 한계이지만, 서버용 컴퓨터에서는 32bit OS여도 4GB를 넘어선 메모리가 사용이 가능하대요! 그 이유인 즉슨 이 PAE라는 이거 패 라고 읽나여? 패버릴까여? 패건들지마! 손모가지 날아가붕게! 의식의 흐름 톸톸 PAE라는 물리 메모리 확장 기법을 통해 4GB 이상의 메모리에 접근할 수 있도록 했기 때문이져!!



이 짤이 나올 줄 아셨다구여? 이제 야미의 포스팅에 적응이 되신거예여!! 나중에 야미가 만든 해킹툴 yummyKit 및 리버싱 포스팅도 재밌게 읽어주세여!!

저 PAE 녀석이 우리를 위해 메모리를 확장시켜 주어써여 ㅜㅠ 하.. 감동.. 가상머신을 원활히 돌려주시는 메모리느님이시여..

(감동 짤도 있지만 짤이 너무 마니 투척되면 이게 포스팅인지 짤방인지 모르니 자제하도록 할께여 T^T)

그렇게 물리 메모리 확장 기법에 대해 알고 넘어가니 이번엔 MSR이라는 친구를 데려오네여!?


MSR이란 Model-Specific Register 라고 불리는 특수한 용도의 레지스터래요. MSR 명령어도 존재하는데, 이 명령어는 범용레지스터의 내용을 CPSR과 SPSR로 복사해주는 명령어라고해요!

- CPSR(Current Program Status Register) : 현재의 Mode를 확인할 수 있으며 현재 CPU 상태를 알 수 있는 레지스터

- SPSR(Saved Program Status Register) : CPSR을 복사해 넣는 특수 Register. Mode 변경 시 CPSR에 백업용도로 사용


MSR 레지스터에는 6개의 종류가 있으며, MSR 레지스터용 명령어인 RDMSR(Read From Model Specific Register)과 WRMSR(Write To Model Specific Register)이 있답니다! RDMSR 명령어는 값을 읽어오고, WRMSR(Write To면 WTMSR로 할 것이지 왜 WR이야 헷갈리게..) 명령어는 값을 쓰는 역할을 하는 것쯤 딱 보자마자 아셨죠?! Read/Write가 중요한 우리에겐 이런 감각쯤 훗 가소롭네여!


이러한 과정을 통해 우리는 64bit 모드 전환에 성공하게 될 거예요!! 우와~~ 박수 쨖쨖~~ 항상 책에 자세~한 설명 써주신 한승훈 선생님께는 너무너무너무~ 너무너무너무너무너무너무~ 너어무너무 감사드려여!!(절대 아이오아이 노래랍니다!)

참! ModeSwitch.asm 파일에서 kSwitchAndExecute64bitKernel 함수에 변경된 것이 있더라구여!


; CR4 컨트롤 레지스터 부분

or eax, 0x20 → or eax, 0x620

(PAE비트와 OSXMMEXCPT비트, OSFXSR비트를 모두 1로 설정한다고 합니다.)


; IA32_EFER.LME 설정 부분

or eax, 0x0100 → or eax, 0x0101

(LME비트와 추가적으로 SCE비트도 1로 설정한다고 해요.)


; CR0 컨트롤 레지스터 부분

or eax, 0xE0000000 → or eax, 0xE0000000E

(NW, CD, PG비트와 더불어 TS, EM, MP비트도 1로 설정한대요.)


xor eax, 0x60000000 → xor eax, 0x60000004

(NW, CD비트 외에도 EM비트까지 0으로 설정한답니다.)


이렇게 4가지 부분의 값이 변경되었네요! 괄호 속 설명이 다 똑같은 이야긴데 각기 다른 부사어가 쓰였네여! 제가 쓰면서도 스스로 참 자랑스러웠습니다 핳하핳 넘나 병맛스럽꾼여..


이제 64bit용 커널을 준비하여 C커널로 쩜핑쩜핑 해볼 차례예요!!

아까 설명드렸던 extern 지시어가 여기서 나오는 거였네요! 전 또 아주 나~중에 나오는건쥴...

오랜만에 32비트 링커 스크립트 이후로 링커 스크립트를 수정하는 부분이 나오는군요!! 좌측 제 소개 부분에 GitHub 이라는 문구를 못찾으시겠다면 !! yummyHit's Github 에 가시면 소스코드가 전부 있답니다!!


그리고 저번 ImageMaker.c 소스코드 작성시 제가 O_BINARY에 대해 불평불만을 토로했었잖아요? 이 부분을 ImageMaker.c 소스코드 맨 위에


#define BINARY 0x10000

(윈도우 환경에서 하시는 분들만 해당되어요!! Ubuntu는 추가하면 make가 255오류를 낸다구요!!)


으로 선언해주시고, 각 open() 함수 4개를 아래와 같이 재수정해주세여! 귀찮게 해드려서 죄송합니다... 다 이런 이유가...


open("Disk.img", O_RDWR | O_CREAT | O_TRUNC | BINARY, S_IREAD | S_IWRITE)
open(argv[1], O_RDONLY | BINARY)
open(argv[2], O_RDONLY | BINARY)
open(argv[3], O_RDONLY | BINARY)


요로코롬 수정해 주신 후 책의 코드를 그대~로 적어 빌드 후 실행하면!! 응? 왜 64bit 전환도 된다면서 64bit용 C언어 커널이 안뜨지..? 무엇이 문제일까여?

Small talk

드디어 설욕을 풀 때가 되었네여..ㅜㅠㅜㅠㅜ 하 제가 4일동안 밤새면서 윈도우 7에서 빌드하려고 얼마나 디버깅을 했던지.. 저의 흔적..☆



제가 사진을 다올리려고하니 이렇게 많은 캡쳐를 떠놓은줄은... 위 사진 두 장으로 압축하였지만, 첫 번째 사진은 좌측에 우분투, 우측에 윈도우를 양쪽으로(맥뿍의 갓러럴즈님이 선사해주신 선물~)두고 디버깅한 스크린샷!! 두 번째 사진은 좌측에 윈도우 원격 디버깅, 우측에 우분투 원격 디버깅 스크린샷!!

이게 우분투에서는 잘 돌아가는데 윈도우에서는 안되더라구요!

4일간의 일대기를 10가지로 압축해서 써드릴게여!! 재미는 없겠지만 ㅜㅠ 전 정말 고되었어용... 한 번만 읽어주십사 하고 적어보겠습니다!!


1. 먼저 Qemu에서 Ctrl+Alt+2 를 누르면 디버깅모드로 전환!(윈도우 Qemu는 메뉴표시줄에서 View → Compatmonitor0 클릭가능) 처음 접근은 임의의 0x10000부터.. 값이 달라질 때까지를 지켜보았다. 그 결과 0x10a18까지는 같고 그 이후가 다른 점을 캐치!


2. Page.c 소스파일에서 0x101000, 0x102000에 각 엔트리 테이블을 넣길래 확인해보니 두 운영체제에서 값이 같았음. 그래서 혹시 64bit 모드로 점프하는 0x200000부분을 확인하니 0x200018까지는 같고 그 이후가 다른 점을 캐치!


3. 나닛 1번과 2번을 확인하니 이거 이거 이미지 복사하는데서 문제있는게 아니네!? 애초에 값이 이상하게 들어가네?!(이렇게 생각하게 된 계기는 0x200018 이후의 값과 0x10a18 이후의 값이 두 운영체제에서 똑~같더라구요! 이미지 복사는 잘 되었다는 이야기죠!) 윈도우는 0x202634에서 값이 끊기구 우분투는 0x204a34에서 값이 끊기더라구여? 왜지? 왜 0x2400만큼 크기가 차이나지!?


4. 이 부분에서 gdb와 연동하는 법을 알아냈씁니다!! 항상 우분투를 즐겨 쓰고 objdump와 gdb를 이용해 디버깅하던 야미는 Qemu 배치파일의 옵션에 -gdb tcp::Port 을 주면 gdb에서 set architecture i386:x86-64 로 환경설정을 세팅한 후 target remote IP::Port 로 원격 디버깅이 가능하다는 것!!


5. 쓰던 gdb로 확인하니 딱 감이 왔어여! 먼저 64bit 엔트리 포인트에서 call Main하기 전, jmp $ 무한루프를 걸어 확인해보니 어라? 각 레지스터의 모든 값이 똑같아여!! 리상하죠?! 아까 전의 0x200018 이후 부분 외엔 다 똑같네여!? 그렇다면 처음부터 봐야겠죠?!

(야미는 여기까지 이틀, 여기서부터 이틀이 걸렸어요.. Qemu 디버깅에선 되지 않던 명령어들이 할 줄 아는 gdb에서 돌아간다닛... 넘나 씽나서 값 변조도 시켜보고, 소스코드의 주소값을 맘대로 넣어보고, 어셈블리어의 세그먼트 레지스터들을 마구 변조시켜보았지만... 결쿡 모든것이 실패하였죠 눙물..ㅜㅠㅜ)


6. 부트로더 어셈블리어 파일부터 값이 다르게 들어가더라구요?! 소스파일을 보면 처음에 점프를 0x07C0으로 해서 START를 실행시키는데, 이 START에서 DS 레지스터에 0x07C0을 넣어주고, SS 레지스터에 0x0000, SP와 BP는 0xFFFE로 초기화시켜주는데 이게 우분투에선 레지스터값에 저장이 안되고 윈도우에선 곧이 곧대로 저장되는 것이었어요! 흠.. 그럼 당연히 윈도우는 되고 우분투가 안되어야 하는게 아닌가!? 싶더라구요.. 그래서 아까 ImageMaker.c 와 kSwitchAndExecute64bitKernel 함수를 수정했었던 것이예여! 이것때문인가 하구...


7. 혹시나 해서 vi편집기를 통해 xxd 명령으로 Hex Editor를 보았는데, Disk.img 자체의 구조가 다르더라구여! 당연하겠죠.. 아까부터 값이 다른 부분들이 마구잡이로 생겨났으니.. 이에 화가난 야미는 윈도우 7 64bit, 윈도우 xp, 우분투 32bit에서 실행환경을 똑같이 하여 실행해본 결과, 윈도우는 전부 실행이 안되고 우분투는 gcc-multilib 패키지덕에 전부 실행이 잘되더군여!! 아 여윾시 리눅스 갓발즈님의 리눅스가 최고라고 생각하던 찰나..


8. 혹시 우분투의 Disk.img 파일을 윈도우로 옮기면 잘 실행되지 않을까..? 하여 해보았더니 더 에러나더라구여? 당연하겠죠... 링커 스크립트에서 Path 부분부터 틀리기 때문에 bin파일도 다르겠죠...


9. 결국 야미는 한승훈 선생님의 가상환경 이미지파일을 다운로드 받아 실행했습니다. 넘나 잘되는 것~(가상머신 이미지 파일 : http://jsandroidapp.cafe24.com/xe/8920) 그렇다면 이곳의 실행환경에 맞춰 내 소스파일을 실행시키면 실행이 될까..? 오오... 넘나 잘되는군여...


10. 결국 결론이 났어요ㅜㅠ 아 참 과정에서 빼먹은게 gcc downgrade 도 해봤구, nasm downgrade 도 해봤는데 전혀 효과가 없었어여... 왜 Qemu Downgrade를 생각하지 못했을까!! 끄아!!!(URL : https://qemu.weilnetz.de/w32/2013/) Qemu 윈도우 32bit 버젼에서 2013년 11월 28일 버젼으로 받으시면 될 거예요!!


네.. 그렇습니다... Qemu를 2013년 11월 28일 버젼 그 이전의 버젼으로 실행해야 잘 돌아가더라구요... 윈도우에서는.. 이런것도 모르고 저는 그렇게 이짓 저짓 삽질을 4일밤새 하였어여 T^T

그래도 전 긍정긍정왕이라!! 해결한 것 하나만으로 족해여!! 하.. 드디어 이 일대기를 쓰게되었다니 행벅하네영.. 넘나 이야기하고싶던 것..

행복함을 느끼기위해 아까 던지려다 못던진 짤을 던질게여! 이럅!! 우리 이제 64bit 환경에서 이것 저것 해보아요!! 넘나 행복에 자아도취 되어있다보니 시간이 벌써... 오늘도 저는 7시간에 걸친 포스팅을... 이거 글쓰는거 시간 엄청잡아먹어요!! 시간없으신분들은 주의해주세요 꺌꺌~



Check out the yummyhit’s website for more info on who am i. If you have questions, you can ask them on E-mail.

카테고리:

업데이트:

댓글남기기