使用CBrother的CLIB库调用windows的API教程
使用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 }
用法还是比较容易理解,只要你熟悉windows编程,那么CBrother可以做任意你想做的事情。
上面这个api的用法我已经把代码发给作者了,作者说后续会加入lib库里,后续慢慢扩展成所有的api,这样在windows下使用api的就更方便了。