进程–操作系统的器官
现在的操作系统都是多进程的操作系统
1.什么是进程?
进程提供程序所需要的资源,如:数据、代码等等。
程序运行的状态和进程没有关系,可以看成是空间状态。
现实生活类比,进程相当于房子,房子里边有各种各样的资源(桌子、椅子、电脑)。线程相当于使用这些资源的人。
1. 验证进程是一个空间的概念

打开一个程序,用DTDEBUG附加它。
2. 一个进程地址范围 0~FFFFFFFF = 4 GB 但是一个进程只用低2GB的进程空间 0~7FFFFFFF ,高2GB的进程空间80000000 ~ FFFF FFFF 是操作系统内核使用的。
2.进程内存空间的地址划分
- 空指针赋值区:从来没有人使用,操作系统也没有使用。
- 用户模式区:我们使用的拉~
- 64KB禁入区:我们代码跑不到哪儿,操作系统也没有使用。(用户空间的前后64KB都没有使用)
- 内核
在Windows里,这些内存空间是虚拟的内存,名义上有4GB,而实际上分配的远远没有4GB,只有线程真正使用的时候才会真正分配。(段和页的管理)。
4GB的进程 就 只由一个文件组成吗?
不是的,一个空间进程 由多个文件组成,exe和各种dll.
这些程序都遵守PE文件结构 DLL,EXE
3.一个程序如何变成进程?
### 进程创建的过程:
一个进程 都是由别的进程,创建出来的。 也就是说进程不可能平白无故的出来。
在windows下,双击运行程序,都是由explorer.exe 来创建你双击程序的进程的。
-
任何进程都是别的进程创建的:CreateProcess()
-
进程的创建过程
- 映射exe文件
- 创建内核对象EPROCESS
- 映射系统dll(ntdll.dll)
- 创建 线程内核对象ETHREAD
- 系统启动线程(一个进程必须有一个线程)
- 映射DLL(ntdll.LdrInitializeThunk)
- 线程开始执行
创建进程
-
进程的创建 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给我们填充的内容。
在使用调试工具(dtdebug、od)运行,查看一下StartupInfo成员属性
可以发现,不同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;
}