日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

在windows程序中嵌入Lua脚本引擎--编写自己的Lua库

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在windows程序中嵌入Lua脚本引擎--编写自己的Lua库 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? 在《在windows程序中嵌入Lua腳本引擎--建立一個簡易的“云命令”執行的系統》一文中,我提到了使用Lua的ffi庫,可以讓我們像寫C代碼一樣寫lua程序。這是個非常令我們這些C程序員激動的事。但是我們使用ffi庫寫出來的程序往往比較大,因為我們可能要聲明一些API的原型和結構體。比如我們看luajit的wiki中關于使用ffi調用kernel32的一個例子。(轉載請指明出于breaksoftware的csdn博客)如果我們要使用

BOOL HeapWalk(HANDLE hHeap, PROCESS_HEAP_ENTRY * lpEntry);

? ? ? ? 則在Lua中要做如下聲明

ffi.cdef[[
typedef struct _PROCESS_HEAP_ENTRY {PVOID lpData;DWORD cbData;BYTE cbOverhead;BYTE iRegionIndex;WORD wFlags;union {struct {HANDLE hMem;DWORD dwReserved[ 3 ];} Block;struct {DWORD dwCommittedSize;DWORD dwUnCommittedSize;LPVOID lpFirstBlock;LPVOID lpLastBlock;} Region;} DUMMYUNIONNAME;
} PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY, *PPROCESS_HEAP_ENTRY;BOOL HeapWalk(HANDLE hHeap, PROCESS_HEAP_ENTRY * lpEntry);
]]

? ? ? ? ?即告訴Lua,我們要調用的函數的名字和函數使用的結構體的原型。

? ? ? ? ?看到這,可能會讓想使用ffi庫的朋友打起了退堂鼓。那我們如何才可以比較簡潔的調用這個函數呢?那就是:編寫我們自己的Lua庫"fl"。

? ? ? ? ?我們可以參考luajit中os庫的聲明方式。

? ? ? ? 1 lualib.h中新增我們庫的名字"fl",并聲明注冊我們庫的函數luaopen_fl

……
#define LUA_FFILIBNAME	"ffi"
#define LUA_FLLIBNAME   "fl"
……
LUALIB_API int luaopen_ffi(lua_State *L);
LUALIB_API int luaopen_fl(lua_State *L);

? ? ? ? 2 在lib_init.c中,將我們的庫名字和打開庫的名字banding

……{ LUA_JITLIBNAME,	luaopen_jit },{ LUA_FLLIBNAME, luaopen_fl },{ NULL,		NULL }

? ? ? ? 3 在Lualib目錄下新建一個lib_fl.c文件

? ? ? ? 實現最基本的函數和結構。主要是實現注冊我們庫的luaopen_fl函數,和函數名和函數地址綁定結構體數組uaL_Reg_fl_lib

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lj_lib.h"
static const luaL_Reg fl_lib[] = {{ NULL, NULL }
};LUALIB_API int luaopen_fl(lua_State *L)
{luaL_register(L, LUA_FLLIBNAME, fl_lib);return 1;
}

? ? ? ? 4 將lib_fl.c加入《在windows程序中嵌入Lua腳本引擎--使用VS IDE編譯Luajit腳本引擎》中介紹的Lua工程。
? ? ? ? 5 修改《在windows程序中嵌入Lua腳本引擎--使用VS IDE編譯Luajit腳本引擎》中介紹的Buildvm工程的生成后事件。在事件中,將lib_fl.c加入ALL_LIB中

@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_fl.c

? ? ? ? 6 在ljamalg.c中新增#include "lib_fl.c"

? ? ? ? 如此我們便新增了一個名字叫fl的庫,我們可以??

fl = require "fl"
fl.……

? ? ? ? 這樣調用它。

? ? ? ? 現在我們要擴充我的庫:

? ? ? ?A 在fl庫中新增一個獲取系統版本信息的函數

