获取系统中所有进程&线程信息
读书笔记--[计算机病毒解密与对抗]
- 遍历进程&线程程序
- 终止进程
- 获取进程信息
- 获取进程内模块信息
- 获取进程命令行参数
代码运行环境:Win7 x64
VS2012 Update3
遍历系统中所有进程
- #include <stdio.h>
- #include <windows.h>
- #include <TlHelp32.h>
- int main()
- {
- // 为进程的所有线程拍个快照
- HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if( hSnapshort==INVALID_HANDLE_VALUE )
- {
- printf("CreateToolhelp32Snapshot调用失败!\n");
- return -1;
- }
- // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
- PROCESSENTRY32 stcProcessInfo;
- stcProcessInfo.dwSize = sizeof(stcProcessInfo);
- BOOL bRet = Process32First(hSnapshort, &stcProcessInfo);
- printf("进程名\t\t\t 进程ID\t 线程数\t 父进程ID\n");
- while (bRet)
- {
- printf("%ls\t\t %d\t %d\t %d\n", stcProcessInfo.szExeFile, stcProcessInfo.th32ProcessID, stcProcessInfo.cntThreads, stcProcessInfo.th32ParentProcessID);
- bRet = Process32Next(hSnapshort, &stcProcessInfo);
- }
- CloseHandle(hSnapshort);
- system("pause");
- return 0;
- }

#include <stdio.h>
#include <windows.h>
#include <TlHelp32.h> int main()
{
// 为进程的所有线程拍个快照
HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if( hSnapshort==INVALID_HANDLE_VALUE )
{
printf("CreateToolhelp32Snapshot调用失败!\n");
return -1;
} // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
PROCESSENTRY32 stcProcessInfo;
stcProcessInfo.dwSize = sizeof(stcProcessInfo); BOOL bRet = Process32First(hSnapshort, &stcProcessInfo); printf("进程名\t\t\t 进程ID\t 线程数\t 父进程ID\n"); while (bRet)
{
printf("%ls\t\t %d\t %d\t %d\n", stcProcessInfo.szExeFile, stcProcessInfo.th32ProcessID, stcProcessInfo.cntThreads, stcProcessInfo.th32ParentProcessID); bRet = Process32Next(hSnapshort, &stcProcessInfo);
} CloseHandle(hSnapshort); system("pause");
return 0;
}
遍历系统中所有线程
- #include <stdio.h>
- #include <windows.h>
- #include <TlHelp32.h>
- int main()
- {
- // 为进程的所有线程拍个快照
- HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
- if( hSnapshort==INVALID_HANDLE_VALUE )
- {
- printf("CreateToolhelp32Snapshot调用失败!\n");
- return -1;
- }
- // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
- THREADENTRY32 stcThreadInfo;
- stcThreadInfo.dwSize = sizeof(stcThreadInfo);
- BOOL bRet = Thread32First(hSnapshort, &stcThreadInfo);
- DWORD dwProId = -1; // 保存上一个线程的进程ID
- unsigned unCount=0;
- while (bRet)
- {
- if( dwProId!=stcThreadInfo.th32OwnerProcessID )
- {
- // 记录PID与所属PID不同,遍历至不属于同一进程的线程
- if( dwProId!=-1 )
- {
- // 不是第一次遍历
- printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
- unCount = 0;
- printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
- }
- dwProId = stcThreadInfo.th32OwnerProcessID;
- printf("进程%d:\n\n ", dwProId);
- printf("线程TID\t\t线程所属进程PID\t\t线程优先级\n");
- }
- printf(" %d\t\t\t%d\t\t\t %d\n",stcThreadInfo.th32ThreadID, stcThreadInfo.th32OwnerProcessID, stcThreadInfo.tpBasePri);
- unCount++;
- bRet = Thread32Next(hSnapshort, &stcThreadInfo);
- }
- printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
- unCount = 0;
- printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
- CloseHandle(hSnapshort);
- system("pause");
- return 0;
- }

