Holy Hacker

초단간 커널로드 PE파일 그대로 이용하기(align의 비밀) 본문

야매!개발

초단간 커널로드 PE파일 그대로 이용하기(align의 비밀)

홀리해커 얄리얄리얄리 2017.07.10 19:59







안녕하십니까?

저는 개인적으로 chobits라는 OS를 분석하면서

굉장히 신기했던것이 말입니다.

Visual Studio C++로 컴파일 링크한

실행파일을 OS 커널 이미지로 사용하는 것이였습니다.







chobits.bin이라는 파일은

실은 실행파일입니다.

PE파일입니다.

참 신기하지 않습니까?

어떻게 PE파일을 커널파일로 바로 사용한것인지 말입니다.



이번 실험에서는

쵸비츠가 어떻게

Visual Studio에서 만든

실행파일 그자체를 어떻게

커널로 사용할 수 있는 것인지

그 비밀(?)을 알아보도록 하겠습니다.^^!!!



원래 Visual Studio를 이용해서 실행파일을 만들면...

보통 이렇게 만들어집니다.

그리고 실제 사용시 메모리에 재배치되어 사용됩니다.

그러니까..

파일상의 OFFSET(위치)와

메모리의 실제 배치되는 위치는 다르게 됩니다.





이렇게 말이죠^^!!

옆에 PE파일은

메모리에 적재되면서..

위치가 재배치 되는게 일반적인 것입니다.














일반적으로 PE파일을 사용하기 위해서는

PE 파일 Loader같은 것을 만들어서

섹션(section)별로 메모리에

재배치를 해주는 것을 해줘야 합니다.




PE파일 로더의 역할은

PE파일을 해석해서 메모리에 로딩합니다.





이런 재배치는

PE파일(실행파일)의 Header정보를 기준으로해서 이루어집니다.





위 정보들은 PE파일의

“IMAGE_NT_HEADERS”정보 중

“IMAGE_OPTIONAL_HEADER”정보입니다.

이 정보들을 이용해서

PE 로더가 PE파일을 로딩합니다.




그런데,

여리님이 2003년에 만들었던 쵸비츠

(지금 2017년이니 10년도 넘은 이야기네요;;;

세월 참 빠르네요...ㅎㅎㅎ)

을 보면, PE로더의 섹션 재배치없이도

실행이 잘되는 것이였습니다.


이게 어찌된 일이니지 확인봅시다요~!!









쵸비츠에서는 이런식으로 PE파일을 로딩합니다.


음..Image Base 0x20000에

PE파일을 적제하면 끝!!!

이게 여리님이 만들었던 쵸비츠의 커널파일로더의 역할

이였습니다.

0x20000에 쵸비츠 커널 로딩!!끝!!!










쵸비츠 커널로더 참 간단하죠?
이게 어떻게 가능한 것인지~~?????

궁금하시죠^^?










여러분 미친감자가

쵸비츠의 커널로더의 비밀을 알아냈다고 합니다.

이것 저것 엄청난 실험을 해봤다고 합니다 .



















재배치를 하지 않도록 하는 그 비밀의 키는

그것은...

“align”이였습니다.















이 놈을 “512”로 해주니까...

뭐..

파일위치와 메모리 재배치 없이 사용할 수 있는

실행파일이 만들어지는 것을 확인했습니다!!!

















Microsft MSDN에서 / ALIGN에 대한 설명입니다.

/ALIGN 옵션은 프로그램의 선형 주소 공간 내에서 각 섹션의 맞춤을 지정합니다. number 인수는 바이트 단위로 지정하며 2의 배수이어야 합니다. 기본값은 4K(4096)입니다. 링커에서는 맞춤으로 인해 잘못된 이미지가 생성되는 경우 경고를 표시합니다.

출처 : https://msdn.microsoft.com/ko-kr/library/8xx65e1y.aspx

기본값이 4K(4096byte)라고 합니다 .









알것죠^^ㅎㅎㅎ

이렇게 하면...

/align:512 로 해주면...



이렇게 되는 것입니다.

