본문 바로가기

My Study/Programming&Theory

Share Memory & Share Moudle

리버싱이나 시스템 프로그래밍을 하면서 궁금한 점이 생겨서 찾아보던 도중 재미있어 보여서 정리를 해보았습니다.

dll은 Dynamic Link Library입니다.
이 때 Windows는 각각의 프로세스에 로드되어 있는 동일한 dll에 대하여 하나의 dll 파일을 실제 물리 메모리에 로드하고 모든 프로세스는 이 하나의 내용을 공유하는 형태로 사용을 하고 있습니다.

그러면 이 때 동일한 dll을 공유하고 있는 상태에서 어떤 한 프로세스가 공유 dll의 일부 코드를 다른 dll과 다르게 수정을 해야하는 경우에는 어떻게 될까요??
즉, Breakpoint를 걸면 cc라는 값으로 코드가 변하게 되고 아니면 WriteProcessMemory같은 함수로 dll의 코드를 변경 했을 때 이 dll을 공유하고 있는 모든 프로세스에 영향을 끼칠까요??

직접 리버싱이나 시스템 프로그래밍 해보신 분들은 이미 해답은 아실 것입니다.
당연히 영향을 끼치지 않습니다. 수정을 가한 dll을 소유하고 있는 프로세스만 영향을 받게 되는 것이지요.

어떻게 이럴 수 있는지 차근차근 알아보도록 하겠습니다.

Windows에서는 이러한 공유의 문제점을 피하고 최대한 효과적인 공유 메모리의 관리를 위하여 Copy-On-Write라는 개념을 사용하고 있습니다.

Copy-On-Write는  처음에는 아래 그림처럼 공유하고 있는 dll이 동일한 물리 메모리를 지시하고 있습니다.
 


이 때 Process B에서 특정 메모리의 내용을 변경하고자 하면 아래 그림처럼 변경하고자 하는 페이지의 내용이 새로운 물리 메모리에 그대로 복사가 이루어집니다.

 


 마지막으로 새롭게 복사되어진 메모리에 변경된 내용을 새롭게 쓴 후 Process B는 새롭게 변경된 페이지를 지시하도록 하는 것 입니다. ( 아래 그림 )

 

 
Windows는 dll이 메모리에 올라갈 때 모든 코드 페이지에 대하여 읽기 전용(PAGE_READONLY) 속성의 페이지로 만듭니다. 한번 올디에서 봐보겠습니다.


위 그림을 보면 모든 dll 세그먼트 속성이 R로 되어 있는 것을 확인할 수 있습니다.

이 때 사용자 또는 다른 시스템이 이 페이지의 내용을 수정하기 위해서는 VirtualProtect()를 사용해 WRITE 속성을 가지도록 바꿔주어야합니다. 이 때 실제의 PTE(Page Table Entry) 내용은 변경되지 않는 PAGE_READONLY 속성을 유지하며 Windows 내부에서는 이 페이지의 내용이 읽기/쓰기가 가능한 Copy-On-Write 페이지임을 세팅하여 놓기만 합니다. 그리고 이후에 사용자가 이 페이지에 대하여 쓰기를 시도할 경우 CPU는 Memory Access Error를 발생시키고 해당 Interrupt Handler에서는 이 페이지의 내용이 읽기/쓰기 가능한 Copy-On-Write 페이지임을 확인한 후 Copy-On-Write를 수행하게 됩니다.

여기서 또 한가지 알아야할 것이 있습니다.
공유된 페이지들은 Copy-On-Write에 의해 가리키고 있는 페이지가 다른 곳으로 바뀔 수 있으며, 이러한 경우 본래의 PTE 정보를 찾을 수 없습니다. 그래서 Windows에서는 원본 PTE를 지니고 있는 PPTE(Protoype PTE)를 가지고 있습니다. 사실 PPTE는 메모리 변환에 사용되기 위한 용도가 아닌 MMF(Memory Mapped File) 또는 공유된 dll에 대하여 Windows에서 본래의 페이지의 위치를 가지고 있는 것 입니다. 만약 공유된 dll에 대하여 새로운 프로세스에서 이 dll에 공유를 원할 경우 Windows는 바로 이 PPTE의 정보를 참조하여 이 dll의 PTE 정보를 구성하게 되는 것입니다.

그리고 공유된 페이지가 유효하지 않게 되었거나 페이지 아웃 되었을 때도 유용하게 사용이 됩니다. 

'My Study > Programming&Theory' 카테고리의 다른 글

Data Read/Write in Cache  (0) 2011.07.12
Windows Cache  (2) 2011.05.31
Interrupt Descriptor Table Architecture  (0) 2011.05.18
Get clipboard data  (0) 2011.05.17
프로세스 생성 막기  (2) 2011.04.28