#include <stdio.h>
#include <windows.h>
#include <TlHelp32.h> int main()
{
// 为进程的所有线程拍个快照
HANDLE hSnapshort = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if( hSnapshort==INVALID_HANDLE_VALUE )
{
printf("CreateToolhelp32Snapshot调用失败!\n");
return -1;
} // 获得线程列表,里面记录了线程的详细信息,再使用Thread32First和Thread32Next遍历快照中记录的每个线程信息
THREADENTRY32 stcThreadInfo;
stcThreadInfo.dwSize = sizeof(stcThreadInfo); BOOL bRet = Thread32First(hSnapshort, &stcThreadInfo);
DWORD dwProId = -1; // 保存上一个线程的进程ID
unsigned unCount=0; while (bRet)
{
if( dwProId!=stcThreadInfo.th32OwnerProcessID )
{ // 记录PID与所属PID不同,遍历至不属于同一进程的线程
if( dwProId!=-1 )
{
// 不是第一次遍历
printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
unCount = 0;
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n");
} dwProId = stcThreadInfo.th32OwnerProcessID;
printf("进程%d:\n\n ", dwProId);
printf("线程TID\t\t线程所属进程PID\t\t线程优先级\n");
} printf(" %d\t\t\t%d\t\t\t %d\n",stcThreadInfo.th32ThreadID, stcThreadInfo.th32OwnerProcessID, stcThreadInfo.tpBasePri);
unCount++; bRet = Thread32Next(hSnapshort, &stcThreadInfo);
} printf("\n进程%d的线程总数:%d\n", dwProId, unCount);
unCount = 0;
printf("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n\n"); CloseHandle(hSnapshort); system("pause");
return 0;
}
在win程序设计中除了使用ToolHelp函数可以完成进程的遍历操作之外(程序需要包含tlhelp32.h),还可以使用Psapi函数EnumProcess函数,但是它只能获取进程的ID。
进程相关操作--终止进程
- void WINAPI ExitProcess(
- UINT uExitCode; // 进程退出码
- );

void WINAPI ExitProcess(
UINT uExitCode; // 进程退出码
);
在程序的任意一个地方调用这个函数都会立即终止自身进程的运行。在C/C++中应避免直接调用这个函数,因为C/C++运行期库得不到通知,∴没有机会去调用全局或静态C/C++对象的析构函数。
- BOOL WINAPI TerminateProcess(
- HANDLE hProcess, // 要结束的进程句柄
- UINT uExitCode // 指定目标进程的退出码
- );

BOOL WINAPI TerminateProcess(
HANDLE hProcess, // 要结束的进程句柄
UINT uExitCode // 指定目标进程的退出码
);
我们必须通过获取目标进程的ID,然后再获取这个进程句柄,然后才可以使用这个句柄操作此进程。可以使用如下函数:
- HANDLE WINAPI OpenProcess(
- DWORD dwDesiredAccess, // 指定得到的句柄具有的访问权限
- BOOL bInheritHandle, // 指定返回的句柄是否可被继承
- DWORD dwProcessId // 指定要打开的进程ID
- );

HANDLE WINAPI OpenProcess(
DWORD dwDesiredAccess, // 指定得到的句柄具有的访问权限
BOOL bInheritHandle, // 指定返回的句柄是否可被继承
DWORD dwProcessId // 指定要打开的进程ID
);
这个函数打开一个存在的进程,返回具有指定权限的句柄。
获取进程的其他信息
- 获取进程对应的可执行程序路径
- DWORD WINAPI GetProcessImageFileNameA (
- _In_ HANDLE hProcess, // 要获得文件路径的进程句柄
- _Out_writes_(nSize) LPSTR lpImageFileName, // 保存文件路径的内存首地址
- _In_ DWORD nSize<span style="white-space:pre"> </span>// 保存文件路径的内存大小
- );

