使用CBrother的CLIB库调用windows的API
2.1.0版本CBrother加入了CLib库,最新需要写一个工具,根据路径查杀一个Windows进程,研究了一下,CLib库的用法,感觉还是比较灵活的。
首先我要明确每一个API在系统的哪一个dll里面,我一般都是去微软官网查这个API。(https://docs.microsoft.com/zh-cn/windows/win32/api/),
比如我查OpenProcess这个API,查到如下内容
在Kernel32.dll里面,其他用到的API也都是这样获取信息,下面就可以写代码了。
1 import CBCLib.code 2 3 var g_kernel32_init = false; //kernel32.dll 是否初始化 4 var g_kernel32 = null; //Kernel32.dll 句柄 5 var g_kernel32_OpenProcess = null; //OpenProcess函数 6 var g_kernel32_CloseHandle = null; //CloseHandle函数 7 var g_kernel32_GetModuleFileNameExA = null; //GetModuleFileNameExA函数 8 var g_kernel32_GetLogicalDriveStringsA = null; //GetLogicalDriveStringsA函数 9 var g_kernel32_QueryDosDeviceA = null; //QueryDosDeviceA函数 10 11 var g_psapi_init = false; //psapi.dll 是否初始化 12 var g_psapi = null; //psapi.dll 句柄 13 var g_psapi_GetProcessImageFileNameA = null; //GetProcessImageFileNameA函数 14 15 const MAX_PATH = 1024; 16 17 //获取kernel32.dll里面的函数 18 function initkernel32() 19 { 20 if (g_kernel32_init) 21 { 22 return; 23 } 24 25 g_kernel32_init = true; 26 27 g_kernel32 = new CLib("kernel32.dll"); 28 if(!g_kernel32.load()) 29 { 30 print "kernel32.dll load err!"; 31 return; 32 } 33 34 //根据函数原型和CLib库类型对应关系写参数列表 35 g_kernel32_OpenProcess = g_kernel32.findFunc("OpenProcess","pointer","int","bool","int"); 36 g_kernel32_CloseHandle = g_kernel32.findFunc("CloseHandle","bool","int"); 37 g_kernel32_GetModuleFileNameExA = g_kernel32.findFunc("K32GetModuleFileNameExA","int","pointer","pointer","pointer","int"); 38 g_kernel32_GetLogicalDriveStringsA = g_kernel32.findFunc("GetLogicalDriveStringsA","int","int","pointer"); 39 g_kernel32_QueryDosDeviceA = g_kernel32.findFunc("QueryDosDeviceA","int","string","pointer","int"); 40 }
我还用到了psapi.dll里面的函数
1 //Psapi.dll里面的函数 2 function initpsapi() 3 { 4 if (g_psapi_init) 5 { 6 return; 7 } 8 g_psapi_init = true; 9 10 g_psapi = new CLib("Psapi.dll"); 11 if (!g_psapi.load()) 12 { 13 print "Psapi.dll load err!"; 14 return; 15 } 16 17 //根据函数原型和CLib库类型对应关系写参数列表 18 g_psapi_GetProcessImageFileNameA = g_psapi.findFunc("GetProcessImageFileNameA","int","pointer","pointer","int"); 19 }
下面是根据进程pid获取进程路径
1 const STANDARD_RIGHTS_REQUIRED = 0x000F0000; 2 const SYNCHRONIZE = 0x00100000; 3 function GetProcessPath(pid) 4 { 5 initkernel32(); 6 7 //打开目标进程 8 var hProcess = g_kernel32_OpenProcess.callFunc(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF,false,pid); 9 if (hProcess.isNull()) 10 { 11 print "openprocess err! " + pid; 12 return; 13 } 14 15 //构建一个buffer,GetModuleFileNameExA会把路径写进这个buffer里 16 var pathBuff = new CLibPointer(); 17 pathBuff.malloc(MAX_PATH); 18 19 var res = g_kernel32_GetModuleFileNameExA.callFunc(hProcess,null,pathBuff,MAX_PATH); 20 if(res > 0) 21 { 22 //GetModuleFileNameExA获取成功 23 res = pathBuff.readString(); 24 } 25 else 26 { 27 //有些系统获取不成功,需要使用另外一种方法。32位程序获取64位进程也需要用这种方法。 28 res = GetProcessPathByPsapi(hProcess); 29 } 30 31 //释放buffer 32 pathBuff.free(); 33 34 //关闭目标进程句柄 35 g_kernel32_CloseHandle.callFunc(hProcess); 36 return res; 37 }
如果GetModuleFileNameExA获取失败了,需要使用GetProcessImageFileNameA获取dos路径,然后转化成绝对路径
1 //使用GetProcessImageFileNameA获取进程路径 2 function GetProcessPathByPsapi(hProcess) 3 { 4 initkernel32(); 5 initpsapi(); 6 7 var newPath = ""; 8 var tempBuff = new CLibPointer(); 9 tempBuff.malloc(MAX_PATH); 10 var res = g_psapi_GetProcessImageFileNameA.callFunc(hProcess,tempBuff,MAX_PATH); 11 if(res > 0) 12 { 13 var driveStr = new CLibPointer(); 14 driveStr.malloc(MAX_PATH); 15 //获取所有盘符 16 if(g_kernel32_GetLogicalDriveStringsA.callFunc(MAX_PATH,driveStr)) 17 { 18 var dospath = tempBuff.readString(); 19 var driveName = new CLibPointer(); 20 driveName.malloc(MAX_PATH); 21 var copydriveStr = driveStr.copyAddr(); 22 23 //遍历盘符,和DOS盘符名称对照 24 while (1) 25 { 26 var szDrive = copydriveStr.readString(); 27 szDrive = strget(szDrive,0,2); 28 if(g_kernel32_QueryDosDeviceA.callFunc(szDrive,driveName,MAX_PATH)) 29 { 30 var dname = driveName.readString(); 31 var namelen = strlen(dname); 32 if(strnicmp(dname,dospath,namelen) == 0) 33 { 34 //对上了,说明就是这个路径 35 newPath = szDrive; 36 newPath += strget(dospath,namelen); 37 break; 38 } 39 40 //盘符指针向前加4获取下一个盘符 41 copydriveStr.addAddr(4); 42 } 43 else 44 { 45 break; 46 } 47 } 48 49 driveName.free(); 50 } 51 driveStr.free(); 52 } 53 54 tempBuff.free(); 55 return newPath; 56 }
下面就是在main函数使用
1 var g_path = "E:\\111\\test.exe"; //进程路径 2 var g_name = "test.exe"; //进程名 3 function main(params) 4 { 5 //这个函数是CBrother提供的,根据进程名获取pid,存到array里 6 var pidarr = GetProcessByName(g_name); 7 for (var i = 0; i < pidarr.size() ; i++) 8 { 9 //根据pid获取进程路径 10 var path = GetProcessPath(pidarr[i]); 11 if (path == g_path) 12 { 13 //如果路径匹配上了,杀掉。这个函数也是CBrother提供的,根据进程ID查杀进程 14 KillProcessByID(pidarr[i]); 15 } 16 } 17 }
上面这个api的用法我已经把代码发给作者了,作者说后续会加入lib库里,后续慢慢扩展成所有的api,这样在windows下使用api的就更方便了。