LUA的使用

背景

LUA刚流行起来的时候,想学习一下LUA。就找了一款使用LUA脚本引擎的游戏玩。希望从中了解LUA的使用

结果

熟悉了LUA的同时也熟悉了这款游戏。

准备工作

使用detoured withdll注入LUAK.dll。LUAK.dll用于管理LUA环境

procedure PROCESS_ATTACH(); stdcall
begin
  //  Msg_hwd := TMsg_hwd.Create;
  HookAPI_init;
end;

拦截了 函数:lua_pushstring lua_setfield lua_pushcclosure luaL_newstate luaL_openlibs luaL_loadbuffer lua_pushlstring lua_tointeger lua_pushinteger lua_pushboolean lua_toboolean lua_createtable lua_resume lua_pushnumber lua_settop lua_tolstring lua_settable lua_pushlightuserdata lua_newthread lua_pushnil lua_tonumber luaL_checknumber lua_yield lua_type lua_typename lua_gettable lua_isstring lua_pcall lua_getfield luaopen_table luaopen_math luaopen_string luaopen_base lua_close lua_touserdata

procedure HookAPI_init;
var
  dwProtect, temp, k: cardinal;
begin
  //
  writelogfs('HookAPI_init');
  LoadLuaLib('Lua5.dll');
  writelogfs('LoadLuaLib');
  LUA_HMODULE := fLibHandle;

  @Oldlua_pushstringFunction := GetProcAddress(LUA_HMODULE, 'lua_pushstring');
  if assigned(Oldlua_pushstringFunction) then
    Oldlua_pushstringAddress := DWORD(@Oldlua_pushstringFunction);
  Spylua_pushstringAddress := DWORD(@Spylua_pushstring);
  VirtualProtect(@Oldlua_pushstringFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(Oldlua_pushstringAddress)[0], tmpBuff_lua_pushstring[0], 6);
  PChar(Oldlua_pushstringAddress)^ := #$FF;
  PChar(Oldlua_pushstringAddress + 1)^ := #$25;
  PInteger(Oldlua_pushstringAddress + 2)^ := DWORD(@Spylua_pushstringAddress);
  VirtualProtect(@Oldlua_pushstringFunction, 6, dwProtect, @temp);
  //
  @Oldlua_setfieldFunction := GetProcAddress(LUA_HMODULE, 'lua_setfield');
  if assigned(Oldlua_setfieldFunction) then
    Oldlua_setfieldAddress := DWORD(@Oldlua_setfieldFunction);
  Spylua_setfieldAddress := DWORD(@Spylua_setfield);
  VirtualProtect(@Oldlua_setfieldFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(Oldlua_setfieldAddress)[0], tmpBuff_lua_setfield[0], 6);
  PChar(Oldlua_setfieldAddress)^ := #$FF;
  PChar(Oldlua_setfieldAddress + 1)^ := #$25;
  PInteger(Oldlua_setfieldAddress + 2)^ := DWORD(@Spylua_setfieldAddress);
  VirtualProtect(@Oldlua_setfieldFunction, 6, dwProtect, @temp);

  @Oldlua_pushcclosureFunction := GetProcAddress(LUA_HMODULE, 'lua_pushcclosure');
  if assigned(Oldlua_pushcclosureFunction) then
    Oldlua_pushcclosureAddress := DWORD(@Oldlua_pushcclosureFunction);
  Spylua_pushcclosureAddress := DWORD(@Spylua_pushcclosure);
  VirtualProtect(@Oldlua_pushcclosureFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(Oldlua_pushcclosureAddress)[0], tmpBuff_lua_pushcclosure[0], 6);
  PChar(Oldlua_pushcclosureAddress)^ := #$FF;
  PChar(Oldlua_pushcclosureAddress + 1)^ := #$25;
  PInteger(Oldlua_pushcclosureAddress + 2)^ := DWORD(@Spylua_pushcclosureAddress);
  VirtualProtect(@Oldlua_pushcclosureFunction, 6, dwProtect, @temp);
  //
  @OldluaL_newstateFunction := GetProcAddress(LUA_HMODULE, 'luaL_newstate');
  if assigned(OldluaL_newstateFunction) then
    OldluaL_newstateAddress := DWORD(@OldluaL_newstateFunction);
  SpyluaL_newstateAddress := DWORD(@SpyluaL_newstate);
  VirtualProtect(@OldluaL_newstateFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(OldluaL_newstateAddress)[0], tmpBuff_luaL_newstate[0], 6);
  PChar(OldluaL_newstateAddress)^ := #$FF;
  PChar(OldluaL_newstateAddress + 1)^ := #$25;
  PInteger(OldluaL_newstateAddress + 2)^ := DWORD(@SpyluaL_newstateAddress);
  VirtualProtect(@OldluaL_newstateFunction, 6, dwProtect, @temp);

  @OldluaL_openlibsFunction := GetProcAddress(LUA_HMODULE, 'luaL_openlibs');
  if assigned(OldluaL_openlibsFunction) then
    OldluaL_openlibsAddress := DWORD(@OldluaL_openlibsFunction);
  SpyluaL_openlibsAddress := DWORD(@SpyluaL_openlibs);
  VirtualProtect(@OldluaL_openlibsFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(OldluaL_openlibsAddress)[0], tmpBuff_luaL_openlibs[0], 6);
  PChar(OldluaL_openlibsAddress)^ := #$FF;
  PChar(OldluaL_openlibsAddress + 1)^ := #$25;
  PInteger(OldluaL_openlibsAddress + 2)^ := DWORD(@SpyluaL_openlibsAddress);
  VirtualProtect(@OldluaL_openlibsFunction, 6, dwProtect, @temp);

  @OldluaL_loadbufferFunction := GetProcAddress(LUA_HMODULE, 'luaL_loadbuffer');
  if assigned(OldluaL_loadbufferFunction) then
    OldluaL_loadbufferAddress := DWORD(@OldluaL_loadbufferFunction);
  SpyluaL_loadbufferAddress := DWORD(@SpyluaL_loadbuffer);
  VirtualProtect(@OldluaL_loadbufferFunction, 6, PAGE_EXECUTE_READWRITE, @dwProtect);
  move(PChar(OldluaL_loadbufferAddress)[0], tmpBuff_luaL_loadbuffer[0], 6);
  PChar(OldluaL_loadbufferAddress)^ := #$FF;
  PChar(OldluaL_loadbufferAddress + 1)^ := #$25;
  PInteger(OldluaL_loadbufferAddress + 2)^ := DWORD(@SpyluaL_loadbufferAddress);
  VirtualProtect(@OldluaL_loadbufferFunction, 6, dwProtect, @temp);