DWORD WINAPI GetProcessImageFileNameA (
_In_ HANDLE hProcess, // 要获得文件路径的进程句柄
_Out_writes_(nSize) LPSTR lpImageFileName, // 保存文件路径的内存首地址
_In_ DWORD nSize// 保存文件路径的内存大小
);
注意使用上述函数获取的路径并不是磁盘驱动器的路径,而是内核路径,形如: " \Device\HarddiskVolume1\WINDOWS\System32\notepad.exe ",通常此路径中的Device表示硬盘驱动器,HarddiskVolume表示分区数字表示具体分区号(1表C 2表D。。。),所以对路径需要进行转换。
- #include <stdio.h>
- #include <windows.h>
- #include <tchar.h>
- #include <TlHelp32.h>
- #include <Psapi.h>
- #pragma comment(lib, "psapi.lib")
- void TransPath(PTCHAR pPath)
- {
- // 获取驱动器字符串位置
- PTCHAR pFind = _tcsstr(pPath, _T("HarddiskVolume"));
- if( pFind==NULL )
- return;
- TCHAR tcDriver[5] = {'C', 'D', 'E', 'F', 'G'}; // 可写满24个字符,这里只是一个demo
- int nNum = pFind[_tcslen(_T("HarddiskVolume"))] - 0x30;
- PTCHAR pTemp = _tcsstr(pFind, _T("\\"));
- // 拼接字符串的缓冲区
- TCHAR tcBuffer[MAX_PATH];
- memset(tcBuffer, 0, MAX_PATH*sizeof(TCHAR));
- _stprintf_s(tcBuffer, _T("%c:%s"), tcDriver[nNum-1], pTemp);
- memset(pPath, 0, _tcslen(pPath));
- _tcscpy_s(pPath, 256, tcBuffer);
- }
- int main()
- {
- // 传入\Device\HarddiskVolume1\WINDOWS\System32\notepad.exe
- DWORD dwNeed;
- PDWORD pdwMem = new DWORD[4000];
- BOOL bRet = EnumProcesses(pdwMem, 4000, &dwNeed);
- if( !bRet )
- {
- if(pdwMem!=NULL)
- {
- delete[] pdwMem;
- pdwMem = nullptr;
- return -1;
- }
- }
- int nNumProc = dwNeed/4;
- HANDLE hProcess = NULL;
- DWORD dwPathLength = 0;
- TCHAR tcBuffer[256] = {0};
- for( int i=0; i<nNumProc; i++ )
- {
- hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pdwMem[i]);
- if( hProcess==NULL )
- continue;
- memset(tcBuffer, 0, 256*sizeof(TCHAR));
- dwPathLength = GetProcessImageFileName(hProcess, tcBuffer, 256);
- if( dwPathLength!=0 )
- {
- TransPath(tcBuffer);
- printf("%08d %ls\n",pdwMem[i], tcBuffer);
- }
- CloseHandle(hProcess);
- }
- if( pdwMem!=NULL )
- {
- delete[] pdwMem;
- pdwMem = NULL;
- }
- system("pause");
- return 0;
- }

#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <TlHelp32.h>
#include <Psapi.h> #pragma comment(lib, "psapi.lib") void TransPath(PTCHAR pPath)
{
// 获取驱动器字符串位置
PTCHAR pFind = _tcsstr(pPath, _T("HarddiskVolume"));
if( pFind==NULL )
return; TCHAR tcDriver[5] = {'C', 'D', 'E', 'F', 'G'}; // 可写满24个字符,这里只是一个demo int nNum = pFind[_tcslen(_T("HarddiskVolume"))] - 0x30; PTCHAR pTemp = _tcsstr(pFind, _T("\\")); // 拼接字符串的缓冲区
TCHAR tcBuffer[MAX_PATH];
memset(tcBuffer, 0, MAX_PATH*sizeof(TCHAR)); _stprintf_s(tcBuffer, _T("%c:%s"), tcDriver[nNum-1], pTemp);
memset(pPath, 0, _tcslen(pPath));
_tcscpy_s(pPath, 256, tcBuffer);
} int main()
{
// 传入\Device\HarddiskVolume1\WINDOWS\System32\notepad.exe
DWORD dwNeed;
PDWORD pdwMem = new DWORD[4000];
BOOL bRet = EnumProcesses(pdwMem, 4000, &dwNeed); if( !bRet )
{
if(pdwMem!=NULL)
{
delete[] pdwMem;
pdwMem = nullptr;
return -1;
}
} int nNumProc = dwNeed/4;
HANDLE hProcess = NULL;
DWORD dwPathLength = 0;
TCHAR tcBuffer[256] = {0}; for( int i=0; i<nNumProc; i++ )
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pdwMem[i]); if( hProcess==NULL )
continue; memset(tcBuffer, 0, 256*sizeof(TCHAR));
dwPathLength = GetProcessImageFileName(hProcess, tcBuffer, 256); if( dwPathLength!=0 )
{
TransPath(tcBuffer);
printf("%08d %ls\n",pdwMem[i], tcBuffer);
} CloseHandle(hProcess);
} if( pdwMem!=NULL )
{
delete[] pdwMem;
pdwMem = NULL;
} system("pause");
return 0;
}
- 获取进程内模块信息
- 获取进程命令行参数