그냥 PE 파일을

Image Base 0x20000 메모리 주소에

그냥 올리면 끝!!!

ㅎㅎㅎㅎ







다음 실험은 쵸비츠(chobits)의 소스를

변경해서

“migam_os”가 나오게 한것입니다.

ㅎㅎㅎㅎ

자~~실제 잘 표시되는지도

확인해보겠습니다.(이게 별것 아니지만,

굉한것입니다.

초단간 커널로더가 가능게 해주는 기술이니 말입니다.ㅎㅎㅎ)

음...새로만든 커널을 fdd 이미지 파일에

집어 넣고

실행하는 화면입니다.^^


맨 마지막 화면에서

“migam_os”가 나올 것입니다.^^


이렇게요^^

성공!!!

























음...

align의 기본값는

4kbyte입니다.


/align 이라는 옵셥을 한번 제거해볼께요..

어떻게 되는지 확인좀 해봅시다.(진짜 4K인지 확인해보자구요)



링커에서 /align 옵션을 제거하고

만들어진 실행파일입니다.

Section Alignment는 0x1000(4096byte)이고

File Alignment는 0x200(512byte)로 되었네요.


예..../align의 기본값은 0x1000(4096byte) 맞네요!!!

(이 미친감자는 의심쟁이 ㅎㅎㅎㅎ)













“/align: 512”으로 하고 링킹을하면,

PE파일의

Section Alignment과 File Alignment의 값이

둘다 512byte가 되는 것입니다!!!










/align: 512를 해줌으로

섹션 얼라인먼트와

파일 얼라인먼트가

동일하면 되는 것입니다.















미친감자 여기서 멈추면 안되겠죠~!

/align값을 다양한 값으로 바꾸는 실험을 시작해보겠습니다.




#실험1 : 링커의 /align 값을 256byte로 바꿔보겠습니다.



자...PE파일을 확인해보겠습니다.^^

자 어떻게 값이 설정 되었을까요^^?


Sectino Alignment와 File Alignment 모두

0x100(256byte)이라는 점~~

512byte이하인 경우

둘다 같은 값이 되는 것 같네요..













그럼~

근단적인 값 한번 세팅해보겠습니다.

“1”로 해볼까요?

2의 배수가 아니니 에러가 발생하겠죠^^?

과연~~~???

자 어떻게 될까요^^???

.

.

.

.

.


에러가 발생했습니다. ^^;;;;

당연한거지~~!!!














그런데 에러메시지가 좀 이상합니다.

“오류 LNK1164 0x1 섹션 맞춤(4)이 /ALIGN 값보다 큽니다.”


섹션 맞춤이 /ALIGN 값보다 크다고????

섹션 맞춤의 값이 몇일까?


그렇다면...

/align:2로 해보겠습니다.


자 바로 빌드~~!!

.

.

.

.

.

역시 에러!!!











그렇다면

/align:4로 해보겠습니다.(2의 배수로 해야 하니^^)

자 이번에는 어떻게 될까요^^


.

.

.

.

.

?

또 에러!!!

입니다;;;;;;


그런데, 에러 문구가 틀려졌네요;;;

“오류 LNK1164 0x9 섹션 맞춤(16)이 /ALIGN 값보다 큽니다.”



섹션 맟춤(16)이라고 되어 있네요

아까는 (4)였거든요^^

음...그렇다면 이젠










/align:16으로 해보겠습니다.

ㅎㅎㅎㅎ

자 이번에는 성공할까요^^???

.

.

.



.

.

.

.

.


와우~~성공^^!!!!

/align:16으로 하니께~~

성공이네요!!!!!










/align:16이 최소로 설정할 수 있는 값일까요^^?

그렇다면

다시 실험~~!!

/align:8로 해보겠습니다.

ㅎㅎㅎㅎ

자 어떻게 될까요^^?

ㅎㅎㅎ

.

.

.

.

.

.



실패입니다.;;;







그렇다면

/align:15로도 해보겠습니다.

ㅎㅎㅎ미친감자 아닙니까^^!!!ㅎㅎㅎ

