initial
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.*
|
||||
!.gitignore
|
||||
161
inc/lua/lauxlib.h
Normal file
161
inc/lua/lauxlib.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
|
||||
const char *fname, int szhint);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int luaL_execresult(lua_State *L, int stat);
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
int level);
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/* From Lua 5.2. */
|
||||
#define luaL_newlibtable(L, l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *p; /* current position in buffer */
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State *L;
|
||||
char buffer[LUAL_BUFFERSIZE];
|
||||
} luaL_Buffer;
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
|
||||
(*(B)->p++ = (char)(c)))
|
||||
|
||||
/* compatibility only */
|
||||
#define luaL_putchar(B,c) luaL_addchar(B,c)
|
||||
|
||||
#define luaL_addsize(B,n) ((B)->p += (n))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
#endif
|
||||
402
inc/lua/lua.h
Normal file
402
inc/lua/lua.h
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||
** See Copyright Notice at the end of this file
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lua_h
|
||||
#define lua_h
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include "luaconf.h"
|
||||
|
||||
|
||||
#define LUA_VERSION "Lua 5.1"
|
||||
#define LUA_RELEASE "Lua 5.1.4"
|
||||
#define LUA_VERSION_NUM 501
|
||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||
|
||||
|
||||
/* mark for precompiled code (`<esc>Lua') */
|
||||
#define LUA_SIGNATURE "\033Lua"
|
||||
|
||||
/* option for multiple returns in `lua_pcall' and `lua_call' */
|
||||
#define LUA_MULTRET (-1)
|
||||
|
||||
|
||||
/*
|
||||
** pseudo-indices
|
||||
*/
|
||||
#define LUA_REGISTRYINDEX (-10000)
|
||||
#define LUA_ENVIRONINDEX (-10001)
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
|
||||
|
||||
|
||||
/* thread status */
|
||||
#define LUA_OK 0
|
||||
#define LUA_YIELD 1
|
||||
#define LUA_ERRRUN 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
|
||||
typedef int (*lua_CFunction) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** functions that read/write blocks when loading/dumping Lua chunks
|
||||
*/
|
||||
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
|
||||
|
||||
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
|
||||
|
||||
|
||||
/*
|
||||
** prototype for memory-allocation functions
|
||||
*/
|
||||
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
|
||||
|
||||
/*
|
||||
** basic types
|
||||
*/
|
||||
#define LUA_TNONE (-1)
|
||||
|
||||
#define LUA_TNIL 0
|
||||
#define LUA_TBOOLEAN 1
|
||||
#define LUA_TLIGHTUSERDATA 2
|
||||
#define LUA_TNUMBER 3
|
||||
#define LUA_TSTRING 4
|
||||
#define LUA_TTABLE 5
|
||||
#define LUA_TFUNCTION 6
|
||||
#define LUA_TUSERDATA 7
|
||||
#define LUA_TTHREAD 8
|
||||
|
||||
|
||||
|
||||
/* minimum Lua stack available to a C function */
|
||||
#define LUA_MINSTACK 20
|
||||
|
||||
|
||||
/*
|
||||
** generic extra include file
|
||||
*/
|
||||
#if defined(LUA_USER_H)
|
||||
#include LUA_USER_H
|
||||
#endif
|
||||
|
||||
|
||||
/* type of numbers in Lua */
|
||||
typedef LUA_NUMBER lua_Number;
|
||||
|
||||
|
||||
/* type for integer functions */
|
||||
typedef LUA_INTEGER lua_Integer;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** state manipulation
|
||||
*/
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
|
||||
/*
|
||||
** basic stack manipulation
|
||||
*/
|
||||
LUA_API int (lua_gettop) (lua_State *L);
|
||||
LUA_API void (lua_settop) (lua_State *L, int idx);
|
||||
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
|
||||
LUA_API void (lua_remove) (lua_State *L, int idx);
|
||||
LUA_API void (lua_insert) (lua_State *L, int idx);
|
||||
LUA_API void (lua_replace) (lua_State *L, int idx);
|
||||
LUA_API int (lua_checkstack) (lua_State *L, int sz);
|
||||
|
||||
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
|
||||
|
||||
|
||||
/*
|
||||
** access functions (stack -> C)
|
||||
*/
|
||||
|
||||
LUA_API int (lua_isnumber) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isstring) (lua_State *L, int idx);
|
||||
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
||||
LUA_API int (lua_type) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
||||
|
||||
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
|
||||
|
||||
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
|
||||
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
|
||||
LUA_API int (lua_toboolean) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUA_API size_t (lua_objlen) (lua_State *L, int idx);
|
||||
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
|
||||
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
|
||||
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
|
||||
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** push functions (C -> stack)
|
||||
*/
|
||||
LUA_API void (lua_pushnil) (lua_State *L);
|
||||
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
|
||||
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
|
||||
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
|
||||
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
|
||||
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
|
||||
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
|
||||
LUA_API void (lua_pushboolean) (lua_State *L, int b);
|
||||
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
|
||||
LUA_API int (lua_pushthread) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void (lua_gettable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawget) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
|
||||
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
||||
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
|
||||
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||
LUA_API void (lua_getfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** set functions (stack -> Lua)
|
||||
*/
|
||||
LUA_API void (lua_settable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawset) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
|
||||
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
|
||||
LUA_API int (lua_setfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** `load' and `call' functions (load and run Lua code)
|
||||
*/
|
||||
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
|
||||
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname);
|
||||
|
||||
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
|
||||
|
||||
|
||||
/*
|
||||
** coroutine functions
|
||||
*/
|
||||
LUA_API int (lua_yield) (lua_State *L, int nresults);
|
||||
LUA_API int (lua_resume) (lua_State *L, int narg);
|
||||
LUA_API int (lua_status) (lua_State *L);
|
||||
|
||||
/*
|
||||
** garbage-collection function and options
|
||||
*/
|
||||
|
||||
#define LUA_GCSTOP 0
|
||||
#define LUA_GCRESTART 1
|
||||
#define LUA_GCCOLLECT 2
|
||||
#define LUA_GCCOUNT 3
|
||||
#define LUA_GCCOUNTB 4
|
||||
#define LUA_GCSTEP 5
|
||||
#define LUA_GCSETPAUSE 6
|
||||
#define LUA_GCSETSTEPMUL 7
|
||||
#define LUA_GCISRUNNING 9
|
||||
|
||||
LUA_API int (lua_gc) (lua_State *L, int what, int data);
|
||||
|
||||
|
||||
/*
|
||||
** miscellaneous functions
|
||||
*/
|
||||
|
||||
LUA_API int (lua_error) (lua_State *L);
|
||||
|
||||
LUA_API int (lua_next) (lua_State *L, int idx);
|
||||
|
||||
LUA_API void (lua_concat) (lua_State *L, int n);
|
||||
|
||||
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
||||
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define lua_pop(L,n) lua_settop(L, -(n)-1)
|
||||
|
||||
#define lua_newtable(L) lua_createtable(L, 0, 0)
|
||||
|
||||
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
|
||||
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||
|
||||
#define lua_strlen(L,i) lua_objlen(L, (i))
|
||||
|
||||
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
|
||||
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
|
||||
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
|
||||
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
|
||||
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
|
||||
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
||||
|
||||
#define lua_pushliteral(L, s) \
|
||||
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
|
||||
|
||||
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
|
||||
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
|
||||
|
||||
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** compatibility macros and functions
|
||||
*/
|
||||
|
||||
#define lua_open() luaL_newstate()
|
||||
|
||||
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
|
||||
|
||||
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
|
||||
|
||||
#define lua_Chunkreader lua_Reader
|
||||
#define lua_Chunkwriter lua_Writer
|
||||
|
||||
|
||||
/* hack */
|
||||
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
** Debug API
|
||||
** =======================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Event codes
|
||||
*/
|
||||
#define LUA_HOOKCALL 0
|
||||
#define LUA_HOOKRET 1
|
||||
#define LUA_HOOKLINE 2
|
||||
#define LUA_HOOKCOUNT 3
|
||||
#define LUA_HOOKTAILRET 4
|
||||
|
||||
|
||||
/*
|
||||
** Event masks
|
||||
*/
|
||||
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
|
||||
#define LUA_MASKRET (1 << LUA_HOOKRET)
|
||||
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
|
||||
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
|
||||
|
||||
typedef struct lua_Debug lua_Debug; /* activation record */
|
||||
|
||||
|
||||
/* Functions to be called by the debuger in specific events */
|
||||
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
|
||||
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L);
|
||||
LUA_API int lua_gethookmask (lua_State *L);
|
||||
LUA_API int lua_gethookcount (lua_State *L);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUA_API void *lua_upvalueid (lua_State *L, int idx, int n);
|
||||
LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2);
|
||||
LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname, const char *mode);
|
||||
LUA_API const lua_Number *lua_version (lua_State *L);
|
||||
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx);
|
||||
LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum);
|
||||
LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum);
|
||||
|
||||
/* From Lua 5.3. */
|
||||
LUA_API int lua_isyieldable (lua_State *L);
|
||||
|
||||
|
||||
struct lua_Debug {
|
||||
int event;
|
||||
const char *name; /* (n) */
|
||||
const char *namewhat; /* (n) `global', `local', `field', `method' */
|
||||
const char *what; /* (S) `Lua', `C', `main', `tail' */
|
||||
const char *source; /* (S) */
|
||||
int currentline; /* (l) */
|
||||
int nups; /* (u) number of upvalues */
|
||||
int linedefined; /* (S) */
|
||||
int lastlinedefined; /* (S) */
|
||||
char short_src[LUA_IDSIZE]; /* (S) */
|
||||
/* private part */
|
||||
int i_ci; /* active function */
|
||||
};
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#endif
|
||||
9
inc/lua/lua.hpp
Normal file
9
inc/lua/lua.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// C++ wrapper for LuaJIT header files.
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "luajit.h"
|
||||
}
|
||||
|
||||
BIN
inc/lua/lua5.1.dll
Normal file
BIN
inc/lua/lua5.1.dll
Normal file
Binary file not shown.
152
inc/lua/luaconf.h
Normal file
152
inc/lua/luaconf.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
** Configuration header.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef luaconf_h
|
||||
#define luaconf_h
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Default path for loading Lua and C modules with require(). */
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
** In Windows, any exclamation mark ('!') in the path is replaced by the
|
||||
** path of the directory of the executable file of the current process.
|
||||
*/
|
||||
#define LUA_LDIR "!\\lua\\"
|
||||
#define LUA_CDIR "!\\"
|
||||
#define LUA_PATH_DEFAULT \
|
||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
|
||||
#define LUA_CPATH_DEFAULT \
|
||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
||||
#else
|
||||
/*
|
||||
** Note to distribution maintainers: do NOT patch the following lines!
|
||||
** Please read ../doc/install.html#distro and pass PREFIX=/usr instead.
|
||||
*/
|
||||
#ifndef LUA_MULTILIB
|
||||
#define LUA_MULTILIB "lib"
|
||||
#endif
|
||||
#ifndef LUA_LMULTILIB
|
||||
#define LUA_LMULTILIB "lib"
|
||||
#endif
|
||||
#define LUA_LROOT "/usr/local"
|
||||
#define LUA_LUADIR "/lua/5.1/"
|
||||
#define LUA_LJDIR "/luajit-2.1.0-beta3/"
|
||||
|
||||
#ifdef LUA_ROOT
|
||||
#define LUA_JROOT LUA_ROOT
|
||||
#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR
|
||||
#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR
|
||||
#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua"
|
||||
#define LUA_RCPATH ";" LUA_RCDIR "?.so"
|
||||
#else
|
||||
#define LUA_JROOT LUA_LROOT
|
||||
#define LUA_RLPATH
|
||||
#define LUA_RCPATH
|
||||
#endif
|
||||
|
||||
#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua"
|
||||
#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR
|
||||
#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR
|
||||
#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua"
|
||||
#define LUA_LCPATH1 ";" LUA_LCDIR "?.so"
|
||||
#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so"
|
||||
|
||||
#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH
|
||||
#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2
|
||||
#endif
|
||||
|
||||
/* Environment variable names for path overrides and initialization code. */
|
||||
#define LUA_PATH "LUA_PATH"
|
||||
#define LUA_CPATH "LUA_CPATH"
|
||||
#define LUA_INIT "LUA_INIT"
|
||||
|
||||
/* Special file system characters. */
|
||||
#if defined(_WIN32)
|
||||
#define LUA_DIRSEP "\\"
|
||||
#else
|
||||
#define LUA_DIRSEP "/"
|
||||
#endif
|
||||
#define LUA_PATHSEP ";"
|
||||
#define LUA_PATH_MARK "?"
|
||||
#define LUA_EXECDIR "!"
|
||||
#define LUA_IGMARK "-"
|
||||
#define LUA_PATH_CONFIG \
|
||||
LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \
|
||||
LUA_EXECDIR "\n" LUA_IGMARK "\n"
|
||||
|
||||
/* Quoting in error messages. */
|
||||
#define LUA_QL(x) "'" x "'"
|
||||
#define LUA_QS LUA_QL("%s")
|
||||
|
||||
/* Various tunables. */
|
||||
#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */
|
||||
#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */
|
||||
#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */
|
||||
#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */
|
||||
#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */
|
||||
|
||||
/* Configuration for the frontend (the luajit executable). */
|
||||
#if defined(luajit_c)
|
||||
#define LUA_PROGNAME "luajit" /* Fallback frontend name. */
|
||||
#define LUA_PROMPT "> " /* Interactive prompt. */
|
||||
#define LUA_PROMPT2 ">> " /* Continuation prompt. */
|
||||
#define LUA_MAXINPUT 512 /* Max. input line length. */
|
||||
#endif
|
||||
|
||||
/* Note: changing the following defines breaks the Lua 5.1 ABI. */
|
||||
#define LUA_INTEGER ptrdiff_t
|
||||
#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */
|
||||
/*
|
||||
** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using
|
||||
** unreasonable amounts of stack space, but still retain ABI compatibility.
|
||||
** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it.
|
||||
*/
|
||||
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
|
||||
|
||||
/* The following defines are here only for compatibility with luaconf.h
|
||||
** from the standard Lua distribution. They must not be changed for LuaJIT.
|
||||
*/
|
||||
#define LUA_NUMBER_DOUBLE
|
||||
#define LUA_NUMBER double
|
||||
#define LUAI_UACNUMBER double
|
||||
#define LUA_NUMBER_SCAN "%lf"
|
||||
#define LUA_NUMBER_FMT "%.14g"
|
||||
#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n))
|
||||
#define LUAI_MAXNUMBER2STR 32
|
||||
#define LUA_INTFRMLEN "l"
|
||||
#define LUA_INTFRM_T long
|
||||
|
||||
/* Linkage of public API functions. */
|
||||
#if defined(LUA_BUILD_AS_DLL)
|
||||
#if defined(LUA_CORE) || defined(LUA_LIB)
|
||||
#define LUA_API __declspec(dllexport)
|
||||
#else
|
||||
#define LUA_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define LUA_API extern
|
||||
#endif
|
||||
|
||||
#define LUALIB_API LUA_API
|
||||
|
||||
/* Support for internal assertions. */
|
||||
#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#define lua_assert(x) assert(x)
|
||||
#endif
|
||||
#ifdef LUA_USE_APICHECK
|
||||
#define luai_apicheck(L, o) { (void)L; assert(o); }
|
||||
#else
|
||||
#define luai_apicheck(L, o) { (void)L; }
|
||||
#endif
|
||||
|
||||
#endif
|
||||
79
inc/lua/luajit.h
Normal file
79
inc/lua/luajit.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
|
||||
**
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
*/
|
||||
|
||||
#ifndef _LUAJIT_H
|
||||
#define _LUAJIT_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUAJIT_VERSION "LuaJIT 2.1.0-beta3"
|
||||
#define LUAJIT_VERSION_NUM 20100 /* Version 2.1.0 = 02.01.00. */
|
||||
#define LUAJIT_VERSION_SYM luaJIT_version_2_1_0_beta3
|
||||
#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2017 Mike Pall"
|
||||
#define LUAJIT_URL "http://luajit.org/"
|
||||
|
||||
/* Modes for luaJIT_setmode. */
|
||||
#define LUAJIT_MODE_MASK 0x00ff
|
||||
|
||||
enum {
|
||||
LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */
|
||||
LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */
|
||||
|
||||
LUAJIT_MODE_FUNC, /* Change mode for a function. */
|
||||
LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */
|
||||
LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */
|
||||
|
||||
LUAJIT_MODE_TRACE, /* Flush a compiled trace. */
|
||||
|
||||
LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */
|
||||
|
||||
LUAJIT_MODE_MAX
|
||||
};
|
||||
|
||||
/* Flags or'ed in to the mode. */
|
||||
#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */
|
||||
#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */
|
||||
#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */
|
||||
|
||||
/* LuaJIT public C API. */
|
||||
|
||||
/* Control the JIT engine. */
|
||||
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
|
||||
|
||||
/* Low-overhead profiling API. */
|
||||
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
|
||||
int samples, int vmstate);
|
||||
LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
|
||||
luaJIT_profile_callback cb, void *data);
|
||||
LUA_API void luaJIT_profile_stop(lua_State *L);
|
||||
LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
|
||||
int depth, size_t *len);
|
||||
|
||||
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
|
||||
LUA_API void LUAJIT_VERSION_SYM(void);
|
||||
|
||||
#endif
|
||||
43
inc/lua/lualib.h
Normal file
43
inc/lua/lualib.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
** Standard library header.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LUALIB_H
|
||||
#define _LUALIB_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
#define LUA_COLIBNAME "coroutine"
|
||||
#define LUA_MATHLIBNAME "math"
|
||||
#define LUA_STRLIBNAME "string"
|
||||
#define LUA_TABLIBNAME "table"
|
||||
#define LUA_IOLIBNAME "io"
|
||||
#define LUA_OSLIBNAME "os"
|
||||
#define LUA_LOADLIBNAME "package"
|
||||
#define LUA_DBLIBNAME "debug"
|
||||
#define LUA_BITLIBNAME "bit"
|
||||
#define LUA_JITLIBNAME "jit"
|
||||
#define LUA_FFILIBNAME "ffi"
|
||||
|
||||
LUALIB_API int luaopen_base(lua_State *L);
|
||||
LUALIB_API int luaopen_math(lua_State *L);
|
||||
LUALIB_API int luaopen_string(lua_State *L);
|
||||
LUALIB_API int luaopen_table(lua_State *L);
|
||||
LUALIB_API int luaopen_io(lua_State *L);
|
||||
LUALIB_API int luaopen_os(lua_State *L);
|
||||
LUALIB_API int luaopen_package(lua_State *L);
|
||||
LUALIB_API int luaopen_debug(lua_State *L);
|
||||
LUALIB_API int luaopen_bit(lua_State *L);
|
||||
LUALIB_API int luaopen_jit(lua_State *L);
|
||||
LUALIB_API int luaopen_ffi(lua_State *L);
|
||||
|
||||
LUALIB_API void luaL_openlibs(lua_State *L);
|
||||
|
||||
#ifndef lua_assert
|
||||
#define lua_assert(x) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
524
luahooks32.lua
Normal file
524
luahooks32.lua
Normal file
@@ -0,0 +1,524 @@
|
||||
|
||||
hk = require('luahooks32core')
|
||||
|
||||
-- Memory protection
|
||||
-- Allow writing to code areas
|
||||
local PAGE_EXECUTE_READWRITE = 0x40
|
||||
function hk.protectRWX(addr, len)
|
||||
return hk.protect(addr, len, PAGE_EXECUTE_READWRITE)
|
||||
end
|
||||
|
||||
hk._openImages = hk._openImages or {}
|
||||
-- open library memoization
|
||||
function hk.open(name)
|
||||
if name==nil then name = '_baseImage' end
|
||||
local img = hk._openImages[name]
|
||||
if img then return img end
|
||||
img = hk._openRaw(name~='_baseImage' and name or nil)
|
||||
hk._openImages[name] = img
|
||||
return img
|
||||
end
|
||||
|
||||
-- Scanning
|
||||
-- Convert text-style scan pattern into code-style pattern
|
||||
-- Input: '11 22 33 ? 44'
|
||||
-- Output: '\x11\x22\x33\x00\x44', 'xxx?x'
|
||||
local function patToCode(p)
|
||||
if p:find('^str:') then -- raw string
|
||||
local pat = p:sub(4, #p)
|
||||
local mask = ('x'):rep(#pat)
|
||||
return pat, mask
|
||||
else -- hex pattern
|
||||
if p:find('[^a-fA-F0-9 \r\n\t%?]') then
|
||||
error('hk pattern: pattern contains invalid character', 3) end
|
||||
local patT, maskT = {}, {}
|
||||
for word in p:gmatch('[^ \r\n\t]+') do
|
||||
if word:find('%?') then
|
||||
table.insert(patT, string.char(0))
|
||||
table.insert(maskT, '?')
|
||||
else
|
||||
local val = tonumber(word, 16)
|
||||
assert(val and val>=0 and val<=255, 'invalid word in scan pattern: '..word, 3)
|
||||
table.insert(patT, string.char(val))
|
||||
table.insert(maskT, 'x')
|
||||
end
|
||||
end
|
||||
return table.concat(patT), table.concat(maskT)
|
||||
end
|
||||
end
|
||||
-- Scan
|
||||
-- hk.scan('15 1 ? 1f') - return first match (or nil)
|
||||
-- hk.scan('15 1 ? 1f', 1) - return nth match (or nil) (starting from 1)
|
||||
-- hk.scan('15 1 ? 1f', true) - return list of all matches (or {})
|
||||
local unhookAll, rehookAll
|
||||
hk._scanResultCache = hk._scanResultCache or {}
|
||||
function hk.scan(pat, opt, img)
|
||||
if type(pat)~='string' then
|
||||
error('hk.scan: argument #1: expected string', 2) end
|
||||
local code, mask = patToCode(pat)
|
||||
img = img or hk.open()
|
||||
opt = opt or 1
|
||||
|
||||
local _
|
||||
local cacheEntry = tostring(img)..':'..pat..':'..tostring(opt)
|
||||
local res = hk._scanResultCache[cacheEntry]
|
||||
if res then return res end
|
||||
|
||||
if opt==true then -- find all matches
|
||||
res = {}
|
||||
unhookAll()
|
||||
while true do
|
||||
local suc,a = pcall(hk._scanRaw, img, code, mask, #res)
|
||||
if not a then break end
|
||||
table.insert(res, a)
|
||||
end
|
||||
rehookAll()
|
||||
elseif type(opt)=='number' and opt%1==0 and opt>0 then -- find nth match
|
||||
unhookAll()
|
||||
suc,res = pcall(hk._scanRaw, img, code, mask, opt-1)
|
||||
rehookAll()
|
||||
else
|
||||
error('hk.scan: argument #2: expected true, positive integer, or nil', 2)
|
||||
end
|
||||
|
||||
hk._scanResultCache[cacheEntry] = res
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
-- Writing
|
||||
local function hexToStr(h)
|
||||
local t = {}
|
||||
if h:find('[^a-zA-Z0-9 \r\n\t]') then
|
||||
error('hk.write: invalid character in hex string', 3) end
|
||||
for w in h:gmatch('[^ \r\n\t]+') do
|
||||
local v = tonumber(w, 16)
|
||||
if not (v and v>=0 and v<=255) then
|
||||
error('hk.write: invalid hex number: '..w, 3) end
|
||||
table.insert(t, string.char(v))
|
||||
end
|
||||
return table.concat(t)
|
||||
end
|
||||
local customWriters = {
|
||||
hex = function(addr, str, len)
|
||||
local data = hexToStr(str)
|
||||
if len then return addr+#data end
|
||||
return hk.writeStr(addr, data)
|
||||
end,
|
||||
str = function(addr, data, len)
|
||||
if len then return addr+#data end
|
||||
return hk.writeStr(addr, data)
|
||||
end,
|
||||
char = function(addr, val, len)
|
||||
if len then return addr+1 end
|
||||
return hk.writeChar(addr, val)
|
||||
end,
|
||||
short = function(addr, val, len)
|
||||
if len then return addr+2 end
|
||||
return hk.writeShort(addr, val)
|
||||
end,
|
||||
int = function(addr, val, len)
|
||||
if len then return addr+4 end
|
||||
return hk.writeInt(addr, val)
|
||||
end,
|
||||
rel = function(addr, val, len)
|
||||
if len then return addr+4 end
|
||||
return hk.writeInt(addr, val - (addr+4))
|
||||
end,
|
||||
float = function(addr, val, len)
|
||||
if len then return addr+4 end
|
||||
return hk.writeFloat(addr, val)
|
||||
end,
|
||||
double = function(addr, val, len)
|
||||
if len then return addr+8 end
|
||||
return hk.writeFloat(addr, val)
|
||||
end,
|
||||
}
|
||||
local customWriterDefaults = {
|
||||
number = 'int',
|
||||
string = 'hex',
|
||||
}
|
||||
local function writeData(addr, data, typ, len)
|
||||
if type(data)=='table' then
|
||||
if typ then
|
||||
error('hk.write: argument #3: expected nil when argument #2 is table', 2) end
|
||||
if not table.islist(data) then
|
||||
error('hk.write: argument #2: table must be a list', 2) end
|
||||
|
||||
local ntyp = nil
|
||||
for i,v in ipairs(data) do
|
||||
if type(v)=='string' and v:sub(#v,#v)==':' then
|
||||
ntyp = v:sub(1,#v-1)
|
||||
if not customWriters[ntyp] then
|
||||
error('hk.write: argument #2: expected writer type at index '
|
||||
..i..', got \''..ntyp..'\'', 2) end
|
||||
else
|
||||
addr = hk.write(addr, data[i], ntyp, len)
|
||||
ntyp = nil
|
||||
end
|
||||
end
|
||||
return addr
|
||||
else
|
||||
if not typ then
|
||||
typ = customWriterDefaults[type(data)]
|
||||
if not typ then
|
||||
error('hk.write: argument #2: expected string, number, or table') end
|
||||
end
|
||||
if not customWriters[typ] then
|
||||
error('hk.write: argument #3: expected writer type, got \''..typ..'\'') end
|
||||
return customWriters[typ](addr, data, len)
|
||||
end
|
||||
end
|
||||
function hk.write(addr, data, typ)
|
||||
return writeData(addr, data, typ, false)
|
||||
end
|
||||
-- write to a write-protected area by turning off write protection first,
|
||||
-- then re-enable write protection afterward
|
||||
function hk.patch(addr, data, typ)
|
||||
local len = writeData(addr, data, typ, true) - addr
|
||||
local oldProt = hk.protectRWX(addr, len)
|
||||
local addrW = writeData(addr, data, typ, false)
|
||||
hk.protect(addr, len, oldProt)
|
||||
return addrW
|
||||
end
|
||||
|
||||
|
||||
-- Hooking
|
||||
local function writeTrampoline(trAddr, hkAddr, regsPtr)
|
||||
return hk.write(trAddr, {
|
||||
-- save registers and flags
|
||||
'a3',regsPtr, -- mov [regsPtr],eax
|
||||
'b8',regsPtr, -- mov eax,regsPtr
|
||||
'89 58 04', -- mov [eax+0x04],ebx
|
||||
'89 48 08', -- mov [eax+0x08],ecx
|
||||
'89 50 0c', -- mov [eax+0x0c],edx
|
||||
'89 70 10', -- mov [eax+0x10],esi
|
||||
'89 78 14', -- mov [eax+0x14],edi
|
||||
'89 60 18', -- mov [eax+0x18],esp
|
||||
'89 68 1c', -- mov [eax+0x1c],ebp
|
||||
'c7 40 20',hkAddr, -- mov [eax+0x20],hkAddr (res->eip)
|
||||
'9c', -- pushfd
|
||||
'5a', -- pop edx
|
||||
'89 50 24', -- mov [eax+0x24],edx (regs->flags)
|
||||
'c7 40 28',0, -- mov [eax+0x28],0 (regs->brk = 0)
|
||||
-- load arguments into ecx+edx and call
|
||||
'89 c1', -- mov ecx,eax
|
||||
'ba',hk._getLuaStatePtr(), -- mov edx,L
|
||||
'e8','rel:',hk._getCallbackPtr(), -- call hook function
|
||||
-- restore registers
|
||||
'b8',regsPtr, -- mov eax,regsPtr
|
||||
'8b 58 04', -- mov ebx,[eax+0x04]
|
||||
'8b 48 08', -- mov ecx,[eax+0x08]
|
||||
'8b 50 0c', -- mov edx,[eax+0x0c]
|
||||
'8b 70 10', -- mov esi,[eax+0x10]
|
||||
'8b 78 14', -- mov edi,[eax+0x14]
|
||||
'8b 60 18', -- mov esp,[eax+0x18]
|
||||
'8b 68 1c', -- mov ebp,[eax+0x1c]
|
||||
-- if regs.brk, restore eax and retn; otherwise continue
|
||||
'83 78 28 00', -- cmp dword ptr [eax+0x28],0
|
||||
'74 06', -- je (past eax restore and retn)
|
||||
'a1',regsPtr, -- mov eax,[regsPtr]
|
||||
'c3', -- retn
|
||||
-- restore flags and eax
|
||||
'8b 50 24', -- mov edx,[eax+0x24] (regs->flags)
|
||||
'52', -- push edx
|
||||
'9d', -- popfd
|
||||
'a1',regsPtr, -- mov eax,[regsPtr]
|
||||
-- after this, moved code will be written, followed by a jump back
|
||||
})
|
||||
end
|
||||
local function writeTrampolineReturn(trAddr, retAddr)
|
||||
return hk.write(trAddr, {
|
||||
'e9','rel:',retAddr, -- jmp retAddr
|
||||
})
|
||||
end
|
||||
local regsStructSize = 4*11
|
||||
local regsStruct = {
|
||||
eax= 0, ebx= 4, ecx= 8, edx=12,
|
||||
esi=16, edi=20, esp=24, ebp=28,
|
||||
eip=32, flags=36, brk=40,
|
||||
}
|
||||
local regsList = {'eax','ebx','ecx','edx','esi','edi','esp','ebp','eip','flags','brk'}
|
||||
local function newRegs()
|
||||
return hk.malloc(regsStructSize)
|
||||
end
|
||||
local function readRegsStruct(regsPtr)
|
||||
local regs = {}
|
||||
for _,regname in ipairs(regsList) do
|
||||
regs[regname] = hk.readInt(regsPtr + regsStruct[regname])
|
||||
end
|
||||
return regs
|
||||
end
|
||||
|
||||
-- Basic instruction length determination for automatic trampoline construction
|
||||
-- Add to this table as needed to define instructions
|
||||
-- a value of true indicates a position-dependent instruction that cannot be moved
|
||||
local instrLen = {
|
||||
['1b'] = {
|
||||
['c9'] = 2, -- sbb ecx,ecx
|
||||
},
|
||||
['23'] = {
|
||||
['c8'] = 2, -- and ecx,eax
|
||||
},
|
||||
['33'] = {
|
||||
['c4'] = 2, -- xor eax,esp
|
||||
},
|
||||
['3b'] = {
|
||||
['15'] = 6, -- cmp edx,i32
|
||||
},
|
||||
['50'] = 1, -- push eax
|
||||
['51'] = 1, -- push ecx
|
||||
['53'] = 1, -- push ebx
|
||||
['55'] = 1, -- push ebp
|
||||
['56'] = 1, -- push esi
|
||||
['57'] = 1, -- push edi
|
||||
['5d'] = 1, -- pop ebp
|
||||
['5e'] = 1, -- pop esi
|
||||
['5f'] = 1, -- pop edi
|
||||
['68'] = 5, -- push i32
|
||||
['6a'] = 2, -- push i8
|
||||
['72'] = true, -- jb rel8
|
||||
['74'] = true, -- jz rel8
|
||||
['75'] = true, -- jnz rel8
|
||||
['81'] = {
|
||||
['ec'] = 6, -- sub esp,i32
|
||||
['c2'] = 6, -- add edx,i32
|
||||
},
|
||||
['83'] = {
|
||||
['c4'] = 3, -- add esp,i8
|
||||
['e4'] = 3, -- and esp,i8
|
||||
['ec'] = 3, -- sub esp,i8
|
||||
},
|
||||
['85'] = {
|
||||
['c0'] = 2, -- test eax,eax
|
||||
},
|
||||
['89'] = {
|
||||
['0d'] = 6, -- mov [i32],ecx
|
||||
['15'] = 6, -- mov [i32],edx
|
||||
},
|
||||
['8b'] = {
|
||||
['0d'] = 6, -- mov ecx,i32
|
||||
['40'] = 3, -- mov eax,[eax+i8]
|
||||
['44'] = {
|
||||
['24'] = 4, -- mov eax,[esp+i8]
|
||||
},
|
||||
['45'] = 3, -- mov eax,[ebp+i8]
|
||||
['6b'] = 3, -- mov ebp,[ebx+i8]
|
||||
['c8'] = 2, -- mov ecx,eax
|
||||
['dc'] = 2, -- mov ebx,esp
|
||||
['e5'] = 2, -- mov esp,ebp
|
||||
['ec'] = 2, -- mov ebp,esp
|
||||
['f1'] = 2, -- mov esi,ecx
|
||||
},
|
||||
['8d'] = {
|
||||
['34'] = {
|
||||
['01'] = 3, -- lea esi,[ecx+eax]
|
||||
},
|
||||
['90'] = 6, -- lea edx,[eax+i32]
|
||||
},
|
||||
['a1'] = 5, -- mov eax,i32
|
||||
['b8'] = 5, -- mov eax,i32
|
||||
['c3'] = 1, -- retn
|
||||
['d9'] = {
|
||||
['47'] = 3, -- fld:32 [edi+i8]
|
||||
['87'] = 6, -- fld:32 [edi+i32]
|
||||
},
|
||||
['dd'] = {
|
||||
['5c'] = {
|
||||
['24'] = 4, -- fstp:64 [esp+i8]
|
||||
},
|
||||
},
|
||||
['e8'] = true, -- call rel32
|
||||
['f7'] = {
|
||||
['d9'] = 2, -- neg ecx
|
||||
},
|
||||
}
|
||||
local function readByteHex(addr)
|
||||
return ('%02x'):format(hk.readChar(addr)%256)
|
||||
end
|
||||
local jmpoutLen = 5 -- Length of the long jump instruction to be inserted as a hook
|
||||
-- Determine the minimum code length >= jmpoutLen that can be
|
||||
-- copied out into the trampoline.
|
||||
-- Returns false if unrecognized instructions
|
||||
-- Returns true if instructions are position-dependent and cannot be moved
|
||||
local function determineOverwriteLen(addr)
|
||||
local len = 0
|
||||
while len < jmpoutLen do
|
||||
local val = readByteHex(addr)
|
||||
local il = instrLen[val]
|
||||
local ofs = 0
|
||||
while type(il)=='table' do
|
||||
ofs = ofs+1
|
||||
val = readByteHex(addr+ofs)
|
||||
il = il[val]
|
||||
end
|
||||
if not il then return false end
|
||||
if il==true then return true end
|
||||
addr = addr + il
|
||||
len = len + il
|
||||
end
|
||||
return len
|
||||
end
|
||||
-- Write into existing function to jump to trampoline
|
||||
local function writeJumpout(rh)
|
||||
local oldProt = hk.protectRWX(rh.hkAddr, rh.hkLen)
|
||||
local hkAddrW = hk.write(rh.hkAddr, {
|
||||
'e9','rel:',rh.trAddr, -- jmp trAddr
|
||||
})
|
||||
for i = 1, rh.hkLen-jmpoutLen do -- fill extra space with nops
|
||||
hkAddrW = hk.write(hkAddrW, '90')
|
||||
end
|
||||
hk.protect(rh.hkAddr, rh.hkLen, oldProt) -- restore write protection on jumpout
|
||||
return hkAddrW
|
||||
end
|
||||
-- Write code copied from hooked function into trampoline
|
||||
local function writeOldCode(rh)
|
||||
local oldProt = hk.protectRWX(rh.hkAddr, rh.hkLen)
|
||||
hk.writeStr(rh.hkAddr, rh.movedCode)
|
||||
hk.protect(rh.hkAddr, rh.hkLen, oldProt)
|
||||
end
|
||||
|
||||
hk._registeredHooks = hk._registeredHooks or {} -- map of addr -> list of callbacks
|
||||
-- Remove/replace all hooks, used when scanning
|
||||
unhookAll = function()
|
||||
for _,rh in pairs(hk._registeredHooks) do
|
||||
writeOldCode(rh)
|
||||
end
|
||||
end
|
||||
rehookAll = function()
|
||||
for _,rh in pairs(hk._registeredHooks) do
|
||||
writeJumpout(rh)
|
||||
end
|
||||
end
|
||||
-- Called from C in trampoline
|
||||
function _bllua_hk_callback(regsPtr)
|
||||
local regs = readRegsStruct(regsPtr)
|
||||
local rh = hk._registeredHooks[regs.eip]
|
||||
if not rh then
|
||||
error('_bllua_hk_callback: no callback registered at address') end
|
||||
rh.callback(regs)
|
||||
end
|
||||
-- Main raw hooking function
|
||||
function hk.hook(hkAddr, callback, hkLen)
|
||||
if type(hkAddr)~='number' or hkAddr<0 or hkAddr%1~=0 then
|
||||
error('hk.hook: argument #1: expected number >0 integer', 2) end
|
||||
if type(callback)~='function' then
|
||||
error('hk.hook: argument #2: expected function', 2) end
|
||||
if hkLen~=nil and (type(hkLen)~='number' or hkLen<0 or hkLen%1~=0) then
|
||||
error('hk.hook: argument #3: expected nil or number', 2) end
|
||||
|
||||
-- if a hook is already registered, overwrite it
|
||||
-- todo: multiple hooks? package names?
|
||||
if hk._registeredHooks[hkAddr] then
|
||||
print('hk.hook: warning: a hook is already registered at address '..
|
||||
('%08x'):format(hkAddr)..', will overwrite.')
|
||||
hk._registeredHooks[hkAddr].callback = callback
|
||||
return
|
||||
end
|
||||
|
||||
if hkLen then
|
||||
if hkLen<jmpoutLen then
|
||||
error('hk.hook: argument #3: overwrite length must be >= '
|
||||
..jmpoutLen, 2) end
|
||||
else
|
||||
hkLen = determineOverwriteLen(hkAddr)
|
||||
if hkLen==false then
|
||||
error('hk.hook: could not automatically determine instruction length. '
|
||||
..'please specify a length >= '..jmpoutLen..' in argument #3', 2)
|
||||
elseif hkLen==true then
|
||||
error('hk.hook: the hook location contains position-dependent code! '
|
||||
..'please move the hook or use a different hooking method', 2)
|
||||
end
|
||||
end
|
||||
|
||||
-- create register save struct
|
||||
local regsPtr = newRegs()
|
||||
|
||||
-- create trampoline code
|
||||
local movedCode = hk.readStr(hkAddr, hkLen)
|
||||
local trLen = 256 + #movedCode -- eh, good enough
|
||||
local trAddr = hk.malloc(trLen)
|
||||
local trOldProt = hk.protectRWX(trAddr, trLen) -- allow execution
|
||||
local trAddrW = trAddr
|
||||
trAddrW = writeTrampoline(trAddrW, hkAddr, regsPtr)
|
||||
trAddrW = hk.writeStr(trAddrW, movedCode)
|
||||
trAddrW = writeTrampolineReturn(trAddrW, hkAddr + hkLen)
|
||||
|
||||
-- create info struct
|
||||
local rh = {
|
||||
hkAddr = hkAddr,
|
||||
hkLen = hkLen,
|
||||
regsPtr = regsPtr,
|
||||
trAddr = trAddr,
|
||||
trLen = trLen,
|
||||
trOldProt = trOldProt,
|
||||
movedCode = movedCode,
|
||||
callback = callback,
|
||||
}
|
||||
|
||||
-- save to hook registry
|
||||
hk._registeredHooks[hkAddr] = rh
|
||||
|
||||
-- write jump out
|
||||
writeJumpout(rh)
|
||||
end
|
||||
-- Remove a hook made by hk.hookRaw
|
||||
function hk.unhook(hkAddr)
|
||||
if type(hkAddr)~='number' or hkAddr<0 or hkAddr%1~=0 then
|
||||
error('hk.unhook: argument #1: expected number >0 integer', 2) end
|
||||
local rh = hk._registeredHooks[hkAddr]
|
||||
assert(rh, 'hk.unhook: no hook registered at address '..
|
||||
('%08x'):format(hkAddr))
|
||||
|
||||
-- remove jumpout
|
||||
writeOldCode(rh)
|
||||
|
||||
-- delete allocated data
|
||||
hk.protect(rh.trAddr, rh.trLen, rh.trOldProt)
|
||||
hk.free(rh.trAddr)
|
||||
hk.free(rh.regsPtr)
|
||||
|
||||
-- remove from hook registry
|
||||
hk._registeredHooks[hkAddr] = nil
|
||||
end
|
||||
function hex(v) return v and ('%08x'):format(v):sub(1,8) end
|
||||
-- called when blocklua unloads
|
||||
function hk.unhookAll()
|
||||
unhookAll()
|
||||
for _,rh in pairs(hk._registeredHooks) do
|
||||
hk.protect(rh.trAddr, rh.trLen, rh.trOldProt)
|
||||
hk.free(rh.trAddr)
|
||||
hk.free(rh.regsPtr)
|
||||
end
|
||||
hk._registeredHooks = {}
|
||||
end
|
||||
-- Utility to display addresses as hex
|
||||
function hk.hex(v)
|
||||
return ('%08x'):format(v)
|
||||
end
|
||||
|
||||
-- todo: stack manipulation
|
||||
|
||||
|
||||
_bllua_on_unload['libhooks'] = hk.unhookAll
|
||||
|
||||
return hk
|
||||
|
||||
|
||||
-- testing
|
||||
--[[
|
||||
|
||||
'dofile('modules/lualib/luahooks32.lua')
|
||||
|
||||
'f = hk.scan('55 8B EC 83 E4 C0 83 EC 38 56 57 8B 7D 08 8B 47 44 D1 E8 A8 01 74 5C 8B 47 28', 2)
|
||||
|
||||
'hk.hook(f, function(regs) print(regs) end)
|
||||
|
||||
|
||||
not documented:
|
||||
hk.open
|
||||
hk.write / hk.patch formats other than hex
|
||||
hk.protect
|
||||
hk.protectRWX
|
||||
|
||||
]]
|
||||
312
luahooks32core.cpp
Normal file
312
luahooks32core.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
// Uses BlHooks for some things
|
||||
// Todo: Make independent
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Psapi.h>
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
// Custom types
|
||||
void bll_hk_newMetatable(lua_State* L, const char* name, struct luaL_Reg* methods) {
|
||||
if(luaL_newmetatable(L, name)) {
|
||||
if(methods!=NULL)
|
||||
luaL_setfuncs(L, methods, 0);
|
||||
//lua_pushliteral(L, "__index");
|
||||
//lua_settable(L, -3);
|
||||
//lua_pushliteral(L, "__metatable");
|
||||
//lua_pushliteral(L, "access to this metatable is disabled");
|
||||
//lua_settable(L, -3);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Image - Reference to a loaded binary, contains the base pointer and size
|
||||
typedef struct {
|
||||
void* base;
|
||||
size_t size;
|
||||
} bll_hk_image;
|
||||
bll_hk_image* bll_hk_newImage(lua_State* L, void* base, size_t size) {
|
||||
bll_hk_image* img = (bll_hk_image*)lua_newuserdata(L, sizeof(bll_hk_image));
|
||||
luaL_setmetatable(L, "_bllua_hk.image");
|
||||
img->base = base;
|
||||
img->size = size;
|
||||
return img;
|
||||
}
|
||||
int bll_hk_image_tostring(lua_State* L) {
|
||||
bll_hk_image* img = (bll_hk_image*)luaL_checkudata(L, 1, "_bllua_hk.image");
|
||||
char buf[100];
|
||||
sprintf(buf, "image:{addr=%08X,size=%08X}",
|
||||
(unsigned int)img->base,
|
||||
(unsigned int)img->size);
|
||||
lua_pushstring(L, buf);
|
||||
return 1;
|
||||
}
|
||||
struct luaL_Reg bll_hk_image_methods[] = {
|
||||
{"__tostring", bll_hk_image_tostring},
|
||||
NULL,
|
||||
};
|
||||
void bll_hk_initTypeImage(lua_State* L) {
|
||||
bll_hk_newMetatable(L, "_bllua_hk.image", bll_hk_image_methods);
|
||||
}
|
||||
|
||||
// Addr - Just a pointer, can be added/subtracted
|
||||
// Just using numbers for now
|
||||
//typedef struct {
|
||||
// void* a;
|
||||
//} bll_hk_addr;
|
||||
//int bll_hk_newAddr(lua_State* L, void* a) {
|
||||
// bll_hk_addr* addr = (bll_hk_addr*)lua_newuserdata(L, sizeof(bll_hk_addr));
|
||||
// luaL_setmetatable(L, "_bllua_hk.addr");
|
||||
// addr->a = a;
|
||||
// return 1;
|
||||
//}
|
||||
//int bll_hk_addr_tostring(lua_State* L) {
|
||||
// bll_hk_addr* addr = (bll_hk_addr*)luaL_checkudata(L, 1, "_bllua_hk.addr");
|
||||
//
|
||||
// char buf[100];
|
||||
// sprintf(buf, "addr:%08X", (unsigned int)addr->a);
|
||||
// lua_pushstring(L, buf);
|
||||
// return 1;
|
||||
//}
|
||||
//int bll_hk_addr_add(lua_State* L) {
|
||||
// bll_hk_addr* addr = (bll_hk_addr*)luaL_checkudata(L, 1, "_bllua_hk.addr");
|
||||
// size_t ofs = luaL_checkinteger(L, 2);
|
||||
//
|
||||
// bll_hk_newAddr(L, (char*)addr->a + ofs);
|
||||
// return 1;
|
||||
//}
|
||||
//int bll_hk_addr_sub(lua_State* L) {
|
||||
// bll_hk_addr* addr = (bll_hk_addr*)luaL_checkudata(L, 1, "_bllua_hk.addr");
|
||||
// size_t ofs = luaL_checkinteger(L, 2);
|
||||
//
|
||||
// bll_hk_newAddr(L, (char*)addr->a - ofs);
|
||||
// return 1;
|
||||
//}
|
||||
//struct luaL_Reg bll_hk_addr_methods[] = {
|
||||
// {"__tostring", bll_hk_addr_tostring},
|
||||
// {"__add", bll_hk_addr_add},
|
||||
// {"__sub", bll_hk_addr_sub},
|
||||
// NULL,
|
||||
//};
|
||||
//void bll_hk_initTypeAddr(lua_State* L) {
|
||||
// bll_hk_newMetatable(L, "_bllua_hk.addr", bll_hk_addr_methods);
|
||||
//}
|
||||
|
||||
|
||||
// Scanning
|
||||
bool bll_hk_patternMatch(char* addr, const char* pat, const char* mask) {
|
||||
for(; *mask; ++addr, ++pat, ++mask) {
|
||||
if(*mask=='x' && *addr!=*pat)
|
||||
return false;
|
||||
}
|
||||
return !*mask;
|
||||
}
|
||||
void* bll_hk_scan(void* imgBase, size_t imgSize, const char* pat, const char* mask,
|
||||
int skip) {
|
||||
char* scanStart = (char*)imgBase;
|
||||
char* scanEnd = scanStart + imgSize;
|
||||
for(char* addr=scanStart; addr<scanEnd; addr++) {
|
||||
if(bll_hk_patternMatch(addr, pat, mask)) {
|
||||
if(skip==0)
|
||||
return addr;
|
||||
else
|
||||
skip--;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Lua lib functions
|
||||
|
||||
#define BLL_HK_PUSHADDR(_l, _a) lua_pushnumber((_l), (lua_Number)(unsigned int)(_a))
|
||||
#define BLL_HK_CHECKADDR(_l, _i) (void*)luaL_checkinteger((_l), (_i))
|
||||
#define BLL_HK_CHECKSIZET(_l, _i) (size_t)luaL_checkinteger((_l), (_i))
|
||||
|
||||
int bll_libhk_open(lua_State* L) {
|
||||
HMODULE mod;
|
||||
if(lua_isnoneornil(L, 1)) {
|
||||
mod = GetModuleHandle(NULL);
|
||||
} else {
|
||||
const char* modName = luaL_checkstring(L, 1);
|
||||
mod = GetModuleHandle(modName);
|
||||
}
|
||||
if(mod) {
|
||||
MODULEINFO info;
|
||||
GetModuleInformation(GetCurrentProcess(), mod, &info, sizeof(MODULEINFO));
|
||||
bll_hk_newImage(L, info.lpBaseOfDll, info.SizeOfImage);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_scan(lua_State* L) {
|
||||
bll_hk_image* img = (bll_hk_image*)luaL_checkudata(L, 1, "_bllua_hk.image");
|
||||
const char* pat = luaL_checklstring(L, 2, NULL);
|
||||
const char* mask = luaL_checklstring(L, 3, NULL);
|
||||
int skip = luaL_checkinteger(L, 4);
|
||||
void* addr = bll_hk_scan(img->base, img->size, pat, mask, skip);
|
||||
if(addr==NULL)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
BLL_HK_PUSHADDR(L, addr);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readStr(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
size_t len = BLL_HK_CHECKSIZET(L, 2);
|
||||
lua_pushlstring(L, (const char*)addr, len); // based lua handling memory for us
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeStr(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
size_t len = 0;
|
||||
const char* data = luaL_checklstring(L, 2, &len);
|
||||
memcpy(addr, data, len);
|
||||
BLL_HK_PUSHADDR(L, (char*)addr+len);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readChar(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
char data = *(char*)addr;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeChar(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
char data = (char)luaL_checkinteger(L, 2);
|
||||
*(char*)addr = data;
|
||||
BLL_HK_PUSHADDR(L, (char*)addr + 1);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readShort(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
short data = *(short*)addr;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeShort(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
short data = (short)luaL_checkinteger(L, 2);
|
||||
*(short*)addr = data;
|
||||
BLL_HK_PUSHADDR(L, (char*)addr + 2);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readInt(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
int data = *(int*)addr;
|
||||
lua_pushinteger(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeInt(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
int data = (int)luaL_checkinteger(L, 2);
|
||||
*(int*)addr = data;
|
||||
BLL_HK_PUSHADDR(L, (char*)addr + 4);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readFloat(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
float data = *(float*)addr;
|
||||
lua_pushnumber(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeFloat(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
float data = luaL_checknumber(L, 2);
|
||||
*(float*)addr = data;
|
||||
BLL_HK_PUSHADDR(L, (char*)addr + 4);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_readDouble(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
double data = *(double*)addr;
|
||||
lua_pushnumber(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_writeDouble(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
double data = luaL_checknumber(L, 2);
|
||||
*(double *)addr = data;
|
||||
BLL_HK_PUSHADDR(L, (char*)addr + 8);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_protect(lua_State* L) {
|
||||
void* addr = BLL_HK_CHECKADDR(L, 1);
|
||||
size_t len = BLL_HK_CHECKSIZET(L, 2);
|
||||
DWORD newProt = (DWORD)luaL_checkinteger(L, 3);
|
||||
DWORD oldProt = 0;
|
||||
VirtualProtect(addr, len, newProt, &oldProt);
|
||||
lua_pushinteger(L, (lua_Integer)oldProt);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_malloc(lua_State* L) {
|
||||
size_t size = (size_t)luaL_checkinteger(L, 1);
|
||||
void* data = malloc(size);
|
||||
BLL_HK_PUSHADDR(L, data);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_free(lua_State* L) {
|
||||
void* data = BLL_HK_CHECKADDR(L, 1);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
//typedef void(*bll_func_ptr)(void);
|
||||
//int bll_libhk_call(lua_State* L) {
|
||||
// void* jdest = BLL_HK_CHECKADDR(L, 1);
|
||||
// ((bll_func_ptr)jdest)();
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
// Hooks lib
|
||||
|
||||
// regsPtr in ecx, L in edx
|
||||
__declspec(fastcall) void bll_hk_callback(void* regsPtr, lua_State* L) {
|
||||
lua_getglobal(L, "_bllua_hk_callback");
|
||||
BLL_HK_PUSHADDR(L, regsPtr);
|
||||
lua_pcall(L, 1, 0, 0);
|
||||
}
|
||||
int bll_libhk_getLuaStatePtr(lua_State* L) {
|
||||
BLL_HK_PUSHADDR(L, (void*)L);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_getCallbackPtr(lua_State* L) {
|
||||
BLL_HK_PUSHADDR(L, (void*)bll_hk_callback);
|
||||
return 1;
|
||||
}
|
||||
int bll_libhk_getStrPtr(lua_State* L) {
|
||||
const char* str = luaL_checkstring(L, 1);
|
||||
BLL_HK_PUSHADDR(L, (void*)str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg bll_hk_reg[] = {
|
||||
{"_openRaw" , bll_libhk_open },
|
||||
{"_scanRaw" , bll_libhk_scan },
|
||||
{"readStr" , bll_libhk_readStr },
|
||||
{"writeStr" , bll_libhk_writeStr },
|
||||
{"protect" , bll_libhk_protect },
|
||||
{"readChar" , bll_libhk_readChar },
|
||||
{"writeChar" , bll_libhk_writeChar },
|
||||
{"readShort" , bll_libhk_readShort },
|
||||
{"writeShort" , bll_libhk_writeShort },
|
||||
{"readInt" , bll_libhk_readInt },
|
||||
{"writeInt" , bll_libhk_writeInt },
|
||||
{"readFloat" , bll_libhk_readFloat },
|
||||
{"writeFloat" , bll_libhk_writeFloat },
|
||||
{"readDouble" , bll_libhk_readDouble },
|
||||
{"writeDouble", bll_libhk_writeDouble},
|
||||
{"malloc" , bll_libhk_malloc },
|
||||
{"free" , bll_libhk_free },
|
||||
//{"call" , bll_libhk_call },
|
||||
{"getStrPtr" , bll_libhk_getStrPtr },
|
||||
{"_getLuaStatePtr", bll_libhk_getLuaStatePtr},
|
||||
{"_getCallbackPtr", bll_libhk_getCallbackPtr},
|
||||
NULL,
|
||||
};
|
||||
extern "C" int __declspec(dllexport) luaopen_luahooks32core(lua_State* L) {
|
||||
luaL_register(L, "luahooks32core", bll_hk_reg);
|
||||
bll_hk_initTypeImage(L);
|
||||
//bll_hk_initTypeAddr(L);
|
||||
return 1;
|
||||
}
|
||||
BIN
luahooks32core.dll
Normal file
BIN
luahooks32core.dll
Normal file
Binary file not shown.
55
readme.md
Normal file
55
readme.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# LuaHooks32
|
||||
Basic x86-32 hooks library for Lua
|
||||
|
||||
## How to Install for Blockland+BlockLua
|
||||
- Install RedBlocklandLoader and BlockLua
|
||||
- Copy `luahooks32.lua` and `luahooks32core.dll` into the `modules/lualib` folder inside your Blockland install folder (you may have to create it)
|
||||
|
||||
## Quick Reference
|
||||
|
||||
`hk = require('luahooks32')` - Load the library
|
||||
|
||||
### Basic Scanning and Patching
|
||||
`addr = hk.scan('01 02 ? ff FF')` - Scan the application binary for a pattern
|
||||
`hk.patch(addr, '01 02 03')` - Patch executable code with a series of bytes
|
||||
|
||||
### Hooking
|
||||
`hk.hook(addr, function(regs) ... end)` - Insert hook into binary code. Registers can be modified inside the hook. Registers are:
|
||||
`regs.eax` `regs.ebx` `regs.ecx` `regs.edx` `regs.esi` `regs.edi` `regs.esp` `regs.ebp` `regs.eip` `regs.flags`
|
||||
There is also `regs.brk`, which if set to 1 inside the hook, will cause the hook to execute a `retn` immediately after completing, returning out of whatever function the hook is inside.
|
||||
Hooks can be inserted anywhere, provided there are at least 5 bytes of position-independent instructions that can be overwritten with a trampoline. Overwritten instructions are then copied into the hook routine.
|
||||
If the basic builtin disassembler fails to detect the length of instructions to overwrite, a third argument to `bl.hook` can be used to manually specify the trampoline length.
|
||||
|
||||
`hk.unhook(addr)` - Remove a previously inserted hook.
|
||||
`hk.unhookAll()` - Remove all hooks.
|
||||
|
||||
### Memory Access
|
||||
|
||||
`hk.write(addr, '01 02 03')` - Write a series of bytes
|
||||
|
||||
`str = hk.readStr(addr)` - Read a null-terminated C-style string from a memory address, and return its contents as a Lua string
|
||||
`hk.writeStr(addr, 'hello\0')` - Write a Lua string to memory. Does NOT null-terminate, so you'll have to append `\0` yourself if you want that.
|
||||
`val = hk.readInt(addr)` - Read a 32-bit signed integer from a memory address (little-endian)
|
||||
`hk.writeInt(addr, val)`
|
||||
`val = hk.readFloat(addr)`
|
||||
`hk.writeFloat(addr, val)`
|
||||
`val = hk.readChar(addr)`
|
||||
`hk.writeChar(addr, val)`
|
||||
`val = hk.readShort(addr)`
|
||||
`hk.writeShort(addr, val)`
|
||||
`val = hk.readDouble(addr)`
|
||||
`hk.writeDouble(addr, val)`
|
||||
Note that these functions can only write into writeable memory (i.e. stack/heap, not code). Use `hk.patch` to write into protected/executable memory.
|
||||
|
||||
`ptr = hk.getStrPtr('str')` - Convert a Lua string into null-terminated C-style and return a pointer to it
|
||||
`print(hk.hex(val))` - Simple utility to convert a number (usually an address) into 32-bit hexadecimal
|
||||
|
||||
`ptr = hk.malloc(numBytes)` - Allocate memory and return a pointer to it
|
||||
`hk.free(ptr)` - Free previously allocated memory
|
||||
|
||||
## Compiling
|
||||
|
||||
With any *32-bit* variant of GCC installed (such as MinGW or MSYS2), run the following command in the repo directory:
|
||||
`g++ luahooks32core.cpp -o luahooks32core.dll -m32 -shared -static-libgcc -Iinc/lua -lpsapi -Linc/lua -llua5.1`
|
||||
|
||||
LuaJIT (lua5.1.dll) can be obtained from https://luajit.org/
|
||||
Reference in New Issue
Block a user