数据分析

在luaL_loadbuffer 中保存LUA代码到文件中,便于以后的分析。

       if trim(name) = '' then
         begin
           SpyluaL_loadstring_count := SpyluaL_loadstring_count + 1;
           save_fn := Logpath + 'loadbuffer_' + inttostr(SpyluaL_loadstring_count) + '.lua';
         end
       else
         begin
           save_fn := Logpath + stringreplace(name, ':', '_', [rfReplaceAll]) + inttostr(sz);
         end;

       ForceDirectories(ExtractFilePath(save_fn));
       ms := TMemoryStream.Create;
       ms.Write(buff[0], sz);
       ms.Position := 0;
       ms.SaveToFile(save_fn);
       FreeAndNil(ms);
       sl := TStringList.Create;
       sl.Add('L=' + inttostr(integer(L)));
       sl.SaveToFile(save_fn + '.txt');
       FreeAndNil(sl);
       last_sz := sz;
       last_ch1 := buff[0];
       last_ch2 := buff[1];

也可以在这里修改LUA代码,例如 

  setlength(lua, sz);
  Move(buff[0], lua[1], sz);
  if pos('gf_SetPlayerInvincible(nTime)', lua) > 0 then
    begin
      fun_name := 'luaL_loadbuffer';
      lua := lua + #13#10 + ' gf_SetPlayerInvincible(10000) ';
      result := OldluaL_loadbufferFunction(L, pchar(lua), length(lua), name);
      lua := stringreplace(lua, 'return szCIP;', ' gf_SetPlayerInvincible(10000);'#13#10'return szCIP;', [rfIgnoreCase]);
      writelogfs(fun_name + ' gf_SetPlayerInvincible');
    end
  else
    begin
      result := OldluaL_loadbufferFunction(L, buff, sz, name);
    end;
  lua := '';

 LUA源码记录到文件中之后,可以先看看文件中的LUA源码进行学习。俺的经验是先看文件尺寸,选大的。

 

然后就可以从这些LUA的源码中学习LUA的源码,在学习LUA的源码同时也可以熟悉这个游戏

随着学习LUA代码,发现了这个游戏有很多新手对话任务。这些任务只要执行 

idx=8101; 
ClientAcceptTask(idx);
ClientCompleteTask(idx);

就可以领取并完成任务,这样就可以获得经验并升级。

工具

任务列表,从lua源码中提取的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月巴月巴白勺合鸟月半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值