Hola, desde hace un tiempo veo usuarios utilizando "luac" como si se tratase de la panacea en cuanto a seguridad, obfuscación o lo que coño penseis que hace luac, en realidad luac es una simplificacion de tiempo en la carga de lua. Al cargar un archivo lua, internamente lo convierte a luac, lo cual funciona mediante una serie de opcodes como cualquier otro binario. Al abrir un archivo compilado ahorramos ese tiempo.
Os traigo una herramienta muy sencillita para revertir un archivo luac a lua generico.
LuaDec51 - https://github.com/sztupy/luadec51
[Download] http://files.luaforge.net/releases/luad ... -win32-bin
Para usarlo solo hay que utilizar un cmd "luadec file.luac > file.lua"
Y generará el archivo. Como nota al margen, los nombres de variables funciones y tablas se pierden, pero luadec regenera nombres que pueden ser sustituidos, ademas el orden numerico es bastante comodo.
Como ejemplo, podemos ver parte del codigo de PeekMi (thedary)
dben.lib
dben.lua
Para los mas expertos, por si fallara el interpreter, es posible solo hacer un dissasamble del codigo, lo cual nos dice como se comporta en el stack este archivo
Los opcodes en lua son muy sencillitos y el stack es bastante basico asi que no hay perdida.
Un saludo :D
Os traigo una herramienta muy sencillita para revertir un archivo luac a lua generico.
LuaDec51 - https://github.com/sztupy/luadec51
[Download] http://files.luaforge.net/releases/luad ... -win32-bin
Para usarlo solo hay que utilizar un cmd "luadec file.luac > file.lua"
Y generará el archivo. Como nota al margen, los nombres de variables funciones y tablas se pierden, pero luadec regenera nombres que pueden ser sustituidos, ademas el orden numerico es bastante comodo.
Como ejemplo, podemos ver parte del codigo de PeekMi (thedary)
dben.lib
Código: Seleccionar todo
LuaQ @data\dben.lua @ € AÀ @ @ À € @ @ € À À € @ $ € $@ À $€ $À @ $ € € sFileDB pm.db require luasql.sqlite3 PMDAT ð? PMCAT @ PMKEY @ ENCODE DECODE EDITAR NUEVO
BetaToPeekMi CrearDB Listar Guardar Eliminar ? W B G E€ FÀÀ \€€ G@ E@ K@Á À \€€G EÀ … ‹ BA œ €\€ G€ E€ Z €€E€ …€ ‹ÀBœ \ À € Ã@ €‚€ ‡ a€ @þE€ K@à \@ E Z@
€E K  Á€ \@€E K  ÁÀ \@€EÀ … ‹ BA œ €\€ G E Z €€E KÀÄ Ê \€ G€ E€ Z €€E K  Å@ Æ€ÅÁ E FÆÜ €\@ €@üE K@à \@ E K@à \@ E@ K@à \@ € bNumeroExiste env luasql sqlite3 con connect cur1 assert execute SELECT * FROM PM_SYSTEM pairs getcolnames numero close 3 ALTER TABLE 'PM_SYSTEM' RENAME to 'PM_SYSTEM_BETA' D CREATE TABLE 'PM_SYSTEM' ('numero' INTEGER PRIMARY KEY, 'key' text) cur2 SELECT key FROM PM_SYSTEM_BETA row fetch a string format + INSERT INTO PM_SYSTEM ('key') VALUES('%s') key W ! ! ! ! ! ! ! $ $ $ % % % % % % & & ' ' % ( * * * - - - . . . . / / / / 1 1 1 1 1 1 1 3 3 3 4 4 4 4 4 4 6 6 6 7 7 7 7 7 7 7 7 7 8 8 : : : = = = > > > ? sFileDB V (for generator) ! (for state) ! (for control) ! i v A P + E@ F€À \€€ G E K Á À \€€GÀ E€ …À ‹ÀA œ €\€ G@ E€ …À ‹ÀAA œ €\€ G@ E€ …À ‹ÀA œ €\€ G@ E@ À € €B € ^ ÀÿEÀ K à \@ E K à \@ €
env luasql sqlite3 con connect res assert execute CREATE TABLE 'PM_DATOS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text, 'sitioweb' text, 'usuario' text, 'password' text, 'comentarios' text, 'categoria' text) M CREATE TABLE 'PM_CATEGORIAS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text) F CREATE TABLE 'PM_SYSTEM' ('numero' INTEGER PRIMARY KEY, 'key' text) close + C C C C D D D D D E E E E E E E F F F F F F F G G G G G G G I I I J J J N N N O O O P sFile * R ¢ ¡ ‚ ‡ …@ € € €À ‡€ €€… € € €@ ‡€ €…€ € @ €À ‡€ Å€ •À Ê A E €€ \ Z €E €€ \ @ € €A@ Z €@€„€€@ Á Å € Ü B • ‚EÁ FÄ\€ G E KÄÅÁ \€GA EA KAÅÀ \€G E KÁÅÊ \ G E Z @€E Z À€AFEA @ À€JÁ … Å ÆÇœ I… †AGIŽ… †GI… †ÁGI… †HI… Å ÆAÈœ I… †ÁHI‘G €€E @ €€J … Å ÆÇœ I… †AGIŽG €E @ @€J … Å ÆÇœ I… †II’G E É@E KÁÅÅ \ G îE KAÉ\A EA KAÉ\A E KAÉ\A @B €Ã €E ZA @ €AÁ G @€… ^€ € ( error PMDAT sTabla PM_DATOS PMCAT PM_CATEGORIAS PMKEY
PM_SYSTEM SELECT * FROM tonumber WHERE categoria LIKE ' tostring ' env luasql sqlite3 con connect sFileDB cur execute row fetch a ð? tData recordid numero etiqueta sitioweb usuario password
categoria comentario comentarios ke
Código: Seleccionar todo
-- Decompiled using luadec 2.0 standard by sztupy (http://luadec51.luaforge.net)
-- Command line was: dben.lib
sFileDB = "pm.db"
require("luasql.sqlite3")
PMDAT = 1
PMCAT = 2
PMKEY = 3
ENCODE = 1
DECODE = 2
EDITAR = false
NUEVO = true
BetaToPeekMi = function(l_1_0)
bNumeroExiste = false
env = luasql.sqlite3()
con = env:connect(l_1_0)
cur1 = assert(con:execute("SELECT * FROM PM_SYSTEM"))
if cur1 then
for i,v in pairs(cur1:getcolnames()) do
if v == "numero" then
bNumeroExiste = true
end
end
cur1:close()
end
if not bNumeroExiste then
con:execute("ALTER TABLE 'PM_SYSTEM' RENAME to 'PM_SYSTEM_BETA'")
con:execute("CREATE TABLE 'PM_SYSTEM' ('numero' INTEGER PRIMARY KEY, 'key' text)")
cur2 = assert(con:execute("SELECT key FROM PM_SYSTEM_BETA"))
if cur2 then
row = cur2:fetch({}, "a")
repeat
if row then
con:execute(string.format("INSERT INTO PM_SYSTEM ('key') VALUES('%s')", row.key))
do return end
else
cur2:close()
end
end
con:close()
env:close()
-- Warning: missing end command somewhere! Added here
end
-- Warning: missing end command somewhere! Added here
end
end
CrearDB = function(l_2_0)
env = luasql.sqlite3()
con = env:connect(l_2_0)
res = assert(con:execute("CREATE TABLE 'PM_DATOS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text, 'sitioweb' text, 'usuario' text, 'password' text, 'comentarios' text, 'categoria' text)"))
res = assert(con:execute("CREATE TABLE 'PM_CATEGORIAS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text)"))
res = assert(con:execute("CREATE TABLE 'PM_SYSTEM' \t ('numero' INTEGER PRIMARY KEY, 'key' text)"))
if res == 0 then
return true
else
con:close()
env:close()
-- Warning: missing end command somewhere! Added here
end
end
Listar = function(l_3_0, l_3_1)
error = false
if l_3_0 == PMDAT then
sTabla = "PM_DATOS"
elseif l_3_0 == PMCAT then
sTabla = "PM_CATEGORIAS"
elseif l_3_0 == PMKEY then
sTabla = "PM_SYSTEM"
end
local sQuery = "SELECT * FROM " .. sTabla
local tReturn = {}
do
local nCount = 0
if tonumber(l_3_1) then
l_3_1 = tonumber(l_3_1)
else
l_3_1 = 0
end
if l_3_1 and l_3_1 > 0 then
sQuery = sQuery .. " WHERE categoria LIKE '" .. tostring(l_3_1) .. "'"
end
env = luasql.sqlite3()
con = env:connect(sFileDB)
cur = con:execute(sQuery)
row = cur:fetch({}, "a")
if cur then
if row then
nCount = nCount + 1
if l_3_0 == PMDAT then
tData = {recordid = tonumber(row.numero), etiqueta = row.etiqueta, sitioweb = row.sitioweb, usuario = row.usuario, password = row.password, categoria = tonumber(row.categoria), comentario = row.comentarios}
elseif l_3_0 == PMCAT then
tData = {recordid = tonumber(row.numero), etiqueta = row.etiqueta}
elseif l_3_0 == PMKEY then
tData = {recordid = tonumber(row.numero), key = row.key}
end
tReturn[nCount] = tData
Para los mas expertos, por si fallara el interpreter, es posible solo hacer un dissasamble del codigo, lo cual nos dice como se comporta en el stack este archivo
Código: Seleccionar todo
; This file has been disassembled using luadec 2.0 standard by sztupy (http://luadec51.luaforge.net)
; Command line was: -dis dben.lib
; Name:
; Defined at line: 0
; #Upvalues: 0
; #Parameters: 0
; Is_vararg: 2
; Max Stack Size: 2
1 [-]: LOADK R0 K1 ; R0 := "pm.db"
2 [-]: SETGLOBAL R0 K0 ; sFileDB := R0
3 [-]: GETGLOBAL R0 K2 ; R0 := require
4 [-]: LOADK R1 K3 ; R1 := "luasql.sqlite3"
5 [-]: CALL R0 2 1 ; R0(R1)
6 [-]: LOADK R0 K5 ; R0 := 1
7 [-]: SETGLOBAL R0 K4 ; PMDAT := R0
8 [-]: LOADK R0 K7 ; R0 := 2
9 [-]: SETGLOBAL R0 K6 ; PMCAT := R0
10 [-]: LOADK R0 K9 ; R0 := 3
11 [-]: SETGLOBAL R0 K8 ; PMKEY := R0
12 [-]: LOADK R0 K5 ; R0 := 1
13 [-]: SETGLOBAL R0 K10 ; ENCODE := R0
14 [-]: LOADK R0 K7 ; R0 := 2
15 [-]: SETGLOBAL R0 K11 ; DECODE := R0
16 [-]: LOADBOOL R0 0 0 ; R0 := false
17 [-]: SETGLOBAL R0 K12 ; EDITAR := R0
18 [-]: LOADBOOL R0 1 0 ; R0 := true
19 [-]: SETGLOBAL R0 K13 ; NUEVO := R0
20 [-]: CLOSURE R0 0 ; R0 := closure(Function #1)
21 [-]: SETGLOBAL R0 K14 ; BetaToPeekMi := R0
22 [-]: CLOSURE R0 1 ; R0 := closure(Function #2)
23 [-]: SETGLOBAL R0 K15 ; CrearDB := R0
24 [-]: CLOSURE R0 2 ; R0 := closure(Function #3)
25 [-]: SETGLOBAL R0 K16 ; Listar := R0
26 [-]: CLOSURE R0 3 ; R0 := closure(Function #4)
27 [-]: SETGLOBAL R0 K17 ; Guardar := R0
28 [-]: CLOSURE R0 4 ; R0 := closure(Function #5)
29 [-]: SETGLOBAL R0 K18 ; Eliminar := R0
30 [-]: RETURN R0 1 ; return
; Function #1:
;
; Name:
; Defined at line: 29
; #Upvalues: 0
; #Parameters: 1
; Is_vararg: 0
; Max Stack Size: 7
1 [-]: LOADBOOL R1 0 0 ; R1 := false
2 [-]: SETGLOBAL R1 K0 ; bNumeroExiste := R1
3 [-]: GETGLOBAL R1 K2 ; R1 := luasql
4 [-]: GETTABLE R1 R1 K3 ; R1 := R1["sqlite3"]
5 [-]: CALL R1 1 2 ; R1 := R1()
6 [-]: SETGLOBAL R1 K1 ; env := R1
7 [-]: GETGLOBAL R1 K1 ; R1 := env
8 [-]: SELF R1 R1 K5 ; R2 := R1; R1 := R1["connect"]
9 [-]: MOVE R3 R0 ; R3 := R0
10 [-]: CALL R1 3 2 ; R1 := R1(R2,R3)
11 [-]: SETGLOBAL R1 K4 ; con := R1
12 [-]: GETGLOBAL R1 K7 ; R1 := assert
13 [-]: GETGLOBAL R2 K4 ; R2 := con
14 [-]: SELF R2 R2 K8 ; R3 := R2; R2 := R2["execute"]
15 [-]: LOADK R4 K9 ; R4 := "SELECT * FROM PM_SYSTEM"
16 [-]: CALL R2 3 0 ; R2,... := R2(R3,R4)
17 [-]: CALL R1 0 2 ; R1 := R1(R2,...)
18 [-]: SETGLOBAL R1 K6 ; cur1 := R1
19 [-]: GETGLOBAL R1 K6 ; R1 := cur1
20 [-]: TEST R1 0 ; if not R1 then PC := 37
21 [-]: JMP 37 ; PC := 37
22 [-]: GETGLOBAL R1 K10 ; R1 := pairs
23 [-]: GETGLOBAL R2 K6 ; R2 := cur1
24 [-]: SELF R2 R2 K11 ; R3 := R2; R2 := R2["getcolnames"]
25 [-]: CALL R2 2 0 ; R2,... := R2(R3)
26 [-]: CALL R1 0 4 ; R1,R2,R3 := R1(R2,...)
27 [-]: JMP 32 ; PC := 32
28 [-]: EQ 0 R5 K12 ; if R5 ~= "numero" then PC := 32
29 [-]: JMP 32 ; PC := 32
30 [-]: LOADBOOL R6 1 0 ; R6 := true
31 [-]: SETGLOBAL R6 K0 ; bNumeroExiste := R6
32 [-]: TFORLOOP R1 2 ; R4,R5 := R1(R2,R3); if R4 ~= nil then begin PC = 28; R3 := R4 end
33 [-]: JMP 28 ; PC := 28
34 [-]: GETGLOBAL R1 K6 ; R1 := cur1
35 [-]: SELF R1 R1 K13 ; R2 := R1; R1 := R1["close"]
36 [-]: CALL R1 2 1 ; R1(R2)
37 [-]: GETGLOBAL R1 K0 ; R1 := bNumeroExiste
38 [-]: TEST R1 1 ; if R1 then PC := 81
39 [-]: JMP 81 ; PC := 81
40 [-]: GETGLOBAL R1 K4 ; R1 := con
41 [-]: SELF R1 R1 K8 ; R2 := R1; R1 := R1["execute"]
42 [-]: LOADK R3 K14 ; R3 := "ALTER TABLE 'PM_SYSTEM' RENAME to 'PM_SYSTEM_BETA'"
43 [-]: CALL R1 3 1 ; R1(R2,R3)
44 [-]: GETGLOBAL R1 K4 ; R1 := con
45 [-]: SELF R1 R1 K8 ; R2 := R1; R1 := R1["execute"]
46 [-]: LOADK R3 K15 ; R3 := "CREATE TABLE 'PM_SYSTEM' ('numero' INTEGER PRIMARY KEY, 'key' text)"
47 [-]: CALL R1 3 1 ; R1(R2,R3)
48 [-]: GETGLOBAL R1 K7 ; R1 := assert
49 [-]: GETGLOBAL R2 K4 ; R2 := con
50 [-]: SELF R2 R2 K8 ; R3 := R2; R2 := R2["execute"]
51 [-]: LOADK R4 K17 ; R4 := "SELECT key FROM PM_SYSTEM_BETA"
52 [-]: CALL R2 3 0 ; R2,... := R2(R3,R4)
53 [-]: CALL R1 0 2 ; R1 := R1(R2,...)
54 [-]: SETGLOBAL R1 K16 ; cur2 := R1
55 [-]: GETGLOBAL R1 K16 ; R1 := cur2
56 [-]: TEST R1 0 ; if not R1 then PC := 81
57 [-]: JMP 81 ; PC := 81
58 [-]: GETGLOBAL R1 K16 ; R1 := cur2
59 [-]: SELF R1 R1 K19 ; R2 := R1; R1 := R1["fetch"]
60 [-]: NEWTABLE R3 0 0 ; R3 := {}
61 [-]: LOADK R4 K20 ; R4 := "a"
62 [-]: CALL R1 4 2 ; R1 := R1(R2,R3,R4)
63 [-]: SETGLOBAL R1 K18 ; row := R1
64 [-]: GETGLOBAL R1 K18 ; R1 := row
65 [-]: TEST R1 0 ; if not R1 then PC := 78
66 [-]: JMP 78 ; PC := 78
67 [-]: GETGLOBAL R1 K4 ; R1 := con
68 [-]: SELF R1 R1 K8 ; R2 := R1; R1 := R1["execute"]
69 [-]: GETGLOBAL R3 K21 ; R3 := string
70 [-]: GETTABLE R3 R3 K22 ; R3 := R3["format"]
71 [-]: LOADK R4 K23 ; R4 := "INSERT INTO PM_SYSTEM ('key') VALUES('%s')"
72 [-]: GETGLOBAL R5 K18 ; R5 := row
73 [-]: GETTABLE R5 R5 K24 ; R5 := R5["key"]
74 [-]: CALL R3 3 0 ; R3,... := R3(R4,R5)
75 [-]: CALL R1 0 1 ; R1(R2,...)
76 [-]: JMP 78 ; PC := 78
77 [-]: JMP 64 ; PC := 64
78 [-]: GETGLOBAL R1 K16 ; R1 := cur2
79 [-]: SELF R1 R1 K13 ; R2 := R1; R1 := R1["close"]
80 [-]: CALL R1 2 1 ; R1(R2)
81 [-]: GETGLOBAL R1 K4 ; R1 := con
82 [-]: SELF R1 R1 K13 ; R2 := R1; R1 := R1["close"]
83 [-]: CALL R1 2 1 ; R1(R2)
84 [-]: GETGLOBAL R1 K1 ; R1 := env
85 [-]: SELF R1 R1 K13 ; R2 := R1; R1 := R1["close"]
86 [-]: CALL R1 2 1 ; R1(R2)
87 [-]: RETURN R0 1 ; return
; Function #2:
;
; Name:
; Defined at line: 65
; #Upvalues: 0
; #Parameters: 1
; Is_vararg: 0
; Max Stack Size: 5
1 [-]: GETGLOBAL R1 K1 ; R1 := luasql
2 [-]: GETTABLE R1 R1 K2 ; R1 := R1["sqlite3"]
3 [-]: CALL R1 1 2 ; R1 := R1()
4 [-]: SETGLOBAL R1 K0 ; env := R1
5 [-]: GETGLOBAL R1 K0 ; R1 := env
6 [-]: SELF R1 R1 K4 ; R2 := R1; R1 := R1["connect"]
7 [-]: MOVE R3 R0 ; R3 := R0
8 [-]: CALL R1 3 2 ; R1 := R1(R2,R3)
9 [-]: SETGLOBAL R1 K3 ; con := R1
10 [-]: GETGLOBAL R1 K6 ; R1 := assert
11 [-]: GETGLOBAL R2 K3 ; R2 := con
12 [-]: SELF R2 R2 K7 ; R3 := R2; R2 := R2["execute"]
13 [-]: LOADK R4 K8 ; R4 := "CREATE TABLE 'PM_DATOS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text, 'sitioweb' text, 'usuario' text, 'password' text, 'comentarios' text, 'categoria' text)"
14 [-]: CALL R2 3 0 ; R2,... := R2(R3,R4)
15 [-]: CALL R1 0 2 ; R1 := R1(R2,...)
16 [-]: SETGLOBAL R1 K5 ; res := R1
17 [-]: GETGLOBAL R1 K6 ; R1 := assert
18 [-]: GETGLOBAL R2 K3 ; R2 := con
19 [-]: SELF R2 R2 K7 ; R3 := R2; R2 := R2["execute"]
20 [-]: LOADK R4 K9 ; R4 := "CREATE TABLE 'PM_CATEGORIAS' ('numero' INTEGER PRIMARY KEY, 'etiqueta' text)"
21 [-]: CALL R2 3 0 ; R2,... := R2(R3,R4)
22 [-]: CALL R1 0 2 ; R1 := R1(R2,...)
23 [-]: SETGLOBAL R1 K5 ; res := R1
24 [-]: GETGLOBAL R1 K6 ; R1 := assert
25 [-]: GETGLOBAL R2 K3 ; R2 := con
26 [-]: SELF R2 R2 K7 ; R3 := R2; R2 := R2["execute"]
27 [-]: LOADK R4 K10 ; R4 := "CREATE TABLE 'PM_SYSTEM' \t ('numero' INTEGER PRIMARY KEY, 'key' text)"
28 [-]: CALL R2 3 0 ; R2,... := R2(R3,R4)
29 [-]: CALL R1 0 2 ; R1 := R1(R2,...)
30 [-]: SETGLOBAL R1 K5 ; res := R1
31 [-]: GETGLOBAL R1 K5 ; R1 := res
32 [-]: EQ 0 R1 K11 ; if R1 ~= 0 then PC := 37
33 [-]: JMP 37 ; PC := 37
34 [-]: LOADBOOL R1 1 0 ; R1 := true
35 [-]: RETURN R1 2 ; return R1
36 [-]: JMP 37 ; PC := 37
37 [-]: GETGLOBAL R1 K3 ; R1 := con
38 [-]: SELF R1 R1 K12 ; R2 := R1; R1 := R1["close"]
Un saludo :D