WIN32 - 进程

本文介绍了Windows操作系统中的进程概念,强调进程作为操作系统的器官,提供了进程内存空间的地址划分,并详细阐述了进程的创建过程,尤其是通过`CreateProcess()`函数。还探讨了如何利用`lpStartupInfo`结构体进行程序的反调试,以防止被"不法分子"调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程–操作系统的器官

现在的操作系统都是多进程的操作系统1587613825378

1.什么是进程?

​ 进程提供程序所需要的资源,如:数据、代码等等。

​ 程序运行的状态和进程没有关系,可以看成是空间状态。

​ 现实生活类比,进程相当于房子,房子里边有各种各样的资源(桌子、椅子、电脑)。线程相当于使用这些资源的人。

1. 验证进程是一个空间的概念
 ![1587614214080](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9naXRlZS5jb20vc210bGcvUGljR28vcmF3L21hc3Rlci9pbWcvMjAyMDA1MTMwMDA3MDcucG5n?x-oss-process=image/format,png)
 打开一个程序,用DTDEBUG附加它。
2. 一个进程地址范围 0~FFFFFFFF = 4 GB 但是一个进程只用低2GB的进程空间 0~7FFFFFFF ,高2GB的进程空间80000000 ~ FFFF FFFF 是操作系统内核使用的。 

2.进程内存空间的地址划分

1587615279749

  1. 空指针赋值区:从来没有人使用,操作系统也没有使用。
  2. 用户模式区:我们使用的拉~
  3. 64KB禁入区:我们代码跑不到哪儿,操作系统也没有使用。(用户空间的前后64KB都没有使用)
  4. 内核

在Windows里,这些内存空间是虚拟的内存,名义上有4GB,而实际上分配的远远没有4GB,只有线程真正使用的时候才会真正分配。(段和页的管理)。

4GB的进程 就 只由一个文件组成吗?

​ 不是的,一个空间进程 由多个文件组成,exe和各种dll.

这些程序都遵守PE文件结构 DLL,EXE


3.一个程序如何变成进程?

### 进程创建的过程:

一个进程 都是由别的进程,创建出来的。 也就是说进程不可能平白无故的出来。

在windows下,双击运行程序,都是由explorer.exe 来创建你双击程序的进程的。

  1. 任何进程都是别的进程创建的:CreateProcess()

  2. 进程的创建过程

    1. 映射exe文件
    2. 创建内核对象EPROCESS
    3. 映射系统dll(ntdll.dll)
    4. 创建 线程内核对象ETHREAD
    5. 系统启动线程(一个进程必须有一个线程)
      1. 映射DLL(ntdll.LdrInitializeThunk)
      2. 线程开始执行

    1587628983354


创建进程

  1. 进程的创建 CreateProcess()

    BOOL CreateProcessA(
      LPCSTR                lpApplicationName,  //name of executable module
      LPSTR                 lpCommandLine,		//command line string
      LPSECURITY_ATTRIBUTES lpProcessAttributes, //SD
      LPSECURITY_ATTRIBUTES lpThreadAttributes,	 //SD	
      BOOL                  bInheritHandles,	//handle inheritance option
      DWORD                 dwCreationFlags,	//creation flags
      LPVOID                lpEnvironment,		//new environment block
      LPCSTR                lpCurrentDirectory,	//current directory name
      LPSTARTUPINFOA        lpStartupInfo,		//startup infomation
      LPPROCESS_INFORMATION lpProcessInformation //process information
    );
    

lpStartupInfo

程序的反调试:

CreateProcess的参数lpStartupInfo:

lpStartupInfo是一个结构体指针,指向StartupInfo结构

StartupInfo结构:

