VC++之 Windows进程篇

保护模式:

基于 X86 微处理器 (80836) 处理器有 3 种工作模式:

               实模式,保护模式,虚拟 86 模式。

 

实模式和虚拟 86 模式是为了和 8086 处理器兼容而设置的,而保护模式是 80836 处理器的主要工作模式。

      windows 操作系统就在此模式之下运行。

 

虚拟内存:

       在保护模式下, 80836 所有 32 根地址线都是可以寻址的,处理器寻址范围是

0x00000000~0xFFFFFFFF(232   ,4GB) 所以 32 windows 操作系统可寻址 4GB 的地址空间 .

       而机器的 RAM 不可能是 4GB ,主要靠 CPU 支持, CPU 在保护模式下支持虚拟存储,既为虚拟内存 。它可以帮助操作系统将磁盘空间作为内存使用。

       在磁盘空进应用这一机制的文件叫做页文件

      

       通常情况下, Windows4G 的前半部分留给进程作为私有存储,而自己使用另一半 2G 来存储操作系统内部使用的数据。

 

进程的创建

       操作系统通过 CreateProcess 函数来创建进程。

              STARTUPINFO

进程创建后,会分配一个此类型的变量。包含父进程传递给子进程的一些信息

 

              PROCESS_INFOMATION

                     存储当前进程的信息

      

       创建进程示例:

             

char szFileName[] = { "D:\\myeclipse6\\workspace \\02Test\\Debug\\02Test.exe " };

    STARTUPINFO si = { sizeof (si) };

    PROCESS_INFORMATION pi;

    :: CreateProcessA ( // 创建线程

NULL,       // 不指定文件名

szFileName, // 命令行参数

NULL,         // 默认进程安全性

NULL,        // 默认线程安全性

FALSE,      // 不可以被子进程继承

CREATE_NEW_CONSOLE, // 为新进程创建一个新的控制台窗口

NULL, // 使用本进程环境变量

NULL, // 使用本进程驱动器和目录

&si,

&pi);

 

 

内存区域操作:

       Windows4KB 为单位为应用程序分配内存,其采用分页机制 来管理内存。每页大小是 4KB ,目的是按页来搜索目标内存,可以提高搜索效率 .

 

练习程序代码:

测试程序 Test.cpp

 

/*
 * test.cpp
 *
 *  Created on: 2009-12-22
 *      Author: Zhangwenbo
 */
#include <stdio.h>
int g_nNum;
int main(){
	int i=198;
	g_nNum=1003;
	while(1){
printf("i=%d,addr=%08lX;g_nNum=%d,addr=%08lX\n",
++i,&i,--g_nNum,&g_nNum);
	}
	return 0;
}
 

 

内存操作代码:

/*
 * Memrepair.cpp
 *
 *  Created on: 2009-12-22
 *      Author: Zhangwenbo
 */
#include <stdio.h>
#include <windows.h>
BOOL FindFirst(DWORD dwValue); //在目标空间进行第一次查找
BOOL FindNext(DWORD dwValue); //在目标空间进行第二次,三次查找
DWORD g_arList[1024]; //地址列表
int g_nListCnt; //有效地址个数
HANDLE g_hProcess; //目标进程句柄

/**
 * 比较内存页中的数据
 */
BOOL CompareAPage(DWORD dwBaseAddr, DWORD dwValue) {
	//读取一页内存 4KB为单位
	BYTE arBytes[4096];
	if (!::ReadProcessMemory(g_hProcess, (LPVOID) dwBaseAddr, arBytes, 4096, NULL)) {
		return FALSE;//此页不可读
	}

	//在这一页内存里面查找
	DWORD* pdw;
	for (int i = 0; i < (int) 4* 1024 - 3 ; i++) {
		pdw = (DWORD*) &arBytes[i];
		if (pdw[0] == dwValue) {//等于要查找的值
			if (g_nListCnt >= 1024)
				return FALSE;
			//添加到全局变量中
			g_arList[g_nListCnt++] = dwBaseAddr + i;
		}
	}
	return TRUE;
}

