所有的进程都是由别的进程创建出来的,用鼠标双击运行一个程序的时候,实际上是由explorer.exe这个进程创建出来的那么这个时候有人可能会问,所有的进程都是由其他进程创建出来的,那么第一个进程呢?第一个进程其实是由操作系统内核进行创建的
进程的创建过程:
- 映射EXE文件
- 创建内核对象EPROCESS(一个进程对应一个EPROCESS)
- 映射系统DLL(ntdll.dll)
- 创建线程内核对象ETHREAD
- 系统启动线程
映射DLL(ntdll.LdrInitializeThunk)
线程开始执行
可以在第4步与第5步之间做一些猥琐的事情,怎么在第4步与第5步之间搞事情呢???
可以在CreateProcess这个函数的第6个参数__in DWORD dwCreationFlags,,将其设置为CREATE_SUSPENDED,然后线程就会被挂起,然后在这个地方进行PE映像切换,这个在《逆向工程核心原理》第56章有讲,因为这里是进程的创建过程,所以对PE影响切换不再描述
创建进程主要是用到一个API CreateProcess
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName, //进程完整路径名
__inout_opt LPTSTR lpCommandLine, //命令行参数
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, //子进程句柄是否可以被继承,一般为NULL
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, //主线程句柄是否可以被继承,一般为NULL
__in BOOL bInheritHandles, //是否可以继承句柄
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment, //NULL,这个参数没什么用
__in_opt LPCTSTR lpCurrentDirectory, //传给子进程的工作目录,如果为NULL,则与本进程的工作目录相同
__in LPSTARTUPINFO lpStartupInfo, //启动信息,由父进程传给子进程
__out LPPROCESS_INFORMATION lpProcessInformation //进程信息
);
typedef struct _STARTUPINFO {
DWORD cb; //当前结构体的大小,为了后续扩展而设置
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFO,
*LPSTARTUPINFO;
注意:
可以用GetStartupInfo来获取当前启动信息,这个可以用于反调试,因为你通过双击运行程序获取的启动参数 和 用OD启动程序获取的启动信息有些参数是不一样的,因此可以作为反调试的手段