进程相关的API函数
0x01. ID与句柄

如果我们成功创建一个进程之后,CreateProcess会返回四个数据,id和句柄
句柄的话就是 当前进程私有的句柄表索引(这是当前进程,给别进程也没用)
每个进程都有一张自己的句柄表,这是私有的句柄表;
而操作系统也有一张,叫全局句柄表,里面包含了所有的正在运行的进程和线程
两种私有和全局的结构都是一样的

看下代码,这个就是进程句柄,当进程创建成功后,这就是当前进程的句柄(私有)
进程ID就是全局句柄表中的编号,也就是索引 (全局)
这个进程ID是全局的,唯一的,但是它不会永远不变的,当进程死了之后,再开启,ID就会变
这边就使用代码来验证一下
#include <stdio.h>
#include <windows.h>
BOOL CreateChildProcess(PTCHAR szChildProcessName, PTCHAR szCommandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
//创建子进程 返回成功与失败
if (!CreateProcess(
szChildProcessName, //对象名称(完整的路径+exe)
szCommandLine, //命令行
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
0, //没有创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录,可以自己设置目录
&si, //STARTUPINFOW结构体详细信息
&pi) //PROCESS_INFOMATION结构体进程信息
)
{
printf("CreateChildProces Error: %d\n", GetLastError());
return FALSE;
}
//打印进程
printf("PID:%d ", pi.dwProcessId);
printf("进程句柄:%#x\n", pi.hProcess);
//printf("线程ID:%d ", pi.dwThreadId);
//printf("线程句柄:%#x\n", pi.hThread);
//获取进程信息
/*SuspendThread(pi.hThread);
ResumeThread(pi.hThread);*/
//释放句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
int main(int argc, char* argv[])
{
//TCHAR szApplicationName[] = TEXT("D:/Program Files/Tencent/QQ/Bin/QQScLauncher.exe");
TCHAR szApplicationName[] = TEXT("C:/Users/86183/Desktop/shellcode.exe");
//TCHAR szCmdline[] = TEXT("ipconfig");
CreateChildProcess(szApplicationName, NULL);
getchar();
return 0;
}
我们先把main函数的代码注释掉,然后再修改一下

我们通过程序知道了句柄是 0xf8
int main(int argc, char* argv[])
{
HANDLE hProcess;
hProcess - (HANDLE)0xf8;
//hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 0x);
if (!TerminateProcess(hProcess, 1))
{
printf("终止进程失败: %d \n", GetLastError());
}
/*
//TCHAR szApplicationName[] = TEXT("D:/Program Files/Tencent/QQ/Bin/QQScLauncher.exe");
TCHAR szApplicationName[] = TEXT("C:/Users/86183/Desktop/shellcode.exe");
//TCHAR szCmdline[] = TEXT("ipconfig");
CreateChildProcess(szApplicationName, NULL);
*/
getchar();
return 0;
}
改好后如上
我们把A进程的句柄赋值给B进程,然后我们直接运行看看

看到了这边得到了报错码 6,我们直接去查看下这是什么错误

这就验证我们的念想了,每个进程中的句柄都是私有的,把A进程的句柄给 B进程是没有用的,会显示句柄无效
我们知道PID是公有的,那我们就可以用PID试试,换种玩法,涉及到了新函数,OpenProcess

f1 查看下是什么,OpenProcess打开已经存在的一个进程,有三个参数
直接查看最后一个,获取PID进行识别,因为PID是全局的,所以可以识别
第二个参数,判断打开的进程允不允许子进程是否继承它(父进程就是我写的这个程序)
第一个参数,你要打开的进程希望拥有什么权利,是拥有创建进程的权利,还是创建进程的,还是所有的

当我们启动这个进程的时候就会杀掉下面那个程序,最后发现成功关闭了
0x02. 以挂起的形式创建进程
CreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags, /
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
我们F1看下第 6 个参数 dwCreationFlags 是什么

其实我们之前创建的代码都是公用一个窗口


这是CreateProcess 的CreationFlags 可以选择新创建一个控制台,具体可以自己试试
然后这边以挂起的方式创建,流程就会变
1、映射EXE文件
2、创建内核对象`EPROCESS`
3、映射系统DLL(ntdll.dll)
4、创建线程内核对象`ETHREAD`
5、如果是挂起的方式创建的:
然后就能在这边做其他的...
....
6、恢复以后再执行
映射DLL(ntdll.LdrlnitializeThunk)
线程开始执行

当走到这的时候进程已经创建好了,还有映射和线程还没做,所以我们可以在下面做些小动作

具体还可以换成恶意程序,这边使用for循环来演示,如果这个循环没有执行完,这个进程就不会启动
执行完了也不能继续跑,因为我们要放开它,让它继续跑,要使用 ResumeThread() 这个函数

实验代码就在如下:
#include <stdio.h>
#include <windows.h>
BOOL CreateChildProcess(PTCHAR szChildProcessName, PTCHAR szCommandLine)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
//创建子进程 返回成功与失败
if (!CreateProcess(
szChildProcessName, //对象名称(完整的路径+exe)
szCommandLine, //命令行
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
CREATE_SUSPENDED, //没有创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录,可以自己设置目录
&si, //STARTUPINFOW结构体详细信息
&pi) //PROCESS_INFOMATION结构体进程信息
)
{
printf("CreateChildProces Error: %d\n", GetLastError());
return FALSE;
}
//打印进程
printf("PID:%d ", pi.dwProcessId);
printf("进程句柄:%#x\n", pi.hProcess);
for (int i = 0; i < 5; i++)
{
Sleep(1000);
printf("---------------------------\n");
}
ResumeThread(pi.hThread);
//printf("线程ID:%d ", pi.dwThreadId);
//printf("线程句柄:%#x\n", pi.hThread);
//获取进程信息
/*SuspendThread(pi.hThread);
ResumeThread(pi.hThread);*/
//释放句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return TRUE;
}
int main(int argc, char* argv[])
{
//HANDLE hProcess;
////hProcess = (HANDLE)0xf8;
//hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 6124);
//if (!TerminateProcess(hProcess, 1))
//{
// printf("终止进程失败: %d \n", GetLastError());
//}
//TCHAR szApplicationName[] = TEXT("D:/Program Files/Tencent/QQ/Bin/QQScLauncher.exe");
TCHAR szApplicationName[] = TEXT("C:/Users/86183/Desktop/shellcode.exe");
//TCHAR szCmdline[] = TEXT("ipconfig");
CreateChildProcess(szApplicationName, NULL);
getchar();
return 0;
}
然后CreateProcess还有四个参数没讲
CreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment, //使用父进程环境变量,没啥的,NULL就可以了
LPCWSTR lpCurrentDirectory, //使用父进程目录作为当前目录,可以自己设置目录
LPSTARTUPINFOW lpStartupInfo //STARTUPINFOW结构体详细信息
LPPROCESS_INFORMATION lpProcessInformation //PROCESS_INFOMATION结构体进程信息
);
int main(int argc, char* argv[])
{
//HANDLE hProcess;
////hProcess = (HANDLE)0xf8;
//hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 6124);
//if (!TerminateProcess(hProcess, 1))
//{
// printf("终止进程失败: %d \n", GetLastError());
//}
//TCHAR szApplicationName[] = TEXT("D:/Program Files/Tencent/QQ/Bin/QQScLauncher.exe");
//TCHAR szApplicationName[] = TEXT("C:/Users/86183/Desktop/shellcode.exe");
//TCHAR szCmdline[] = TEXT("ipconfig");
//CreateChildProcess(szApplicationName, NULL);
wchar_t strModule[256];
GetModuleFileName(NULL, strModule, 256); //获取当前exe所在的路径(得到当前模块路径)
wchar_t strWork[1000];
int i = 1000;
GetCurrentDirectory(1000, strWork); //得到当前工作路径
printf("模块路径: %s \n工作路径:%s \n", strModule, strWork);
getchar();
return 0;
}
exe在哪里,模块路径就在哪里
工作路径就是创建进程的地方
lpCurrentDirectory可以设置成null,那这个有什么意义吗?
比如我们之前读取文件函数
FILE* fp = fopen("A.exe","r")
这个时候就会在当前目录找,
0x03. 其他进程相关的API:
获取进程PID
GetCurrentProcessid
获取进程句柄
GetCurrentProcess
获取命令行
GetCommandLine
获取启动信息
GetStartupInfo
遍历进程ID
EnumProcesses
快照
CreateToolhelp32Snapshot
进程相关的API函数的更多相关文章
- 任务相关的API函数-uxTaskGetSystemState
uxTaskGetSystemState:此函数用于获取系统中所有的任务状态,每个任务的状态信息保存在一个TaskStatus_t类型的结构体里面.要使用此函数必须把 configUSE_TRACE_ ...
- 2、FreeRTOS任务相关API函数
1.任务相关的API函数 函数存在于task.c中,主要的函数有: xTaskCreate():使用动态的方法创建一个任务: xTaskCreatStatic():使用静态的方法创建一个任务(用的非常 ...
- Windows API 进程相关笔记
0. 前言 最近做了一个进程信息相关的项目,整理了一下自己做项目时的笔记,分享给大家 1. 相关概念 1.1 HANDLE 概念 HANDLE(句柄)是Windows操作系统中的一个概念. 在Wind ...
- FreeRTOS-05任务相关API函数
根据正点原子FreeRTOS视频整理 单片机:STM32F207VC FreeRTOS源码版本:v10.0.1 任务相关API函数: 1. main.c /* * */ #include " ...
- [Chapter 3 Process]Practice 3.1 相关知识:进程创建、fork函数
3.1 Using the program shown in the Figure3.30, explain what the output will be at LINE A 答案:LINE A 处 ...
- 串口编程的相关API函数
用户使用函数CreateFile()创建与指定串口相关联的文件,然后可以使用该函数返回的文件句柄进行串口参数设置.• 01 HANDLE hModem; //定义串口句柄02 hModem=Creat ...
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- Socket 之 API函数介绍
1.创建套接字──socket() 应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,其调用格式如下: SOCKET PASCAL FAR soc ...
随机推荐
- JVM学习(九)volatile应用
一.初认volatile 首先学习volatile关键字时,我们先简单的了解一下它能干啥: 工作内存与主内存同步延迟现象导致的可见性问题: 可通过synchronized或volatile关键字解决, ...
- docker zookeeper 集群搭建
#创建集群目录 mkdir /opt/cluster/zk cd /opt/cluster/zk #清理脏数据[可跳过] docker stop zk-2181 docker stop zk-2182 ...
- 刷题[GWCTF 2019]你的名字
解题思路 打开发现需要输入名字,猜测会有sql注入漏洞,测试一下发现单引号被过滤了,再fuzs下看看过滤了哪些 长度为1518和1519的都有过滤,测试一下,感觉不是sql注入了.那还有什么呢,考虑了 ...
- Java程序员面试学习资料汇总
整理了一些关于Java程序员面试的书籍及免费资料. 一.书籍篇1)<Offer来了:Java面试核心知识点精讲(原理篇)>精讲Java面试必需的JVM原理.Java基础.并发编程.数据结构 ...
- 简单渗透测试流程演示(445端口、IPC$、灰鸽子)
目录 一.实验流程 二.实验过程 2.1 信息收集 2.2 利用过程 2.3 暴力破解系统密码之445 2.4 通过木马留后门 一.实验流程 0.授权(对方同意被渗透测试才是合法的.)1.信息收集 ...
- Linux里面的压缩和解压类指令
gzip/gunzip 指令 ( .gz 不能压缩目录) gzip 用于压缩文件, gunzip 用于解压的 . gzip gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后 ...
- 项目里出现两个配置类继承WebMvcConfigurationSupport时,为什么只有一个会生效(源码分析)
为什么我们的项目里出现两个配置类继承WebMvcConfigurationSupport时,只有一个会生效.我在网上找了半天都是说结果的,没有人分析源码到底是为啥,博主准备讲解一下,希望可以帮到大家! ...
- Maven环境搭建及常用命令、生命周期
一.下载maven包,解压 二.配置环境变量,MAVEN_PATH=解压路径 添加到path中 三.测试 mvn -v 查看maven版本 四.设置本地仓库的路径 在conf文件夹下的setting ...
- 固件(Firmware)
来源:https://baike.baidu.com/item/%E5%9B%BA%E4%BB%B6/627829 固件 固件(Firmware)就是写入EPROM(可擦写可编程只读存储器)或EE ...
- linux下各种骚操作
(备注:不定时更新) 1. ctrl+l 清屏快捷键,相当于clear 2. !+命令开头部分 执行最近执行的此条命令 ### 如!vi 编辑上一次用vi打开的文件, 3. echo $$ ...