- // 返回命令行参数字符串的首地址
- LPTSTR GetCommandLine(VOID);

// 返回命令行参数字符串的首地址
LPTSTR GetCommandLine(VOID);
获取指定进程的命令行参数,可以使用OD随意调试一个Win程序,如notepad.exe。在command窗口输入follow GetCommandLineA命令即可定位到该函数的实现代码。可以看到实现代码仅一行
- mov ax, dword ptr [7C8835F4]
- // 个人做测试的时候地址好像是7C8855F4

mov ax, dword ptr [7C8835F4]
// 个人做测试的时候地址好像是7C8855F4
也就是说进程的命令行参数被保存在内存中的固定位置,只要定位到GetCommandLineA的入口地址,跳过一个字节后取出一个dword值,这个值是一个指针,指向的内容即命令行参数的地址。现在的问题即得到远程进程中GetCommandLineA函数的入口地址即可得到该进程的命令行参数。获取指定模块中某个Win32API函数地址的函数是GetProcAddress。but这个函数仅可获取当前进程中API函数的地址,要获得远程进程中某个函数的地址就必须在远程进程中执行这个函数,需要使用远线程方法,本文暂时不涉及这个内容。换个思路:GetCommandLineA使用Kernel32.dll提供,这个库是系统基本库,几乎所有程序都会加载这个模块。而且对于NT架构所有进程加载Kernel32.dll的模块基址基本都是一致的,而GetCommandLineA在其库中的地址也是固定的。所以我们在本进程中得到的此函数地址和远程进程中该函数的地址是一致的(这个方法在我的电脑Win7x64中实验失败,应该因为程序的加载基址不固定了)。获取远程进程中数据使用ReadProcessMemory函数。
- BOOL WINAPI ReadProcessMemory(
- _In_ HANDLE hProcess, <span style="white-space:pre"> </span> // 远程进程句柄
- _In_ LPCVOID lpBaseAddress,<span style="white-space:pre"> </span> // 目标进程内存空间首地址
- _Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer, // 本进程内存空间首地址,存储读出的数据
- _In_ SIZE_T nSize,<span style="white-space:pre"> </span> // 要读取的字节数
- _Out_opt_ SIZE_T * lpNumberOfBytesRead<span style="white-space:pre"> </span> // 实际读取的字节数
- );

BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess, // 远程进程句柄
_In_ LPCVOID lpBaseAddress, // 目标进程内存空间首地址
_Out_writes_bytes_to_(nSize, *lpNumberOfBytesRead) LPVOID lpBuffer, // 本进程内存空间首地址,存储读出的数据
_In_ SIZE_T nSize, // 要读取的字节数
_Out_opt_ SIZE_T * lpNumberOfBytesRead // 实际读取的字节数
);
为保证此方法成功,应判断当前系统是否是NT系统,使用GetVersion函数获取当前系统的版本。返回值表示系统的版本信息,若是NT/2k/xp则返回值小于0x80000000,否则大于该值。虚拟机中XP实验成功。