LJLIB_CF(fl_GetSystemVersion)
{OSVERSIONINFOA osver;ZeroMemory(&osver, sizeof(OSVERSIONINFOA));osver.dwOSVersionInfoSize = sizeof(osver);if ( GetVersionExA(&osver) ){lua_pushnumber(L, osver.dwMajorVersion);lua_pushnumber(L, osver.dwMinorVersion);lua_pushnumber(L, osver.dwBuildNumber);lua_pushnumber(L, osver.dwPlatformId);lua_pushstring(L, osver.szCSDVersion);return 5;}else{return 0;}
}

? ? ? ?并在fl_lib數組中新增名字和該函數的地址的綁定

static const luaL_Reg fl_lib[] = {{ "GetSystemVersion",	lj_cf_fl_GetSystemVersion },{ NULL, NULL }
};

? ? ? ? ?這樣我們編譯出來的luajit便可以使用簡單的方法調用獲取系統版本了。

? ? ? ? B 在fl庫中一個獲取系統中所有進程的函數

? ? ? ? 為了讓我們的這個例子盡可能復雜,我不準備使用快照的方法去獲取進程信息。而是使用Windows未公開的函數NtQuerySystemInformation。我在之前的《使用APIHOOK實現進程隱藏》中介紹過該方法。

#include <windows.h>#define MAXLOOPCOUNT 5 
#define MAXPROCSSNUM 1024#define STATUS_SUCCESS 0x00000000
#define SystemProcessInformation 5
#define STATUS_SUCCESS 0x00000000
#define STATUS_INFO_LENGTH_MISMATCH ((ULONG)0xC0000004L)typedef DWORD (WINAPI * Fun_NtQuerySystemInformation)( DWORD, PVOID, DWORD, PDWORD );typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR  Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef const UNICODE_STRING *PCUNICODE_STRING;typedef struct _SYSTEM_PROCESS_INFORMATION
{DWORD           dwNextEntryOffset;                  // 下段結構對象的偏移DWORD           dwNumberOfThreads;                  // 線程數LARGE_INTEGER   qSpareLi1;                          LARGE_INTEGER   qSpareLi2;LARGE_INTEGER   qSpareLi3;LARGE_INTEGER   qCreateTime;                        // 創建時間LARGE_INTEGER   qUserTime;                          // 用戶態時間LARGE_INTEGER   qKernelTime;                        // 內核態時間UNICODE_STRING  ImageName;                          // 文件名(非路徑)int             nBasePriority;                      // 基本優先級DWORD           dwProcessId;                        // 進程IDDWORD           dwInheritedFromUniqueProcessId;     // 父進程IDDWORD           dwHandleCount;                      // 句柄數DWORD           dwSessionId;ULONG           dwSpareUl3;SIZE_T          tPeakVirtualSize;SIZE_T          tVirtualSize;DWORD           dwPageFaultCount;DWORD           dwPeakWorkingSetSize;DWORD           dwWorkingSetSize;SIZE_T          tQuotaPeakPagedPoolUsage;SIZE_T          tQuotaPagedPoolUsage;SIZE_T          tQuotaPeakNonPagedPoolUsage;SIZE_T          tQuotaNonPagedPoolUsage;SIZE_T          tPagefileUsage;SIZE_T          tPeakPagefileUsage;SIZE_T          tPrivatePageCount;LARGE_INTEGER   qReadOperationCount;LARGE_INTEGER   qWriteOperationCount;LARGE_INTEGER   qOtherOperationCount;LARGE_INTEGER   qReadTransferCount;LARGE_INTEGER   qWriteTransferCount;LARGE_INTEGER   qOtherTransferCount;
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;BOOL GetNtQuerySystemInfoBuffer( IN DWORD SystemInformationClass, void** lpBuffer )
{BOOL bSuccess = FALSE;HMODULE hNtDll =  NULL;Fun_NtQuerySystemInformation NtQuerySystemInformation = NULL;ULONG cbBuffer = 0x0001;ULONG ulNeedBytes = cbBuffer;int nloopcount = 0;ULONG nstatus = 0;void* pBuffer = NULL;*lpBuffer = NULL;hNtDll = GetModuleHandle( L"ntdll.dll" );do {if( NULL == hNtDll ) {// 加載ntdll失敗,返回FALSEbreak;}NtQuerySystemInformation = ( Fun_NtQuerySystemInformation ) GetProcAddress( hNtDll, "NtQuerySystemInformation" );if ( NULL == NtQuerySystemInformation ) {// 獲取導出函數NtQuerySystemInformation失敗,返回FALSEbreak;}// 預分配的空間大小,先分配一個小空間,理論上使用這個空間去獲取信息是失敗的cbBuffer = 0x0001;ulNeedBytes = cbBuffer;// 分配內存用于保存進程信息,只分配不釋放,由外部釋放*lpBuffer = malloc( cbBuffer );nloopcount = 0;do {// 為了防止無限循環,做個最大循環限制if ( nloopcount > MAXLOOPCOUNT ) {break;}nloopcount++;if( NULL == *lpBuffer ) {// 分配內存失敗,返回FALSEbreak;}// 理論上,第一次執行這個函數會失敗的,因為分配的空間太小nstatus = NtQuerySystemInformation( SystemInformationClass, *lpBuffer,cbBuffer,&ulNeedBytes );if ( STATUS_INFO_LENGTH_MISMATCH == nstatus ) {// 理論上,第一次執行NtQuerySystemInformation后會進入這里進行內存的再次擴容cbBuffer = ulNeedBytes;// 重新分配內存用于保存進程信息,只分配不釋放,由外部釋放pBuffer = realloc( *lpBuffer, cbBuffer );if (pBuffer != NULL)*lpBuffer = pBuffer;continue;}else if ( STATUS_SUCCESS == nstatus ) {// 成功bSuccess = TRUE;break;}else {// 非內存大小分配不夠導致的錯誤bSuccess = FALSE;break;}} while(1);} while( 0 );if ( NULL != hNtDll ) {FreeLibrary( hNtDll );hNtDll = NULL;}if ( FALSE == bSuccess ) {// 如果獲取信息失敗,則釋放分配的內存if ( NULL !=  *lpBuffer ) {free( *lpBuffer );*lpBuffer = NULL;}}return bSuccess;
}  

? ? ? ? 看到如上結構體,要是在lua中用ffi去聲明,豈不是很崩潰!我們再看下填充數據的輔助函數

BOOL GetProcessFullInfo(lua_State *L)
{BOOL bSuccess = FALSE;PSYSTEM_PROCESS_INFORMATION pInfo = NULL;int nloopcount = 0;do {LPVOID pBuffer = NULL;if ( FALSE == GetNtQuerySystemInfoBuffer( SystemProcessInformation, &pBuffer) ) {// 獲取失敗,直接返回,不用釋放pBuffer,因為GetZwQuerySystemInfoBuffer內部就釋放了break;}if ( NULL == pBuffer ) {break;}pInfo = ( PSYSTEM_PROCESS_INFORMATION ) pBuffer;nloopcount = 0;lua_newtable( L );while( NULL != pInfo ) {// 為了防止無限循環,做個最大進程數限制if ( nloopcount > MAXPROCSSNUM ) {break;}nloopcount++;if( 0 == pInfo->dwNextEntryOffset ) {// 找到末尾最后一個了,就退出循環break;}else {lua_pushinteger( L, pInfo->dwProcessId);//lua_newtable( L );lua_pushinteger( L, pInfo->dwInheritedFromUniqueProcessId );lua_pushlstring( L, (char*)pInfo->ImageName.Buffer, pInfo->ImageName.Length );lua_settable( L, -3 );//lua_settable( L, -3 );// 利用偏移,找到下一個結構對象pInfo = ( PSYSTEM_PROCESS_INFORMATION)( ( (PUCHAR) pInfo ) + pInfo->dwNextEntryOffset );}}if ( NULL != pBuffer ) {free( pBuffer );pBuffer = NULL;}bSuccess = TRUE;} while( 0 );return bSuccess;
}

? ? ? ? 該函數生成一個如同

struct PINFO{
DWORD dwPPID; // 父進程ID
wstring wstrProcessName; // 本進程名字
};struct PINFOEX{
DWORD dwPID;  // 本進程ID
PINFO Info;
}list<PINFOEX> PINFOLIST;

? ? ? ? 的結果。

? ? ? ? 如果我們執行如此簡短的Lua腳本

fl = require "fl"
allprocessinfo = fl.GetAllProcess()
for PID,item in pairs(allprocessinfo) dofor PPID,PNAME in pairs(item) doprint(PPID,PNAME)end
end

? ? ? ? 將把我們系統中進程信息打印出來。

? ? ? ? 介紹Luajit嵌入win32程序的文章講完了。

? ? ? ? 最后,該工程源碼都在以下鏈接:http://pan.baidu.com/s/1geQ10R5 密碼:pknq

總結

以上是生活随笔為你收集整理的在windows程序中嵌入Lua脚本引擎--编写自己的Lua库的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产视频网 | 麻豆一区产品精品蜜桃的特点 | 蜜桃av鲁一鲁一鲁一鲁俄罗斯的 | 欧美日a | 欧美精品一区二区三区视频 | 激情视频国产 | 乌克兰黄色片 | 美女扒开粉嫩的尿囗给男生桶 | 操极品女神| 日韩欧美xxxx | 一级在线看 | www免费视频 | 都市激情中文字幕 | 黄色a在线观看 | 小sao货cao死你 | 手机在线看片1024 | 大尺度做爰啪啪床戏 | 色女生影院 | 18无码粉嫩小泬无套在线观看 | www天堂在线| 亚洲免费自拍 | 日韩高清精品免费观看 | 精品久久九九 | 天堂网资源 | 久久久这里有精品 | 黄色www视频| 少妇高潮一区二区三区 | 欧美高清在线观看 | 极品超粉嫩尤物69xx | 欧美精品四区 | 国产精品久久久久影院 | 欧美绿帽合集xxxxx | 欧美性在线观看 | 成人免费观看网址 | 韩国三级在线视频 | 国产videos | 国产精品揄拍100视频 | 亚洲国产精品成人va在线观看 | 久久久久无码国产精品一区李宗瑞 | 日韩中文字幕二区 | 国产精品无码电影 | 91精品国产91久久久久久吃药 | 欧美精品高清 | 一起草国产 | 午夜激情网站 | 亚洲呦呦 | 91福利在线导航 | 中国一级特黄真人毛片免费观看 | 理论片久久 | 国模杨依粉嫩蝴蝶150p | 一本视频 | 9191久久| 91丨九色丨丰满 | 日韩3区| 伊人久久大香线蕉av一区 | 成人免费xxxxx在线视频 | 日韩av片在线看 | 国产精品一区免费 | 四虎影院污| 欧美一区2区三区4区公司 | 国产日韩欧美在线观看视频 | 亚洲不卡视频在线 | 精品亚洲永久免费 | 韩国bj大尺度vip福利网站 | 欧美视频第一区 | 欧美美女爱爱视频 | 99精品一区二区三区无码吞精 | 亚洲一区二区三区观看 | 精品国产免费观看 | 搡老熟女老女人一区二区 | 国产成人精品一区二区三区在线 | 悠悠色影院 | 激情在线观看视频 | 一区二区国产精品视频 | 免费观看a级片 | 日韩一区二区三区久久 | 少妇饥渴难耐 | 成人h动漫精品一区二区器材 | 97人妻精品一区二区三区免费 | 爽天天天天天天天 | 免费看的黄色录像 | 欧美三级网站 | 日本网站免费 | 亚洲激情a| 尹人成人 | 免费看黄色片视频 | 久久久久久国产精品视频 | 成人短视频在线观看 | 九一天堂 | 久久久丁香 | 亚洲大尺度在线 | 日韩成人免费 | 国产成人精品久久二区二区 | 欧美精品成人一区二区在线观看 | 国产精品成人网 | 少妇真实被内射视频三四区 | 欧美一区二区三区爽爽爽 | 久久久久久久久免费 | 香蕉婷婷 |