1.显示当前的所有进程:
//显示所有进程
void getAllProcess(HANDLE handle){
//HANDLE handle1; //定义要结束进程句柄
PROCESSENTRY32 *info; //定义PROCESSENTRY32结构字指
//PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32)
info=new PROCESSENTRY32;
info->dwSize=sizeof(PROCESSENTRY32);
//调用一次 Process32First 函数,从快照中获取进程列表
Process32First(handle,info);
//重复调用 Process32Next,直到函数返回 FALSE为止,打印进程信息
while(Process32Next(handle,info)!=FALSE){
info->szExeFile; //指向进程名字
printf("ProcessName:%s\n",info->szExeFile);
printf("ProcessID: %d\n\n",info->th32ProcessID);
}
//通过进程号选中进程
int processID;
printf("请输入你需要的进程号:");
scanf("%d",&processID);
//再次调用 Process32First 函数,获取进程列表
Process32First(handle,info);
//重复调用 Process32Next,直到函数返回 FALSE为止,对比进程号,找出指定进程
while(Process32Next(handle,info)!=FALSE){
if(processID==info->th32ProcessID){
HANDLE hfilename = NULL ;
hfilename = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,info->th32ProcessID );
MODULEENTRY32 pes;
//这个结构描述了一个条目从一个列表,列举了一个指定的进程所使用的模块。
pes.dwSize = sizeof(MODULEENTRY32);
if (hfilename == NULL ){
printf("文件名字访问失败!");
}
BOOL i = Module32First(hfilename,&pes);
char* ppath=pes.szExePath;
printf("ProcessDir: %s\n",ppath);
printf("ProcessName:%s\nProcessID:%d\n",info->szExeFile,info->th32ProcessID);
//FALSE=可继承,info->th32ProcessID=进程ID
}
}
CloseHandle(handle);
return;
}
2.通过进程路径获取该进程,映射到本进程,从而再获取本进程加载的API函数 :
int main(){
HANDLE handle; //定义CreateToolhelp32Snapshot系统快照句柄
handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获得系统快照句柄
getAllProcess(handle);
char s[255];
printf("请输入文件绝对路径(ProcessDir):\n");
scanf("%s",s);
HANDLE hFile=(HANDLE)CreateFile(s,GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE){//无效句柄
hFile=NULL;
TCHAR *buffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,(LPTSTR)&buffer,0,NULL);
MessageBox(0,buffer,TEXT("Error"),MB_OK);
//无法打开该进程
CloseHandle(hFile);
printf("handle失败\n");
return 0;
}
else{
printf("handle有效\n");
}
//创建一个新的进程映射到内核对象
HANDLE hFileMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,100,NULL);
if(!hFileMap){
TCHAR *buffer;
printf("hFileMap失败\n");
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,(LPTSTR)&buffer,0,NULL);
MessageBox(0,buffer,TEXT("Error"),MB_OK);
CloseHandle(hFileMap);
return 0;
}
else{
printf("新的进程映射到内核对象\n");
}
//映射文件视图到调用进程的地址空间,返回值是映射视图的开始位置
LPVOID lpMemory=MapViewOfFile(hFileMap,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
HMODULE hModule = ::GetModuleHandleA(NULL);
IMAGE_DOS_HEADER* pDosHeader=(IMAGE_DOS_HEADER*)hModule;
IMAGE_OPTIONAL_HEADER* pOpNtHeader=(IMAGE_OPTIONAL_HEADER*)((BYTE*)hModule+pDosHeader->e_lfanew+24); //这里加24
IMAGE_IMPORT_DESCRIPTOR* pImportDesc=(IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hModule
+pOpNtHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (pImportDesc->FirstThunk){
char* pszDllName=(char*)((BYTE*)hModule+pImportDesc->Name);
printf("模块名称:%s\n",pszDllName);
DWORD n = 0;
//一个IMAGE_THUNK_DATA就是一个导入函数
IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hModule + pImportDesc->OriginalFirstThunk);
while (pThunk->u1.Function){
//取得函数名称
char* pszFuncName = (char*)((BYTE*)hModule+pThunk->u1.AddressOfData+2); //函数名前面有两个..
printf("function name:%-25s, ", pszFuncName);
//取得函数地址
PDWORD lpAddr = (DWORD*)((BYTE*)hModule + pImportDesc->FirstThunk) + n; //从第一个函数的地址,以后每次+4字节
printf("addrss:%X\n", lpAddr);
n++; //每次增加一个DWORD
pThunk++;
}
printf("\n");
pImportDesc++;
}
//停止当前程序的一个内存映射
UnmapViewOfFile(lpMemory);
//关掉该新建的文件映射
CloseHandle(hFileMap);
//关掉原文件句柄
CloseHandle(hFile);
system("pause");
return 0;
}
3.依旧存在的问题:
- 涉及需要提升权限才可以操作的进程,在CreateFile时报错:拒绝访问,使用管理员身份运行也不可以;
- 一些进程的dir显示不出来;
- 正打开的进程无法映射,在CreateFile时报错:另一个程序正在使用此文件,进程无法访问;
- 显示的API函数是将我们需要的进程映射到当前进程而来,不是单独的选中的进程,不知是否可以利用文件的内存结构,获取IAT表的位置并进行读取。
4.部分结果截图:
最后,欢迎大家到我的个人主页http://jiaqianli.cn/,有更为详细的介绍,希望一起交流、学习,一起进步~