使用CBrother的CLIB庫呼叫windows的API
阿新 • • 發佈:2019-11-18
使用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的就更方便