在收集LUA资料进行学习时,其中有个叫LuaDec的,能把LUA编译出来的代码解回去(逆回脚本内容),官方网站是:
http://luadec.luaforge.net/
它最后支持LUA5.0版本的代码,不过LUA也是开源的,个人可修改源码,这很难应对所有版本。
LuaDec的示例,只是用luaL_loadfile把脚本文件载入,然后就进行解码了,没有在LUA中运作时,LUA执行脚本的哪部分内容。没有这样的例子。
本人不会写文章,直接贴源码及分析时的经验。
主要HOOK上luaV_execute以及luaV_execute函数里边的luaD_poscall地方
如果是HOOK别人的程序,需要注意对LUA源码进行修改,达到和别人的LUA进行同步。
我接触过2~3个程序,目前发现其比较相同处
1,枚举型OpCode的指令顺序要对应
2,lua_TObject的结构大小,以及其成员value,tt的上下位置
3,LUA5.1版本时,Proto结构的变化
4,LUA5.1版本是,LClosure的结构变化
LUA源码好多宏,好多union类型,看着头疼,最后是用OD跟踪看内存,再拿源码对比得出些经验的
// TestLuaDec.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "stdlib.h"
DWORD dwSubLuaRet = 0;
DWORD dwLuaRet = 0;
BOOL bMainLuaStart = FALSE;
lua_State* luaHookHandle = NULL;
DWORD fnluaV_execute = NULL;
DWORD fnluaD_precall = NULL;
void hookluaEx()
{
__try{
char* code = lua_Dec(luaHookHandle, -1);
if (code)
{
printf("主函数开始\n");
printf(code);
printf("主函数结束\n\n");
free(code);
}
}__except (EXCEPTION_EXECUTE_HANDLER) {
printf("lua fail");
return;
}
}
__declspec(naked) void hooklua(DWORD lua)
{
__asm
{
push ebp
mov ebp, esp
push eax
mov eax, lua
mov luaHookHandle, eax
pop eax
push lua
call fnluaV_execute
mov dwLuaRet, eax
call hookluaEx
add esp, 4
mov eax,dwLuaRet
pop ebp
retn
}
}
void hookSubluaEx()
{
__try{
char* code = lua_DecSub(luaHookHandle, -1);
if (code)
{
printf("子函数开始\n");
printf(code);
printf("子函数结束\n\n");
free(code);
}
}__except (EXCEPTION_EXECUTE_HANDLER) {
printf("lua fail");
return;
}
}
__declspec(naked) void hookSublua(DWORD lua, DWORD lua2)
{
__asm
{
push ebp
mov ebp, esp
push lua2
push lua
call fnluaD_precall
mov dwSubLuaRet, eax
call hookSubluaEx
add esp, 8
mov eax,dwSubLuaRet
pop ebp
retn
}
}
void HookLua()
{
HMODULE ImageBase = GetModuleHandle(NULL);
PIMAGE_DOS_HEADER dos_stub = (PIMAGE_DOS_HEADER)ImageBase;
PIMAGE_NT_HEADERS PEHead = (PIMAGE_NT_HEADERS)((DWORD)ImageBase + dos_stub->e_lfanew);
DWORD f_luaV_execute = 0x0000E13D;
BOOL b_luaV_execute = FALSE;
DWORD f_luaD_precall = 0xFED8BD83;
BOOL b_luaD_precall = FALSE;
DWORD i = 0;
DWORD OldProtect, tOld;
for (int NOS=0; NOS<PEHead->FileHeader.NumberOfSections; NOS++)
{
PIMAGE_SECTION_HEADER pSecHeader = (PIMAGE_SECTION_HEADER)((DWORD)PEHead + NOS * sizeof(IMAGE_SECTION_HEADER)+sizeof(IMAGE_NT_HEADERS));
if (IMAGE_SCN_CNT_CODE & pSecHeader->Characteristics)
{
char* pFile = (char*)((DWORD)ImageBase+pSecHeader->VirtualAddress);
for (i=0; i<pSecHeader->SizeOfRawData-0x10; i++)
{
if (b_luaD_precall && b_luaD_precall)
break;
if (b_luaV_execute == FALSE && !memcmp(&pFile[i], &f_luaV_execute, 4))
{
if (*(PBYTE)(pFile+i+0x32) == 0xE8)
{
b_luaV_execute = TRUE;
DWORD t = (DWORD)ImageBase + i + pSecHeader->VirtualAddress + 0x32;
VirtualProtect((void*)t, 5, PAGE_EXECUTE_READWRITE, &OldProtect);
fnluaV_execute = t + 5 + *(PDWORD)(t+1);
(*(PDWORD)(t+1)) = (DWORD)hooklua - t - 5;
VirtualProtect((void*)i, 5, OldProtect, &tOld);
}
}
if (b_luaD_precall == FALSE && !memcmp(&pFile[i], &f_luaD_precall, 4))
{
if (*(PBYTE)(pFile+i-0x0E) == 0xE8)
{
b_luaD_precall = TRUE;
DWORD t = (DWORD)ImageBase + i + pSecHeader->VirtualAddress - 0x0E;
VirtualProtect((void*)t, 5, PAGE_EXECUTE_READWRITE, &OldProtect);
fnluaD_precall = t + 5 + *(PDWORD)(t+1);
(*(PDWORD)(t+1)) = (DWORD)hookSublua - t - 5;
VirtualProtect((void*)i, 5, OldProtect, &tOld);
}
}
}
}
}
}
int main(int argc, char* argv[])
{
#ifdef _DEBUG //代码特征在DEBUG版本有效
HookLua();
#endif
lua_State* L;
L=lua_open();
luaopen_base(L);
luaopen_io(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
lua_dofile(L, "test.lua");
system("pause");
return 0;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课