进程创建

admin 2024年3月1日10:57:24评论20 views字数 5122阅读17分4秒阅读模式

在C++中,有多种进程创建的方法 :WinExec、ShellExecute、CreateProcess、system、popen等,下面一一介绍并给出案例

1. WinExec

WinExec是一个过时的函数,用于在 Windows 操作系统中执行外部程序。它存在于早期版本的 Windows API 中,但自 Windows 2000 以后,Microsoft 已不再推荐使用它,Winexec通过返回值是否大于31来判断进程是否成功启动。函数原型:

 UINT WinExec(
   LPCSTR lpCmdLine,   //要执行的命令行或可执行文件的路径,可以直接传递参数
   UINT   uCmdShow     //表示应用程序窗口的显示方式,如SW_NORMAL、SW_HIDE、SW_MAXIMIZE等
 );

案例:

 void WinExecFunc(){  
     int result = WinExec("notepad.exe WinExec", SW_NORMAL);  
     if (result > 31) {  
         // WinExec 返回大于 31 表示成功启动  
         printf("Notepad started successfully.n");  
    } else {  
         printf("Failed to start Notepad.n");  
    }  
 }

2. ShellExecute

ShellExecute用于在 Windows 操作系统中执行外部程序、打开文档、浏览网页等任务的 Windows API 函数,根据文件关联来确定如何处理指定的文件,返回大于32的值代表成功,否则失败。函数原型:

 HINSTANCE ShellExecute(
   HWND    hwnd,          //窗口句柄,可选一般是父窗口的,不关联可以用null
   LPCTSTR lpOperation,   //要执行的动作,例如edit、explore、find、open、print、NULL等
   LPCTSTR lpFile,        //要执行的文件、文档、程序或URL的路径
   LPCTSTR lpParameters,  //要传进去的参数
   LPCTSTR lpDirectory,   //执行程序的默认目录
   INT     nShowCmd       //窗口显示方式,如SW_NORMAL、SW_HIDE、SW_MAXIMIZE等
 );

案例:

 void ShellExecFunc(){  
     HINSTANCE hInst = ShellExecute(NULL, "open", "notepad.exe", "ShellExecute", NULL, SW_SHOWNORMAL);  
 
     if ((int)(intptr_t)hInst > 32) {  
         printf("Notepad started successfully.n");  
    } else {  
         printf("Failed to start Notepad. Error code: %dn", (int)(intptr_t)hInst);  
    }  
 }

3. CreateProcess

CreateProcess是Windows API 中用于创建新进程的函数,通常用于执行外部可执行文件,非0值表示成功,否则失败。函数原型:

 BOOL CreateProcess(
   LPCSTR               lpApplicationName,    //要执行的程序的名称
   LPSTR                lpCommandLine,        //要执行的命令,可执行文件的路径和参数。
   LPSECURITY_ATTRIBUTES lpProcessAttributes, //是否可以由子进程继承返回的新进程对象的句柄
   LPSECURITY_ATTRIBUTES lpThreadAttributes,  //是否可以由子进程继承返回的新进程对象的句柄
   BOOL                 bInheritHandles,      //如果参数为true,则调用进程中每个可继承句柄都由新进程来继承
   DWORD                dwCreationFlags,      //指定创建进程的方式和优先级,CREATE_NEW_CONSOLE是创建一个新控制台、CREATE_SUSPENDED表示新进程的主线程会以暂停的状态来创建,直到使用ResumeThread函数时才运行、DETACHED_PROCESS对于控制台进程,新进程没有访问父进程控制台的权限.新进程可以通过allocconsole函数自己创建一个新的控制台
   LPVOID               lpEnvironment,        //指向新进程的环境块
   LPCSTR               lpCurrentDirectory,   //指向进程当前目录的路径,如果为null,则新进程使用与调用进程相同的驱动器和目录
   LPSTARTUPINFO        lpStartupInfo,        //指向一个用于决定新进程的主窗体如何显示的startupinfo结构体
   LPPROCESS_INFORMATION lpProcessInformation //指向一个用来接收新进程的识别信息的process_information结构体
 );

