1. 가상메모리
- 좀더 많은 주소를 얻고 싶을 때 boot.ini 에서 3G를 주면 된다.
- malloc이 실패하면 0 번지가 리턴된다. 이영역은 사용하지못한다.
- 2G-128K 가 사용자가 쓸수 있는 공간이라 할수 있다.
- 하나의 프로세스에서 스레드 1000개 정도가 MAX라 할수 있다.( Thread는 1M의 스택영역을 갖고있다. )
- 지금은 0x40,0000을 쓰지 않지만 과거와의 호환을 위해서 0x40,000 번지 부터 프로그램이 로드된다.
- VirtualAlloc () => 비어있는 가상주소공간을 할당한다는 개념..
1) 예약 : 주소만 확보해둔다.
2) 확정 : 물리공간과의 연결을 해준다.
3) 결국 예약을 함으로써 주소만 미리 확보 해둔다음 확정을 사용하여 쓴다는 개념!!
- VirtualAllocEx => 다른 프로세스의 가상메모리를 확보.
- 주소 할당단위는 64k배수 뒷4자리가 0이어야 하고, 0일때는 자동으로 할당된다.
- malloc은 결국 윈도우에선 VirtualAlloc 을 호출 한다는 것을 알 수 있다.
Kernel영역 | 2~4G 사이 |
PageTable | 0xC000,0000 |
ntoskrnl.exe | 0x8000,000 |
User영역 | 0~2G 사이 |
OS를 보호(완충지대) | 0x7FFF,0000 |
기본적인 DLL 영역 kernel32.dll, user32.dll GDI32.dll, ntdll.dll | 0x7xxx,xxxx |
사용자 추가 DLL | 0x1000,0000 |
MS-DOS 시절 전용프로그램 공간(호환성) | 0x40,0000 |
Heap | ~ 0x13,0000 |
Stack | 0x13,0000 ~ 0x3,0000 |
User영역의 시작 | 0x1,0000 |
NO_ACCESS(접근금지) | 0~64k |
- 좀더 많은 주소를 얻고 싶을 때 boot.ini 에서 3G를 주면 된다.
- malloc이 실패하면 0 번지가 리턴된다. 이영역은 사용하지못한다.
- 2G-128K 가 사용자가 쓸수 있는 공간이라 할수 있다.
- 하나의 프로세스에서 스레드 1000개 정도가 MAX라 할수 있다.( Thread는 1M의 스택영역을 갖고있다. )
- 지금은 0x40,0000을 쓰지 않지만 과거와의 호환을 위해서 0x40,000 번지 부터 프로그램이 로드된다.
- VirtualAlloc () => 비어있는 가상주소공간을 할당한다는 개념..
1) 예약 : 주소만 확보해둔다.
2) 확정 : 물리공간과의 연결을 해준다.
3) 결국 예약을 함으로써 주소만 미리 확보 해둔다음 확정을 사용하여 쓴다는 개념!!
char* p1 = (char*)VirtualAlloc( (void*)0, // 원하는 주소(64k배수), 자동으로 할당 0
size*15, // 원하는 크기(4k 단위)
MEM_RESERVE, // 예약만
PAGE_NOACCESS ); // 보호 속성(어짜피 접근못하므로 NOACCESS)
void* p2 = VirtualAlloc( p1, size, MEM_COMMIT, PAGE_READWRITE );
size*15, // 원하는 크기(4k 단위)
MEM_RESERVE, // 예약만
PAGE_NOACCESS ); // 보호 속성(어짜피 접근못하므로 NOACCESS)
void* p2 = VirtualAlloc( p1, size, MEM_COMMIT, PAGE_READWRITE );
- VirtualAllocEx => 다른 프로세스의 가상메모리를 확보.
- 주소 할당단위는 64k배수 뒷4자리가 0이어야 하고, 0일때는 자동으로 할당된다.
- malloc은 결국 윈도우에선 VirtualAlloc 을 호출 한다는 것을 알 수 있다.
2. MMF( Memory Mapped File )
- OS는 오래동안 쓰지 않는 프로그램의 물리메모리를 가상메모리에 백업해 놓는다.
- 백업되 있던 가상메모리를 물리 메모리로 올리기 위해선 오버헤드가 발생된다.
- VirtualLock 을 쓰면 항상 물리공간에 있게 할 수 있다. ( 물리메모리에 부담이 간다. )
- Working Set : 물리 공간에 있는 Page 집합 SetProcessWorkingSet ( 1~2M를 쓸 수 있다. )
- 메모리에 연결된 파일을 MMF 라 한다.!! 파일로 직접 접근하여 쓸 수 있다.
- 보안을 설정해주면 접근을 제한 해줄 수 있다. 아무나 접근 할 수 있는 공유메모리와 다른 개념!!!
- 파일을 Open해서 쓰는 것보다 효율적이다.
1) 일반파일보다 빠르게 작업을 할 수 있다.
2) 연결만 해놓으면 그자체가 buf가 되므로 버퍼 없는 작업이 가능하다.
3) 동일한 파일을 가상주소로 연결 하며 프로세스간 통신(IPC)가 구현된다.
4) PEVIEW 처럼 exe의 Header를 분석하기 위해선 MMF가 이상적이다. 메모리로 exe를 로드해서 읽기 보다는 가상주소를 exe로 바로 맵핑하면 해당 주소에 맞는 구조체만 만들어 주면 된다.
5) exe, dll은 모두 MMF로 구성되어 있다. ( Demand Page )모두 Page단위로 필요할 때만 물리메모리에 올려진다.
- WM_SETTEXT 의 MMF 사용
1) 다른 프로세스의 윈도우 제목을 변경하고자 할때 문자열만 넘기면 왜 되는 것인가?
- OS는 오래동안 쓰지 않는 프로그램의 물리메모리를 가상메모리에 백업해 놓는다.
- 백업되 있던 가상메모리를 물리 메모리로 올리기 위해선 오버헤드가 발생된다.
- VirtualLock 을 쓰면 항상 물리공간에 있게 할 수 있다. ( 물리메모리에 부담이 간다. )
- Working Set : 물리 공간에 있는 Page 집합 SetProcessWorkingSet ( 1~2M를 쓸 수 있다. )
- 메모리에 연결된 파일을 MMF 라 한다.!! 파일로 직접 접근하여 쓸 수 있다.
- 보안을 설정해주면 접근을 제한 해줄 수 있다. 아무나 접근 할 수 있는 공유메모리와 다른 개념!!!
- 파일을 Open해서 쓰는 것보다 효율적이다.
1) 일반파일보다 빠르게 작업을 할 수 있다.
2) 연결만 해놓으면 그자체가 buf가 되므로 버퍼 없는 작업이 가능하다.
3) 동일한 파일을 가상주소로 연결 하며 프로세스간 통신(IPC)가 구현된다.
4) PEVIEW 처럼 exe의 Header를 분석하기 위해선 MMF가 이상적이다. 메모리로 exe를 로드해서 읽기 보다는 가상주소를 exe로 바로 맵핑하면 해당 주소에 맞는 구조체만 만들어 주면 된다.
5) exe, dll은 모두 MMF로 구성되어 있다. ( Demand Page )모두 Page단위로 필요할 때만 물리메모리에 올려진다.
- WM_SETTEXT 의 MMF 사용
1) 다른 프로세스의 윈도우 제목을 변경하고자 할때 문자열만 넘기면 왜 되는 것인가?
int main()
{
HWND h = FindWindow( 0, "계산기" );
// 계산기의 캡션바를 "Hello"로 변경한다. - 될까?
SendMessage( h, WM_SETTEXT, 0, (LPARAM)"Hello" );
}
2) WM_SETTEXT 메시지를 수행할 때 내부적으로 MMF 에 "Hello" 를 보관했다가 계산기에서 이 영역에서 문자열을 읽어 와서 제목을 변경 해 주는 것이다. {
HWND h = FindWindow( 0, "계산기" );
// 계산기의 캡션바를 "Hello"로 변경한다. - 될까?
SendMessage( h, WM_SETTEXT, 0, (LPARAM)"Hello" );
}
3. DLL Inject ( 참고 문서 :
- 다른 프로세스에 내가 만든 DLL을 집어넣어 보자.!!! 핵심은 CreateRemoteThread
- FindWindow 로 계산기 핸들을 얻은 다음에 pid => 프로세스 핸들 을 얻게 되면
- SetWindowLong으로 WndProc 를 변경 할 수 있을까? (서브클래싱을 할 수 있을까?)
- 되지 않는다.. 왜냐하면 프로세스간의 독립성을 보장하는 가상메모리를 생각하면 알 수 있다.
- 계산기의 가상 메모리에는 내가 변경하고자 하는 함수가 올라와 있지 않기 때문이다.
- 이를 해결하기 위해선 계산기의 가상메모리에 함수를 올려놓아야 한다.( DLL을 사용해서 올려보자!! )
- 문자열을 써주기 위해선 VirtualAllocEx 로 공간을 할당한 후에 WriteProcessMemory로 써준다.
- 다른 프로세스에 내가 만든 DLL을 집어넣어 보자.!!! 핵심은 CreateRemoteThread
- FindWindow 로 계산기 핸들을 얻은 다음에 pid => 프로세스 핸들 을 얻게 되면
- SetWindowLong으로 WndProc 를 변경 할 수 있을까? (서브클래싱을 할 수 있을까?)
- 되지 않는다.. 왜냐하면 프로세스간의 독립성을 보장하는 가상메모리를 생각하면 알 수 있다.
- 계산기의 가상 메모리에는 내가 변경하고자 하는 함수가 올라와 있지 않기 때문이다.
- 이를 해결하기 위해선 계산기의 가상메모리에 함수를 올려놓아야 한다.( DLL을 사용해서 올려보자!! )
- 문자열을 써주기 위해선 VirtualAllocEx 로 공간을 할당한 후에 WriteProcessMemory로 써준다.
2007/10/15 - [Study/System] - 10.15(월) 실습-1( 가상메모리, MMF, DLL Inject )
참고문서 :