获取系统中所有进程&线程信息的更多相关文章
- Android中获取系统上安装的APP信息
Version:0.9 StartHTML:-1 EndHTML:-1 StartFragment:00000099 EndFragment:00003259 Android中获取系统上安装的APP信 ...
- Linux 系统中僵尸进程
Linux 系统中僵尸进程和现实中僵尸(虽然我也没见过)类似,虽然已经死了,但是由于没人给它们收尸,还能四处走动.僵尸进程指的是那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸.配图源 ...
- [linux]top命令详解-实时显示系统中各个进程的资源占用状况
简介 top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按 ...
- 9.7 top:实时显示系统中各个进程的资源占用状况
top命令 用于实时地对系统处理器状态进行监控,它能够实时地显示系统中各个进程的资源占用状况.该命令可以按照CPU的使用.内存的使用和执行时间对系统任务进程进行排序显示,同时top命令还可以通过交互式 ...
- Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免?
如题 Unix/Linux系统中僵尸进程是如何产生的?有什么危害?如何避免? 一个进程在调用exit命令结束自己的生命的时候,其实他并没有真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结 ...
- java中的getProperty()方法。获取系统中属性名为key的属性对应的值
总结:getProperty方法:获取系统中属性名为key的属性对应的值,系统中常见的属性名以及属性如下: 现在用getProperty()的方法,获取系统信息代码: package com.aaa; ...
- linux系统中的进程状态分析
转载地址:https://blog.csdn.net/shenwansangz/article/details/51981459 linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序, ...
- 显示系统中所有的socket信息
netstat -aon /proc/net/tcp /proc/net/udp /proc/net/unix 相关的代码是:tcp4_seq_show(struct seq_file *file, ...
- linux系统中的进程
一.fork 在类unix系统中,我们所执行的任何程序,都是由父进程(parent process)所产生出来的一个子进程(child process),子进程在结束后,将返回到父进程去.此一现象被称 ...
随机推荐
- php如何防止图片盗用/盗链的两种方法(转)
图片防盗链有什么用? 防止其它网站盗用你的图片,浪费你宝贵的流量.本文章向大家介绍php防止图片盗用/盗链的两种方法 Apache图片重定向方法 设置images目录不充许http访问 Apache服 ...
- Windows 服务的安装(1)
在上一篇文章中创建了window服务 http://www.cnblogs.com/netqq/p/4182259.html 在本篇中将教会你如何安装这个服务 服务程序的开发和运行环境均为:windo ...
- ORACLE常用数值函数、转换函数、字符串函数
本文更多将会介绍三思在日常中经常会用到的,或者虽然很少用到,但是感觉挺有意思的一些函数.分二类介绍,分别是: 著名函数篇 -经常用到的函数 非著名函数篇-即虽然很少用到,但某些情况下却很实用 注:N表 ...
- 如何查看编译安装的lnmp环境各自的配置参数
安装好后如何查看mysql/apache/nginx/php安装参数 查看mysql编译参数: cat /usr/local/mysql/bin/mysqlbug | grep CONFIGURE ...
- Android中Context的理解及使用(一)——Context的作用
Context的作用:用来访问全局信息的接口,通过Context进行资源的访问. 1.Context获取字符串资源: public class MainActivity extends AppComp ...
- Windows 7 OpenGL配置
http://blog.csdn.net/qingyang8513/article/details/45155245
- window server 2008配置FTP服务器550 Access is denied. 问题解决办法
如果你是按照网上的通用方法,在搭建FTP服务器的时候临时建了一个用户的话,那么这个用户是普通用户,你即便勾选了“读”“写”权限,那么再打开防火墙的情况下,你还是不能上传文件,只能下载.只需要登录到服务 ...
- win7系统下 自带的定时关机
进入cmd下,输入shutdown -s -t 600 以上例子代表的是10分钟后自动关机 -s代表定时关机 -t代表着定时,时间以秒为单位一分钟60s 输入完后按enter 定时关机设置完成 当想取 ...
- sublime自动生成头部注释
1.在tool->new snippet-创建一个新的snippet sublime text2 用snippet 创建文件头部信息 Snippets are smart templates t ...
- 解决pip安装超时
我们在使用python开发的时候总会需要安装很多第三方模块 比如我用flask搭建web, 需要很多第三方模块,比如flask-sqlalchemy, flask-bootstrap等等.而这些模块用 ...