제2 장 - Win 32 프로그램 운행 원리 (부분 개념 및 코드 설명)
개념 팁:
1. 모든 프로 세 스 는 자신의 개인 주소 공간 을 부여 합 니 다.프로 세 스 내 스 레 드 가 실 행 될 때 이 스 레 드 는 프로 세 스 에 속 하 는 메모리 에 만 접근 할 수 있 고 다른 프로 세 스 에 속 하 는 메모리 가 차단 되 어 이 스 레 드 에 접근 할 수 없습니다.
PS: 프로 세 스 A 는 주소 공간의 0x 12345678 주소 에 데이터 구 조 를 가 질 수 있 고 프로 세 스 B 는 주소 공간의 0x 12345678 에 완전히 다른 데 이 터 를 저장 할 수 있 습 니 다.서로 방문 할 수 없다.
2. 대부분의 시스템 에서 윈도 우 는 주소 공간의 절반 (4GB 의 절반, 0x0000000 - 0x7FFFFF) 을 프로 세 스 에 개인 저장 소 로 남 겨 두 고 운영 체제 내부 에서 사용 하 는 데 이 터 를 저장 합 니 다.
3. 각 프로 세 스 의 주소 공간 은 사용자 공간 과 시스템 공간 두 부분 으로 나 뉜 다.사용자 공간 부분 은 프로 세 스 의 개인 주소 공간 입 니 다. 프로 세 스 는 다른 프로 세 스 의 이 부분 공간의 데 이 터 를 읽 거나 쓸 수 없습니다.시스템 공간 부분 에 운영 체제 의 코드 를 설치 하 는데 커 널 코드, 장치 구동 코드, 장치 I / O 버퍼 등 을 포함한다.시스템 공간 부분 은 모든 프로 세 스 에서 공 유 됩 니 다.일부 시스템 에서 이 데이터 구 조 는 보호 된다.접근 을 시도 할 때 접근 이상 이 발생 할 수 있 습 니 다.
4. 프로세서 가 여러 개의 특권 단 계 를 정의 합 니 다.예 를 들 어 80386 프로세서 가 모두 4 가지 (0 - 3) 특권 단 계 를 정의 하거나 링 이 라 고 합 니 다.이 중 0 레벨 은 최고급 (특권 레벨), 3 레벨 은 최저 레벨 (사용자 레벨) 이다.
5. 응용 프로그램의 접근 을 막 거나 관건 적 인 시스템 데이터 (즉 2GB 시스템 공간 내 데이터) 를 수정 하기 위해 윈도 는 두 가지 접근 모드 를 사용 했다. 커 널 모드 와 사용자 모드 는 각각 프로세서 의 0 과 3 이라는 두 가지 특권 단 계 를 사용 했다.사용자 프로그램의 코드 는 사용자 모드 에서 실행 되 고 시스템 프로그램 (예 를 들 어 시스템 서비스 프로그램 과 하드웨어 구동) 의 코드 는 커 널 모드 에서 실 행 됩 니 다.
6. 커 널 대상 은 시스템 이 제공 하 는 사용자 모드 에서 코드 와 커 널 모드 에서 코드 가 상호작용 을 하 는 기본 인터페이스 이다.커 널 인 터 랙 션 대상 을 사용 하 는 것 은 응용 프로그램 과 시스템 커 널 이 상호작용 을 하 는 중요 한 방식 중 하나 이다.
7. 커 널 대상 을 도입 하면 시스템 은 다음 과 같은 4 가지 임 무 를 편리 하 게 완성 할 수 있다.
1) 시스템 자원 에 식별 가능 한 이름 을 제공한다.
2) 프로 세 스 간 에 자원 과 데 이 터 를 공유 합 니 다.
3) 자원 이 허가 되 지 않 은 코드 에 접근 하지 않도록 보호 한다.
4) 대상 의 인용 상황 을 추적 하여 시스템 으로 하여 금 언제 한 대상 이 더 이상 사용 되 지 않 고 사용 하 는 공간 을 방출 할 수 있 는 지 알 게 한다.
8. 커 널 대상 의 데이터 구 조 는 커 널 모드 에서 만 접근 할 수 있 기 때문에 메모리 에서 이러한 데이터 구 조 를 직접 찾 는 것 은 응용 프로그램 에 있어 불가능 합 니 다.응용 프로그램 은 커 널 대상 에 API 함 수 를 사용 해 야 합 니 다.
9. 함 수 를 호출 하여 커 널 대상 을 만 들 때 함 수 는 이 커 널 대상 을 표시 하 는 핸들 을 되 돌려 줍 니 다.핸들 은 프로 세 스 와 관련 된 것 으로 커 널 대상 을 만 드 는 프로 세 스 에 만 유효 합 니 다.물론 여러 프로 세 스 가 하나의 커 널 대상 을 공유 하 는 것 도 가능 합 니 다. Duplicate Handle 함 수 를 사용 하여 프로 세 스 핸들 을 다른 프로 세 스 에 복사 하면 됩 니 다.
10. 커 널 대상 중 가장 간단 하고 자주 사용 하 는 속성 - 사용 계수.계수 속성 을 사용 하여 프로 세 스 가 특정 커 널 대상 에 대한 응용 횟수 를 가리 키 며, 시스템 에서 인용 횟수 가 0 인 것 을 발견 하면 자원 을 자동 으로 닫 습 니 다.(생 성 시 1 로 초기 화 되 었 습 니 다. 이 커 널 대상 을 열 때마다 1 을 더 하고 닫 으 면 1 을 줄 입 니 다. 0 으로 줄 였 을 때 프로 세 스 가 이 커 널 대상 에 대한 모든 인용 이 닫 혔 음 을 설명 합 니 다. 시스템 은 이 커 널 대상 자원 을 방출 해 야 합 니 다.)
11. 프로 세 스 (Process) 는 실행 중인 프로그램 으로 자신의 가상 주소 공간 을 가지 고 있 으 며, 프로 세 스 가 만 든 파일, 파이프, 동기 화 대상 등 자신의 코드, 데이터 와 다른 시스템 자원 을 가지 고 있다.하나의 프로 세 스 도 이 프로 세 스 를 실행 하 는 스 레 드 (Thread) 를 하나 이상 포함 합 니 다.
12. 프로그램 과 프로 세 스 가 표면 에서 매우 비슷 하 다.그러나 프로그램 은 일련의 정적 명령 이 고 프로 세 스 는 용기 입 니 다. 프로그램 인 스 턴 스 상하 문 에서 실행 되 는 일련의 스 레 드 에 사용 되 는 자원 을 포함 합 니 다.
13. 스 레 드 는 프로 세 스 내 실행 코드 의 독립 된 실체 입 니 다.운영 체제 가 프로 세 스 를 만 든 후에 스 레 드 실행 프로 세 스 의 코드 를 만 들 것 입 니 다.보통 이 스 레 드 를 주 스 레 드 라 고 부른다.주 스 레 드 는 실행 과정 에서 다른 스 레 드 를 만 들 수 있 습 니 다 (보조 스 레 드 라 고 함).
14. Win 프로 세 스 의 두 구성 부분:
1) 프로 세 스 커 널 대상.운영 체 제 는 이 커 널 대상 을 사용 하여 프로 세 스 를 관리 합 니 다.이 커 널 대상 도 운영 체제 가 프로 세 스 통계 정 보 를 저장 하 는 곳 이다.
2) 개인 적 인 가상 주소 공간.이 주소 공간 은 실행 가능 하거나 DLL 모듈 의 코드 와 데 이 터 를 포함 하고 프로그램 이 동적 으로 메모 리 를 신청 하 는 곳 입 니 다. 예 를 들 어 스 레 드 스 택 과 프로 세 스 더미 등 입 니 다.
15. 응용 프로그램 은 프로그램 이 실 행 될 때 호출 되 는 입구 함수 가 있어 야 합 니 다.콘 솔 프로그램 을 만 들 었 다 면 이 입구 함 수 는 main 입 니 다.
PS:int main(int argc,char *argv[]);
16. 사실상 운영 체 제 는 실제 main 함 수 를 호출 하 는 것 이 아니 라 C / C + + 운행 기 시작 함 수 를 호출 합 니 다. 이 함 수 는 C / C + 운행 기 라 이브 러 리 를 초기 화 합 니 다.따라서 프로그램 에서 malloc 와 free 같은 함 수 를 호출 할 수 있 습 니 다.
17. 콘 솔 프로그램 에서 C / C + + 실행 기 시작 함 수 는 프로그램 입구 함수 main 을 호출 합 니 다.없 으 면 'unsolved external symbol' 오 류 를 되 돌려 줍 니 다.
18. Win 32 프로그램의 시작 과정 은 프로 세 스 의 생 성 과정 입 니 다. 운영 체 제 는 CreateProcess 함수 (코드 설명 에서 이 함수 에 대한 구체 적 인 설명 이 있 을 것 입 니 다) 를 호출 하여 새로운 프로 세 스 를 만 듭 니 다.하나의 스 레 드 가 CreateProcess 함 수 를 호출 할 때 시스템 은 프로 세 스 커 널 대상 을 만 듭 니 다. 사용 계 수 는 1 로 초기 화 됩 니 다. 이 프로 세 스 커 널 대상 은 프로 세 스 자체 가 아니 라 시스템 이 이 프로 세 스 를 관리 하 는 작은 데이터 구조 일 뿐 입 니 다.시스템 은 다음 에 새로운 프로 세 스 를 위해 가상 주소 공간 을 만 들 고 프로그램 이 실 행 될 때 필요 한 코드 와 데 이 터 를 불 러 옵 니 다.시스템 은 이 어 새 프로 세 스 를 위 한 메 인 스 레 드 를 만 들 것 입 니 다. 이 메 인 스 레 드 는 C / C + 실행 기 시작 코드 를 실행 하여 실 행 됩 니 다. C / C + 실행 기 시작 코드 는 main 함 수 를 호출 합 니 다.시스템 이 새 프로 세 스 와 프로 세 스 의 주 스 레 드 를 성공 적 으로 만 들 수 있다 면 CreateProcess 함 수 는 TRUE 로 돌아 갑 니 다. 그렇지 않 으 면 FALSE 로 돌아 갑 니 다.
19. 일반적으로 생 성 프로 세 스 를 부모 프로 세 스 라 고 부 르 며, 생 성 된 프로 세 스 를 하위 프로 세 스 라 고 부른다.시스템 은 새 프로 세 스 를 만 들 때 새 프로 세 스 에 STARTUPINFO 형식의 변 수 를 지정 합 니 다. 이 구 조 는 부모 프로 세 스 가 하위 프로 세 스에 전달 하 는 디 스 플레이 정 보 를 포함 합 니 다.(그래 픽 인터페이스 응용 프로그램 에 있어 서 이 정 보 는 새로운 프로 세 스 의 메 인 스 레 드 의 메 인 창 표시 등에 영향 을 줄 수 있 습 니 다.)
코드 설명:
1.CreateProcess(create process)
PS: 완전한 프로 세 스 를 만 드 는 프로그램 입 니 다. Windows 자체 명령 행 프로그램 cmd. exe 를 열 었 습 니 다. (하지만 저 는 보통 Win + R 입 니 다. 직접 cmd 로 들 어 갑 니 다.)
1 #include "stdafx.h"
2 #include
3 #include
4
5 int main(int argc, char* argv[])
6 {
7 char szCommandLine[] = "cmd";
8 STARTUPINFO si = { sizeof(si) };
9 PROCESS_INFORMATION pi;
10
11 si.dwFlags = STARTF_USESHOWWINDOW; // wShowWindow
12 si.wShowWindow = TRUE; // TRUE ,
13 // FALSE
14 BOOL bRet = ::CreateProcess (
15 NULL, //
16 szCommandLine, //
17 NULL, //
18 NULL, //
19 FALSE, //
20 CREATE_NEW_CONSOLE, //
21 NULL, //
22 NULL, //
23 &si,
24 &pi);
25
26 if(bRet)
27 {
28 // ,
29 ::CloseHandle (pi.hThread);
30 ::CloseHandle (pi.hProcess);
31
32 printf(" ID :%d
", pi.dwProcessId);
33 printf(" ID :%d
", pi.dwThreadId);
34 }
35 return 0;
36 }
2.ProcessList(process list)
PS: ToolHelp 함수 의 CreateToolhelp32Snapshop 함 수 를 사용 하여 현재 시스템 에서 실행 중인 프로 세 스에 스냅 샷 (Snapshot) 을 찍 어 프로 세 스 목록 을 가 져 옵 니 다. 그리고 Process32First 함수 와 Process32Next 함 수 를 이용 하여 스냅 샷 에 기 록 된 목록 을 옮 겨 다 닙 니 다.
1 #include "stdafx.h"
2 #include
3 #include //
4
5 int main(int argc, char* argv[])
6 {
7 PROCESSENTRY32 pe32;
8 // ,
9 pe32.dwSize = sizeof(pe32);
10
11 //
12 HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
13 if(hProcessSnap == INVALID_HANDLE_VALUE)
14 {
15 printf(" CreateToolhelp32Snapshot !
");
16 return -1;
17 }
18
19 // ,
20 BOOL bMore = ::Process32First(hProcessSnap, &pe32);
21 while(bMore)
22 {
23 printf(" :%s
", pe32.szExeFile);
24 printf(" ID :%u
", pe32.th32ProcessID);
25
26 bMore = ::Process32Next(hProcessSnap, &pe32);
27 }
28
29 // snapshot
30 ::CloseHandle(hProcessSnap);
31 return 0;
32 }
3.TerminateProcess(terminate process)
PS: 이 프로그램 은 프로 세 스 만 의 ID 번 호 를 입력 하여 이 프로 세 스 를 끝 냅 니 다. 병 사 는 작업 결 과 를 되 돌려 줍 니 다. (작업 관리자 에서 프로 세 스 ID 를 찾 아 보 세 요. QQ 같은 것 을 가 져 오 는 것 을 권장 합 니 다. Windows 같은 것 은 절대 찾 지 마 세 요)
1 #include "stdafx.h"
2 #include
3
4 BOOL TerminateProcessFromId(DWORD dwId)
5 {
6 BOOL bRet = FALSE;
7 // ,
8 HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
9 if(hProcess != NULL)
10 {
11 //
12 bRet = ::TerminateProcess(hProcess, 0);
13 }
14 CloseHandle(hProcess);
15 return bRet;
16 }
17
18 int main(int argc, char* argv[])
19 {
20 DWORD dwId;
21 printf(" ID :
");
22 scanf("%u", &dwId);
23 if(TerminateProcessFromId(dwId))
24 {
25 printf(" !
");
26 }
27 else
28 {
29 printf(" !
");
30 }
31
32 return 0;
33 }
4.Testor
PS: 이것 은 이 장의 마지막 프로그램 인 메모리 수정 기 서 비 스 를 위 한 테스트 프로그램 입 니 다. 그 다음 에는 메모리 수정 기 를 통 해 g nNum 과 i 의 값 을 수정 합 니 다.
1 #include "stdafx.h"
2 #include
3 //
4 int g_nNum;
5 int main(int argc, char* argv[])
6 {
7 int i = 198; //
8 g_nNum = 1003;
9
10 while(1)
11 {
12 //
13 printf(" i = %d, addr = %08lX; g_nNum = %d, addr = %08lX
",
14 ++i, &i, --g_nNum, &g_nNum);
15 getchar();
16 }
17
18 return 0;
19 }
5.MemRepair(memory repair)
PS: 이 장의 마지막 프로그램 인 메모리 수정 기 입 니 다. 프로그램 설명 이 적 혀 있 습 니 다.
1 #include "stdafx.h"
2 #include "windows.h"
3 #include "stdio.h"
4 #include
5
6
7 BOOL FindFirst(DWORD dwValue); //
8 BOOL FindNext(DWORD dwValue); // 2、3、4……
9
10 DWORD g_arList[1024]; //
11 int g_nListCnt; //
12 HANDLE g_hProcess; //
13
14
15 //////////////////////
16
17 BOOL WriteMemory(DWORD dwAddr, DWORD dwValue);
18 void ShowList();
19
20
21 int main(int argc, char* argv[])
22 {
23 // 02testor
24 char szFileName[] = "..\\02testor\\debug\\02testor.exe";
25 STARTUPINFO si = { sizeof(si) };
26 PROCESS_INFORMATION pi;
27 ::CreateProcess(NULL, szFileName, NULL, NULL, FALSE,
28 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
29 // ,
30 ::CloseHandle(pi.hThread);
31 g_hProcess = pi.hProcess;
32
33 //
34 int iVal;
35 printf(" Input val = ");
36 scanf("%d", &iVal);
37
38 //
39 FindFirst(iVal);
40
41 //
42 ShowList();
43
44
45 while(g_nListCnt > 1)
46 {
47 printf(" Input val = ");
48 scanf("%d", &iVal);
49
50 //
51 FindNext(iVal);
52
53 //
54 ShowList();
55 }
56
57
58 //
59 printf(" New value = ");
60 scanf("%d", &iVal);
61
62 //
63 if(WriteMemory(g_arList[0], iVal))
64 printf(" Write data success
");
65
66
67 ::CloseHandle(g_hProcess);
68 return 0;
69 }
70
71 BOOL CompareAPage(DWORD dwBaseAddr, DWORD dwValue)
72 {
73 // 1
74 BYTE arBytes[4096];
75 if(!::ReadProcessMemory(g_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL))
76 return FALSE; //
77
78 // 1
79 DWORD* pdw;
80 for(int i=0; iint )4*1024-3; i++)
81 {
82 pdw = (DWORD*)&arBytes[i];
83 if(pdw[0] == dwValue) // ?
84 {
85 if(g_nListCnt >= 1024)
86 return FALSE;
87 //
88 g_arList[g_nListCnt++] = dwBaseAddr + i;
89 }
90 }
91
92 return TRUE;
93 }
94
95 BOOL FindFirst(DWORD dwValue)
96 {
97 const DWORD dwOneGB = 1024*1024*1024; // 1GB
98 const DWORD dwOnePage = 4*1024; // 4KB
99
100 if(g_hProcess == NULL)
101 return FALSE;
102
103 // ,
104 DWORD dwBase;
105 OSVERSIONINFO vi = { sizeof(vi) };
106 ::GetVersionEx(&vi);
107 if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
108 dwBase = 4*1024*1024; // Windows 98 ,4MB
109 else
110 dwBase = 640*1024; // Windows NT ,64KB
111
112 // 2GB
113 for(; dwBase < 2*dwOneGB; dwBase += dwOnePage)
114 {
115 // 1
116 CompareAPage(dwBase, dwValue);
117 }
118
119 return TRUE;
120 }
121
122 BOOL FindNext(DWORD dwValue)
123 {
124 // m_arList , m_nListCnt
125 int nOrgCnt = g_nListCnt;
126 g_nListCnt = 0;
127
128 // m_arList
129 BOOL bRet = FALSE; //
130 DWORD dwReadValue;
131 for(int i=0; i)
132 {
133 if(::ReadProcessMemory(g_hProcess, (LPVOID)g_arList[i], &dwReadValue, sizeof(DWORD), NULL))
134 {
135 if(dwReadValue == dwValue)
136 {
137 g_arList[g_nListCnt++] = g_arList[i];
138 bRet = TRUE;
139 }
140 }
141 }
142
143 return bRet;
144 }
145
146 //
147 void ShowList()
148 {
149 for(int i=0; i< g_nListCnt; i++)
150 {
151 printf("%08lX
", g_arList[i]);
152 }
153 }
154
155 BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)
156 {
157 return ::WriteProcessMemory(g_hProcess, (LPVOID)dwAddr, &dwValue, sizeof(DWORD), NULL);
158 }
요약: 중요 한 개념, 지식, 코드 설명 이 모두 표시 되 었 습 니 다. 이 장 을 통 해 Win 32 프로그램 실행 등 원리 에 대해 명확 하 게 이해 할 수 있 습 니 다. 프로그램 이 실행 되 는 전체 과정 을 진정 으로 이해 하고 메모리 의 실제 상황 을 이해 할 수 있 습 니 다. 예전 에 Win 32 프로그램 에 대한 인식 이 명확 하지 않 았 던 것 을 바 꾸 었 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.