자..어떻게 될까요^^?.

.

.

.

.

..

.


ㅋㅋㅎㅎㅎ당연히 에러겄죠^^ㅎㅎㅎ

.

.

.

.

.

.


허거덕;;;;;성공입니다;;;;;;;;

/align:15인데;;;말입니다.;;;;허거덕;;;;

(2의 배수로 설정해야 한다고 했는데)

뭐지???

직접 파일을 확인해봐야겠네요;;








뭐여;;;;그냥 기본값으로

만들어졌고만;;;



Section Alignment : 0x1000(4096byte)말입니다.



이건 /align:15가 아니지 말입니다.;;;;;

에러구만..아니

버그구만요;;;;;;

버그!!!!

실망이네요;;;;






자 그러면

/align:16으로 했을때

PE값의 내용을 확인해보고 이 실험은

마무리 하겠습니다.

음...0x10(16byte)로

정확히 되었네요^^







[[결론!!!]]

/align:512로하면

Section Alignment와 File Alignment가

동일한 값이 되며

메모리 재배치가 필요없어집니다.









그리고,/algin의 최소값은?

.

.

.

16

이라는 것~^^!!!

/align:16이 설정할 수 있는 align최소값입니다.




[(주관적으로)  버리기 아까운 자료들]

  • chobits Visual Stdio 2015 링커 파라메타

^D:\TMP\TEST001.001\TEST001\RELEASE\6845CRT.OBJ|D:\TMP\TEST001.001\TEST001\RELEASE\TEST.OBJ|D:\TMP\TEST001.001\TEST001\RELEASE\VSPRINTF.OBJ

/OUT:"D:\TMP\TEST001.001\RELEASE\CHOBITS.BIN" /VERBOSE /NOLOGO ENTRY.OBJ HAL_ASM.OBJ /NODEFAULTLIB /MANIFEST:NO /PDB:"D:\TMP\TEST001.001\RELEASE\TEST001.PDB" /ASSEMBLYDEBUG /SUBSYSTEM:CONSOLE /OPT:NOREF /OPT:ICF /TLBID:1 /ENTRY:"EntryPoint16" /BASE:"0x20000" /DYNAMICBASE:NO /FIXED /NXCOMPAT:NO /IMPLIB:"D:\TMP\TEST001.001\RELEASE\TEST001.LIB" /MACHINE:X86 /SAFESEH:NO RELEASE\6845CRT.OBJRELEASE\TEST.OBJRELEASE\VSPRINTF.OBJ


이것 굉장히 어렵게 잡아낸것입니다 .ㅎㅎㅎ

(link.exe가 종료하면서 없어지는 정보입니다.link.exe를 발견하면

suspend시켜가지고 잡은 내용이지요)

여기에서 중요한 옵션은

/NODEFAULTLIB

/SUBSYSTEM:CONSOLE

/ENTRY: “EntryPoint16”

/BASE: “0x20000”

입니다.










  • chobists Visual C++ 6.0 링커 파라메타

# ADD LINK32 entry.obj /nologo /base:"0x20000" /entry:"EntryPoint16" /subsystem:console /map /debug /debugtype:coff /machine:I386 /nodefaultlib /out:".\disk\chobits.bin" /DRIVER /align:512 /FIXED

여기서 /align 이라는 옵션이 중요함!!!








  • /align: 512로 했을 때 성공화면^^;(버리기 아까워)

이것 저것 하다 드디어 성공했던 화면입니다.

분명히 그 순간에 화면캡처한 화면 맞습니다.^^!!!



이 코드가 실행되어 화면에 표신된것입니다.^^





이 글자를 너무 쉽게 생각

하시면 안됩니다...

ㅎㅎㅎㅎ

부트섹터를 지나

GDT를 설정하고

보호모드로 변경하여~

B8000 비디오카드에

데이타를 Write한 것이라는 것

ㅎㅎㅎㅎ



ㅎㅎㅎㅎㅎ 할렐루야!

미친감자의 /align 실험은 여기까정~~~







0 Comments
댓글쓰기 폼