使用CBrother的CLIB庫調用windows的API
windows
2.1.0版本CBrother加入了CLib庫,最新須要寫一個工具,根據路徑查殺一個Windows進程,研究了一下,CLib庫的用法,感受仍是比較靈活的。api
首先我要明確每個API在系統的哪個dll裏面,我通常都是去微軟官網查這個API。(https://docs.microsoft.com/zh-cn/windows/win32/api/),函數
好比我查OpenProcess這個API,查到以下內容工具
在Kernel32.dll裏面,其餘用到的API也都是這樣獲取信息,下面就能夠寫代碼了。spa
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裏面的函數3d
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路徑,而後轉化成絕對路徑code
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函數使用blog
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的就更方便了。進程