typedef struct _STARTUPINFOA {
  DWORD  cb;			//size of the structure in bytes
  LPSTR  lpReserved;	//must be null
  LPSTR  lpDesktop;		//The name of the desktop, or the name of both the desktop and window station for this process.
  LPSTR  lpTitle;		//创建的子进程窗口的标题,默认为父进程标题,如果没有窗口为0
  DWORD  dwX;			
  DWORD  dwY;
  DWORD  dwXSize;
  DWORD  dwYSize;
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;		//标识startup的成员是否被使用
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;

在windows,默认我们双击运行程序,进程是由explorer.exe给我们创建子进程的。

而StartupInfo结构是由调用者填充的,我们双击运行查看一下explorer给我们填充的内容。

1587637792067

在使用调试工具(dtdebug、od)运行,查看一下StartupInfo成员属性

1587637932605

可以发现,不同caller创建进程,给StartupInfo结构填充的属性是不同的。

那么我们就可以通过StartupInfo的属性,来判断我们写的程序是否将被“不法分子”调试,如果发现StartupInfo的属性和正常Window创建进程的属性不同,那么我们加一个判断,不同的时候我们退出我们的程序,于是就给我们程序添加上了反调试的功能。

VOID AntiDebug(){
	STARTUPINFO si;//子进程的信息,由父进程填充
	GetStartupInfo(&si);  
	//Retrieves the contents of the STARTUPINFO structure that was specified when the calling process was created.
    /*
    	void GetStartupInfo(
  LPSTARTUPINFOW lpStartupInfo //A pointer to a STARTUPINFO structure that receives the startup information.
	);
    */
    
    printf("dwX:%x dwY:%x dwXCountChars:%x dwYCountChars:%x dwFillAttribute:%x dwXSize:%x dwYSize:%x dwFlags:%x\n",si.dwX,si.dwY,si.dwXCountChars,si
		.dwYCountChars,si.dwFillAttribute,si.dwXSize,si.dwYSize,si.dwFlags); 
}

lpProcessInformation

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess; //进程句柄  用来标识每一个进程
  HANDLE hThread;	//线程句柄 每一个进程必须由一个线程
  DWORD  dwProcessId;	//进程id
  DWORD  dwThreadId;	//线程id
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;

2.代码测试

VOID AntiDebug(){
	STARTUPINFO si;//子进程的信息,由父进程填充
	GetStartupInfo(&si);
	printf("dwX:%x dwY:%x dwXCountChars:%x dwYCountChars:%x dwFillAttribute:%x dwXSize:%x dwYSize:%x dwFlags:%x\n",si.dwX,si.dwY,si.dwXCountChars,si
		.dwYCountChars,si.dwFillAttribute,si.dwXSize,si.dwYSize,si.dwFlags); 
    //通过父进程填充的StartUPInfo的成员属性,来判断程序是否是在调试器里的
}
bool CreateChildProcess(TCHAR* szChildProcessName,TCHAR* szCommandline){
	STARTUPINFO si;//IN 给你的子进程赋属性 一般全为空
	PROCESS_INFORMATION pi;//OUT 创建进程成功后,返回的子进程标识
	
    //#define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length))
	ZeroMemory(&si,sizeof(si));  
	ZeroMemory(&pi,sizeof(pi));
	if (!CreateProcess(
		szChildProcessName, //对象名称
		szCommandline,		//命令行参数
		NULL,				//不继承进程句柄
		NULL,				//不继承线程句柄
		FALSE,				//不继承句柄
		0,				//没有创建标志
		NULL,			//使用父进程环境变量
		NULL,			//使用父进程目录作为当前目录,可以自己设置目录
		&si,			//caller 填写的信息
		&pi				//out 创建的子进程的信息
		))
	{
	printf("Last error:%d \n",GetLastError());
	} 
	//打印进程的相关信息
	printf("进程句柄:%d ,线程句柄:%x  进程ID:%x,线程ID:%x",pi.hProcess,pi.hThread,pi.dwProcessId,pi.dwThreadId);

	//释放子进程句柄
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	return TRUE;
	//CreateProcess()

}

int _tmain(int argc, _TCHAR* argv[])
{
	TCHAR szApplicationName[] = TEXT("c://program files//internet explorer//iexplore.exe");
	TCHAR szCommand[] = TEXT("http://www.bing.cn/");
	CreateChildProcess(szApplicationName,szCommand);
	//AntiDebug();// 反调试
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值