案例:

 void CreateProcessFunc(){  
     STARTUPINFO si;  
     PROCESS_INFORMATION pi;  
 
     ZeroMemory(&si, sizeof(STARTUPINFO));  
     si.cb = sizeof(STARTUPINFO);  
     ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));  
 
     // 启动记事本  
     if (CreateProcess(  
             NULL,                 // 应用程序名称,可以设为 NULL           "notepad.exe CreateProcess",       // 命令行,表示要启动记事本  
             NULL,                 // 进程安全属性,可以设为 NULL           NULL,                 // 线程安全属性,可以设为 NULL           FALSE,               // 不继承句柄  
             0,                    // 标志,通常为 0           NULL,                 // 环境变量,可以设为 NULL           NULL,                 // 当前工作目录,可以设为 NULL           &si,                 // STARTUPINFO 结构  
             &pi                   // PROCESS_INFORMATION 结构  
    )) {  
         printf("Notepad started successfully.n");  
         CloseHandle(pi.hProcess); // 关闭进程句柄  
         CloseHandle(pi.hThread);  // 关闭线程句柄  
    } else {  
         printf("Failed to start Notepad. Error code: %dn", GetLastError());  
    }  
 }

4. system

system是标准C/C++库中的函数,用于执行操作系统命令,返回非0值代表执行失败,函数原型:

 int system(
    const char *command  //command你要执行的命令,可以带参数
 );

案例:

 void systemFunc(){  
     int result = system("notepad system");  
 
     if (result == 0) {  
         printf("Command executed successfully.n");  
    } else {  
         printf("Command failed to execute.n");  
    }  
 }

5. popen

popen是标准C库中的函数,用于创建一个管道并启动子进程执行外部程序,这个在上一篇文章《远程线程注入》中的tasklist我就用的这个,函数原型:

FILE *popen(
const char *command, //要执行的命令
const char *mode //文件访问模式,r、w
);

案例代码:

void popenFunc(){  
FILE *fp;
char buffer[128];
// 打开管道并执行命令
fp = popen("notepad popen", "r");
if (fp == NULL) {
printf("Failed to execute command.n");
exit(0);
}
// 读取子进程的输出
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("Output: %s", buffer);
}
// 关闭管道
pclose(fp);
}

另,补充一下

远程线程注入dll的时候无法多次注入,刚刚找到了一个方法卸载掉dll(参数与注入的一致):

BOOL UnInjectDll(DWORD dwProcessId, char *ptszDllFile)  
{
// 参数无效
if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))
{
return false;
}
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
// 获取模块快照
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (INVALID_HANDLE_VALUE == hModuleSnap)
{
return false;
}
MODULEENTRY32 me32;
memset(&me32, 0, sizeof(MODULEENTRY32));
me32.dwSize = sizeof(MODULEENTRY32);
// 开始遍历
if (FALSE == ::Module32First(hModuleSnap, &me32))
{
::CloseHandle(hModuleSnap);
return false;
}
// 遍历查找指定模块
bool isFound = false;
do
{
isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile));
if (isFound) // 找到指定模块
{
break;
}
} while (TRUE == ::Module32Next(hModuleSnap, &me32));
::CloseHandle(hModuleSnap);
if (false == isFound)
{
return false;
}
// 获取目标进程句柄
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == hProcess)
{
return false;
}
// 从 Kernel32.dll 中获取 FreeLibrary 函数地址
LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
if (NULL == lpThreadFun)
{
::CloseHandle(hProcess);
return false;
}
// 创建远程线程调用 FreeLibrary hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr /* 模块地址 */, 0, NULL);
if (NULL == hThread)
{
::CloseHandle(hProcess);
return false;
}
// 等待远程线程结束
::WaitForSingleObject(hThread, INFINITE);
// 清理
::CloseHandle(hThread);
::CloseHandle(hProcess);
return true;
}

dll卸载代码引用:https://www.cnblogs.com/szyicol/p/13023428.html

原文始发于微信公众号(天幕安全团队):进程创建

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月1日10:57:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   进程创建https://cn-sec.com/archives/2098314.html

发表评论

匿名网友 填写信息