使用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的就更方便了。

12-27 15:06