目前主流的调试工具依赖于ptrace接口,需要2个进程通过信号来互相唤醒处理调试事件。简单考察一次单点命中,目标tracee+trace线程至少需要 3次 用户/内核上下文切换:
{tracee执行直到命中hwbp_trap}
-[上下文切换,同步处理]->
(储存信号,唤醒tracer睡眠)
-[上下文切换+异步进程调度]->
{tracer被唤醒处理,重新执行tracee程序}
-[上下文切换+异步进程调度]->
{tracee重新开始运行}
符号标志意义为:[上下文开销] {用户态执行内容} (内核态执行内容)
可以看到上下文开销中直接由硬件异常导致的上下文切换是同步的,耗时较少,但是睡眠和唤醒tracer、tracee是一个不小的开销,并且tracer的处理函数需要反复使用ptrace调用陷入内核态以获取tracee的内存+寄存器信息,实际的运行开销比这里只考虑做ptrace_cont的场景更大。但是呢,为了能够在tracer线程里灵活执行可修改的调试操作,好像又是只能依赖这一套反复唤醒和切换的流程。对...对吗?
也并不一定,如果内核硬件调试异常的handler中直接把这个异常给处理完了,然后直接返回用户态,
{tracee执行直到命中hwbp_trap}
-[上下文切换,同步处理]->
(丢弃信号,内核内处理异常,硬件断点更新,直接返回用户态)
-[上下文切换,同步处理]->
{tracee重新开始运行}
这样的切换开销最多只是2次同步上下文切换,相比之下就是飞速。那么怎么实现可修改的异常处理功能呢?不妨把lua脚本植入进内核。查了下git,果然在内核层跑解释器语言这种烂点子已经有人想过。
截取自lunatik,目前只包含标准库和dostring功能(string直接从用户空间拷贝)
源码集合附上,放入待编译的内核子模块path/to/your/module/以子目录为lua-core为例
这样就算验证完了内核的lua执行环境

劫持系统调用实现
在lua代码中已安装实现的接口,可直接在lua代码中调用
未完待续...后续可以给大家演示一下常见的几个骚操作,包括
obj-$(CONFIG_YOUR_MODULE) += yourmoduleall.o
ccflags-y += -D_LUNATIK -D_KERNEL -DLUA_USE_C89 -I${PWD}/lua-core
yourmoduleall-y += yourmodule.o \
lua-core/lapi.o lua-core/lcode.o lua-core/lctype.o lua-core/ldebug.o lua-core/ldo.o \
lua-core/ldump.o lua-core/lfunc.o lua-core/lgc.o lua-core/llex.o lua-core/lmem.o \
lua-core/lobject.o lua-core/lopcodes.o lua-core/lparser.o lua-core/lstate.o \
lua-core/lstring.o lua-core/ltable.o lua-core/ltm.o \
lua-core/lundump.o lua-core/lvm.o lua-core/lzio.o \
lua-core/lauxlib.o lua-core/lbaselib.o \
lua-core/lcorolib.o lua-core/ldblib.o lua-core/lstrlib.o \
lua-core/ltablib.o lua-core/lutf8lib.o lua-core/lmathlib.o lua-core/linit.o \
lua-core/loadlib.o lua-core/arm64/setjmp.o
obj-$(CONFIG_YOUR_MODULE) += yourmoduleall.o
ccflags-y += -D_LUNATIK -D_KERNEL -DLUA_USE_C89 -I${PWD}/lua-core
yourmoduleall-y += yourmodule.o \
lua-core/lapi.o lua-core/lcode.o lua-core/lctype.o lua-core/ldebug.o lua-core/ldo.o \
lua-core/ldump.o lua-core/lfunc.o lua-core/lgc.o lua-core/llex.o lua-core/lmem.o \
lua-core/lobject.o lua-core/lopcodes.o lua-core/lparser.o lua-core/lstate.o \
lua-core/lstring.o lua-core/ltable.o lua-core/ltm.o \
lua-core/lundump.o lua-core/lvm.o lua-core/lzio.o \
lua-core/lauxlib.o lua-core/lbaselib.o \
lua-core/lcorolib.o lua-core/ldblib.o lua-core/lstrlib.o \
lua-core/ltablib.o lua-core/lutf8lib.o lua-core/lmathlib.o lua-core/linit.o \
lua-core/loadlib.o lua-core/arm64/setjmp.o
//取消lunatik中loadfile的功能
int lunatik_loadfile(lua_State *L, const char *filename, const char *mode){
return 1;
}
//内核环境测试代码
int call_lua(char* simple_cmd){
int result;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
printk(KERN_ALERT "Lua-cannot create state: not enough memory\n");
return 1;
}
lua_gc(L, LUA_GCSTOP); /* stop GC while building state */
//lua基础库
luaL_openlibs(L);
// //load kernLuaBpLibs
// luaL_openKernBplibs(L);
result=luaL_dostring(L,simple_cmd);
lua_close(L);
return 0;
}
//用来搞笑的测试代码
//放入模块_init中测试
int test_lua(void){
return call_lua("print('hello motherfucker')");
}
//取消lunatik中loadfile的功能
int lunatik_loadfile(lua_State *L, const char *filename, const char *mode){
return 1;
}
//内核环境测试代码
int call_lua(char* simple_cmd){
int result;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
printk(KERN_ALERT "Lua-cannot create state: not enough memory\n");
return 1;
}
lua_gc(L, LUA_GCSTOP); /* stop GC while building state */
//lua基础库
luaL_openlibs(L);
// //load kernLuaBpLibs
// luaL_openKernBplibs(L);
result=luaL_dostring(L,simple_cmd);
lua_close(L);
return 0;
}
//用来搞笑的测试代码
//放入模块_init中测试
int test_lua(void){
return call_lua("print('hello motherfucker')");
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-8-14 14:15
被dadadasda编辑
,原因: 追加编译设置,内核模块中的lua运行库源码,发布接口文档