/**
 * 进行下次查找
 */
BOOL FindNext(DWORD dwValue) {
	//保存m_arList数组中有效地址的个数,初始化新的m_nListCnt的值
	int nOrgCnt = g_nListCnt;
	g_nListCnt = 0;
	//从m_arList数组记录的地址处查找
	BOOL bRet = FALSE;
	DWORD dwReadValue;
	for (int i = 0; i < nOrgCnt; i++) {
		if (::ReadProcessMemory(g_hProcess, (LPVOID) g_arList[i], &dwReadValue, sizeof(DWORD), NULL)) {
			if (dwReadValue == dwValue) {
				g_arList[g_nListCnt++] = g_arList[i];
				return TRUE;
			}
		}
	}
	return bRet;
}
/**
 * 第一次在指定空间查找
 */
BOOL FindFirst(DWORD dwValue) {
	//1GB
	const DWORD dwOneGB = 1024* 1024* 1024 ;
	//4KB
	const DWORD dwOnePage = 4* 1024 ;

	if (g_hProcess == NULL)
		return FALSE;
	//查看操作系统类型
	DWORD dwBase;
	OSVERSIONINFO vi = { sizeof(vi) };
	::GetVersionExA(&vi);
     //确定从哪个地址开始搜索
	if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
		    dwBase = 4* 1024* 1024 ; //WINDOW98系列 4mb
		}else {
			dwBase=640*1024;//64kb windowsNT系列
		}

		//在开始地址到2GB的地址空间查找 递增1页大小(4kb)
		for(;dwBase<2*dwOneGB;dwBase+=dwOnePage) {
			//比较一页大小的内存
			CompareAPage(dwBase,dwValue);
		}

		return TRUE;
	}

	/**
	 * 打印列表
	 */
void ShowList() {
	for (int i = 0; i < g_nListCnt; i++) {
		printf("%08lX\n", g_arList[i]);

	}
}
/**
* 改写内存值
*/
BOOL WriteMemory(DWORD dwAddr,DWORD dwValue){
	return ::WriteProcessMemory(g_hProcess,(LPVOID)dwAddr,&dwValue,sizeof(DWORD),NULL);
}
int main() {
	//启动02Test进程
	char szFileName[] = {
			"D:\\myeclipse6\\workspace\\02Test\\Debug\\02Test.exe" };
	STARTUPINFO si = { sizeof(si) };
	PROCESS_INFORMATION pi;
	//创建线程
	::CreateProcessA(NULL, szFileName, NULL, NULL, FALSE, CREATE_NEW_CONSOLE,
			NULL, NULL, &si, &pi);
	//关闭线程句柄,我们不使用此句柄
	::CloseHandle(pi.hThread);
	//获取目标进程句柄
	g_hProcess = pi.hProcess;
	//输入要修改的值
	int iVal;
	printf("输入值:");
	scanf("%d", &iVal);
	//进行第一次查找
	FindFirst(iVal);
	//打印出搜查结果
	ShowList();
	while (g_nListCnt > 1) {
		printf("输入值:");
		scanf("%d", &iVal);
		//进行下次查找
		FindNext(iVal);
		ShowList();
		printf("输入新值:");
		scanf("%d", &iVal);
		if(WriteMemory(g_arList[0],iVal)){
			printf("修改成功!");
		}
	}
	::CloseHandle(g_hProcess);
	return 0;
}

 

DWORD 是什么?

1 个二进制位称为 1bit , ( 1 位)

8 个二进制位称为 1Byte ,( 1 字节)

2 个字节 (2Byte=2*8bit) 就是 1Word    1 字, 16 位),

DWORDDOUBLE WORD )就是双字的意思,两个字( 32 位)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值