Compare commits

..

No commits in common. "ai-dev" and "master" have entirely different histories.

14 changed files with 136 additions and 672 deletions

View File

@ -1,7 +1,3 @@
from django.contrib import admin from django.contrib import admin
from .models import ScriptLog
@admin.register(ScriptLog) # Register your models here.
class ScriptLogAdmin(admin.ModelAdmin):
list_display = ('id', 'input_size', 'output_size', 'created_at')
readonly_fields = ('created_at',)

View File

@ -1,25 +0,0 @@
# Generated by Django 5.2.7 on 2026-01-31 12:29
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ScriptLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('input_code', models.TextField()),
('output_code', models.TextField()),
('input_size', models.IntegerField()),
('output_size', models.IntegerField()),
('created_at', models.DateTimeField(auto_now_add=True)),
],
),
]

View File

@ -1,11 +1,3 @@
from django.db import models from django.db import models
class ScriptLog(models.Model): # Create your models here.
input_code = models.TextField()
output_code = models.TextField()
input_size = models.IntegerField()
output_size = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"ScriptLog {self.id} - {self.created_at}"

View File

@ -1,263 +0,0 @@
import random
import string
import base64
import json
import hashlib
import re
from .parser import Lexer, Parser
class LuauVMObfuscator:
def __init__(self):
self.opcodes = [
"MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETGLOBAL", "SETGLOBAL",
"GETTABLE", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL",
"DIV", "MOD", "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ",
"LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN",
"FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG"
]
self.k1, self.k2, self.k3 = random.randint(500, 2000), random.randint(500, 2000), random.randint(500, 2000)
self.op_to_id = {name: ((self.opcodes.index(name) + self.k1) ^ self.k2) + self.k3 for name in self.opcodes}
self.var_map, self.used_vars = {}, set()
def get_var(self, hint="var"):
if hint in self.var_map: return self.var_map[hint]
c = "Il1"; l = random.randint(24, 32)
v = "_" + "".join(random.choice(c) for _ in range(l))
while v in self.used_vars: v = "_" + "".join(random.choice(c) for _ in range(l))
self.used_vars.add(v); self.var_map[hint] = v
return v
def to_expr(self, n):
r = random.randint(1, 1000)
ch = random.choice(['add', 'sub', 'xor'])
if ch == 'add': return f"({n-r}+{r})"
if ch == 'sub': return f"({n+r}-{r})"
return f"bit32.bxor({n^r},{r})"
def encrypt_string(self, s, key):
res, last = [], key % 256
for i, c in enumerate(s):
k = (key + i + last) % 256
last = ord(c)
res.append(chr(ord(c) ^ k))
return "".join(res)
def minify(self, code):
code = re.sub(r'--.*', '', code)
code = re.sub(r'\s+', ' ', code)
for op in ['==', '~=', '<=', '>=', '=', r'\+', r'\*', '/', '>', '<', ',', ';', ':', '-']:
code = re.sub(r'\s*' + op + r'\s*', op.replace('\\', ''), code)
return code.strip()
def generate_vm_source(self, bytecode):
raw_ins = bytecode['instructions']
indices = list(range(len(raw_ins)))
random.shuffle(indices); pos_map = {orig: i for i, orig in enumerate(indices)}
final_insts = []
for orig_idx in indices:
inst = raw_ins[orig_idx]
next_sh = pos_map[orig_idx + 1] if orig_idx + 1 < len(raw_ins) else 0
final_insts.append([inst[0]&0xFF,(inst[0]>>8)&0xFF,inst[1]&0xFF,inst[2]&0xFF,inst[3]&0xFF,next_sh&0xFF,(next_sh>>8)&0xFF])
inst_str = "".join(chr(i) for inst in final_insts for i in inst)
inst_b64 = base64.b64encode(inst_str.encode('latin-1')).decode()
consts = []
salt = random.randint(100000, 999999)
for i, c in enumerate(bytecode['constants']):
if c['type'] == 'string':
k = (i * 149 + salt) % 256; enc = self.encrypt_string(c['value'], k)
consts.append({"t": 1, "v": base64.b64encode(enc.encode('latin-1')).decode()})
elif c['type'] == 'number': consts.append({"t": 2, "v": c['value']})
else: consts.append({"t": 3, "v": str(c['value'])})
v = {
"BIT": "bit32", "ENV": self.get_var("env"), "DEC": self.get_var("dec"),
"INST": self.get_var("inst"), "CONSTS": self.get_var("consts"), "SALT": self.to_expr(salt),
"EXEC": self.get_var("exec"), "REGS": self.get_var("regs"), "CURR": self.get_var("curr"),
"PTR": self.get_var("ptr"), "OP": self.get_var("op"), "A": self.get_var("a"),
"B": self.get_var("b"), "C": self.get_var("c"), "UNP": "unpack or table.unpack",
"SPW": "task and task.spawn or spawn", "JSON": "game:GetService('HttpService')",
"CHARS": self.get_var("chars"), "LOOKUP": self.get_var("lookup"), "GETC": self.get_var("getc")
}
vm_lua = f'''local {v['ENV']}=setmetatable({{}},{{__index=getfenv()}});
local {v['CHARS']}='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
local {v['LOOKUP']}={{}};
for i=1,64 do {v['LOOKUP']}[{v['CHARS']}:sub(i,i)]=i-1 end;
local function {v['DEC']}(data)
data=data:gsub('[^%a%d%+/]','');
local res={{}};
for i=1,#data,4 do
local a,b,c,d={v['LOOKUP']}[data:sub(i,i)],{v['LOOKUP']}[data:sub(i+1,i+1)],{v['LOOKUP']}[data:sub(i+2,i+2)],{v['LOOKUP']}[data:sub(i+3,i+3)];
local n={v['BIT']}.lshift(a or 0,18)+{v['BIT']}.lshift(b or 0,12)+{v['BIT']}.lshift(c or 0,6)+(d or 0);
res[#res+1]=string.char({v['BIT']}.extract(n,16,8));
if c then res[#res+1]=string.char({v['BIT']}.extract(n,8,8)) end;
if d then res[#res+1]=string.char({v['BIT']}.extract(n,0,8)) end;
end;
return table.concat(res);
end;
local {v['INST']}={v['DEC']}('{inst_b64}');
local {v['CONSTS']}={v['JSON']}:JSONDecode([=[{json.dumps(consts)}]=]);
local {v['EXEC']}=function()
local {v['REGS']}={{}};
local {v['CURR']}={self.to_expr(pos_map[0])};
local function {v['GETC']}(idx)
local c={v['CONSTS']}[idx+1];
if not c then return end;
if c.t==1 then
local r,k={v['DEC']}(c.v),(idx*149+{v['SALT']})%256;
local res,lst={{}},k%256;
for i=1,#r do
local char={v['BIT']}.bxor(string.byte(r,i),(k+i+lst-1)%256);
res[i]=string.char(char);
lst=char;
end;
return table.concat(res);
elseif c.t==3 then return c.v=='true' and true or (c.v=='false' and false or nil) end;
return c.v;
end;
while true do
local {v['PTR']}={v['CURR']}*7+1;
local b1,b2,b3,b4,b5,b6,b7=string.byte({v['INST']},{v['PTR']},{v['PTR']}+6);
if not b1 then break end;
{v['CURR']}=b6+({v['BIT']}.lshift(b7,8));
local {v['OP']}={v['BIT']}.bxor(b1+{v['BIT']}.lshift(b2,8),{self.to_expr(self.k2)})-{self.to_expr(self.k1)};
local {v['A']},{v['B']},{v['C']}=b3,b4,b5;
if {v['OP']}=={self.opcodes.index('MOVE')} then {v['REGS']}[{v['A']}]={v['REGS']}[{v['B']}]
elseif {v['OP']}=={self.opcodes.index('LOADK')} then {v['REGS']}[{v['A']}]={v['GETC']}({v['B']})
elseif {v['OP']}=={self.opcodes.index('GETGLOBAL')} then {v['REGS']}[{v['A']}]={v['ENV']}[{v['GETC']}({v['B']})]
elseif {v['OP']}=={self.opcodes.index('SETGLOBAL')} then {v['ENV']}[{v['GETC']}({v['B']})]={v['REGS']}[{v['A']}]
elseif {v['OP']}=={self.opcodes.index('GETTABLE')} then
local b={v['REGS']}[{v['B']}];
if b then {v['REGS']}[{v['A']}]=b[{v['REGS']}[{v['C']}] or {v['GETC']}({v['C']})] end
elseif {v['OP']}=={self.opcodes.index('SETTABLE')} then
local a={v['REGS']}[{v['A']}];
if a then a[{v['REGS']}[{v['B']}] or {v['GETC']}({v['B']})]={v['REGS']}[{v['C']}] end
elseif {v['OP']}=={self.opcodes.index('SELF')} then
local b={v['REGS']}[{v['B']}];
if b then
{v['REGS']}[{v['A']}+1]=b;
{v['REGS']}[{v['A']}]=b[{v['GETC']}({v['C']})];
end
elseif {v['OP']}=={self.opcodes.index('ADD')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)+({v['REGS']}[{v['C']}] or 0)
elseif {v['OP']}=={self.opcodes.index('SUB')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)-({v['REGS']}[{v['C']}] or 0)
elseif {v['OP']}=={self.opcodes.index('MUL')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)*({v['REGS']}[{v['C']}] or 0)
elseif {v['OP']}=={self.opcodes.index('DIV')} then {v['REGS']}[{v['A']}]=({v['REGS']}[{v['B']}] or 0)/({v['REGS']}[{v['C']}] or 1)
elseif {v['OP']}=={self.opcodes.index('UNM')} then {v['REGS']}[{v['A']}]=-({v['REGS']}[{v['B']}] or 0)
elseif {v['OP']}=={self.opcodes.index('NOT')} then {v['REGS']}[{v['A']}]=not {v['REGS']}[{v['B']}]
elseif {v['OP']}=={self.opcodes.index('LEN')} then {v['REGS']}[{v['A']}]=#{v['REGS']}[{v['B']}] or 0
elseif {v['OP']}=={self.opcodes.index('CALL')} then
local f={v['REGS']}[{v['A']}];
if f then
local args={{}};
if {v['B']}>1 then for i=1,{v['B']}-1 do args[i]={v['REGS']}[{v['A']} + i] end end;
local res={{f(({v['UNP']})(args))}};
if {v['C']}>1 then for i=1,{v['C']}-1 do {v['REGS']}[{v['A']} + i - 1]=res[i] end end;
end
elseif {v['OP']}=={self.opcodes.index('RETURN')} then break end;
end;
end;
({v['SPW']})({v['EXEC']});'''
return self.minify(vm_lua)
def compile_to_bytecode(self, ast):
constants, instructions, locals_map = [], [], {}
self.next_reg = 0
def add_const(val):
if isinstance(val, str) and ((val.startswith("'" ) and val.endswith("'" )) or (val.startswith('"') and val.endswith('"'))): val = val[1:-1]
for i, c in enumerate(constants):
if c['value'] == val: return i
t = 'string' if isinstance(val, str) else 'number'
if val in ['true', 'false', 'nil']: t = 'keyword'
constants.append({'type': t, 'value': val})
return len(constants) - 1
def emit(op, a=0, b=0, c=0): instructions.append([self.op_to_id[op], a, b, c])
def gen_expr(expr, target):
if not expr: return
if expr['type'] == 'NUMBER': emit("LOADK", target, add_const(float(expr['value'])))
elif expr['type'] == 'STRING': emit("LOADK", target, add_const(expr['value']))
elif expr['type'] == 'KEYWORD': emit("LOADK", target, add_const(expr['value']))
elif expr['type'] == 'variable':
if expr['name'] in locals_map: emit("MOVE", target, locals_map[expr['name']])
else: emit("GETGLOBAL", target, add_const(expr['name']))
elif expr['type'] == 'index':
br = self.next_reg; self.next_reg += 1; gen_expr(expr['base'], br)
if expr['key']['type'] == 'STRING':
emit("GETTABLE", target, br, add_const(expr['key']['value']))
else:
kr = self.next_reg; self.next_reg += 1; gen_expr(expr['key'], kr)
emit("GETTABLE", target, br, kr); self.next_reg -= 1
self.next_reg -= 1
elif expr['type'] == 'binary':
lr = self.next_reg; self.next_reg += 1; gen_expr(expr['left'], lr)
rr = self.next_reg; self.next_reg += 1; gen_expr(expr['right'], rr)
op_m = {'+': 'ADD', '-': 'SUB', '*': 'MUL', '/': 'DIV'}
emit(op_m.get(expr['op'], 'ADD'), target, lr, rr); self.next_reg -= 2
elif expr['type'] == 'unary':
or_reg = self.next_reg; self.next_reg += 1; gen_expr(expr['operand'], or_reg)
op_m = {'-': 'UNM', '#': 'LEN', 'not': 'NOT'}
emit(op_m.get(expr['op'], 'UNM'), target, or_reg); self.next_reg -= 1
elif expr['type'] == 'call': gen_call(expr, target)
elif expr['type'] == 'method_call': gen_method_call(expr, target)
def gen_call(node, target):
fr = self.next_reg; self.next_reg += 1
gen_expr(node['func'], fr)
for i, arg in enumerate(node['args']):
ar = self.next_reg; self.next_reg += 1; gen_expr(arg, ar)
emit("CALL", fr, len(node['args']) + 1, 2)
if target != fr: emit("MOVE", target, fr)
self.next_reg = fr
def gen_method_call(node, target):
fr = self.next_reg; self.next_reg += 1
br = self.next_reg; self.next_reg += 1
gen_expr(node['base'], br)
emit("SELF", fr, br, add_const(node['method']))
self.next_reg = fr + 2
for i, arg in enumerate(node['args']):
ar = self.next_reg; self.next_reg += 1; gen_expr(arg, ar)
emit("CALL", fr, len(node['args']) + 2, 2)
if target != fr: emit("MOVE", target, fr)
self.next_reg = fr
for node in ast:
if node['type'] == 'assign':
vr = self.next_reg; self.next_reg += 1; gen_expr(node['value'], vr)
if node.get('local'): locals_map[node['name']] = vr
elif 'target' in node:
t = node['target']
if t['type'] == 'index':
br = self.next_reg; self.next_reg += 1; gen_expr(t['base'], br)
if t['key']['type'] == 'STRING':
emit("SETTABLE", br, add_const(t['key']['value']), vr)
else:
kr = self.next_reg; self.next_reg += 1; gen_expr(t['key'], kr)
emit("SETTABLE", br, kr, vr); self.next_reg -= 1
self.next_reg -= 1
elif t['type'] == 'variable':
emit("SETGLOBAL", vr, add_const(t['name']))
else: emit("SETGLOBAL", vr, add_const(node['name']))
elif node['type'] == 'call': gen_call(node, self.next_reg)
elif node['type'] == 'method_call': gen_method_call(node, self.next_reg)
elif node['type'] == 'return':
vr = self.next_reg; self.next_reg += 1; gen_expr(node['value'], vr)
emit("RETURN", vr, 2)
self.next_reg -= 1
emit("RETURN")
return {"instructions": instructions, "constants": constants}
def obfuscate(self, code):
if not code.strip(): return ""
try:
lexer = Lexer(code)
tokens = lexer.tokenize()
parser = Parser(tokens)
ast = parser.parse()
if not ast: return ""
bytecode = self.compile_to_bytecode(ast)
return self.generate_vm_source(bytecode)
except Exception:
import traceback
return f"-- Obfuscation Error: {traceback.format_exc()}"
def obfuscate(code):
return LuauVMObfuscator().obfuscate(code)

View File

@ -1,117 +0,0 @@
import re
class Lexer:
def __init__(self, code):
self.code = code
self.tokens = []
self.pos = 0
LB, RB, DQ, SQ, BS = chr(91), chr(93), chr(34), chr(39), chr(92)
OP_LIST = r'==|~=|<=|>=|\.\.\.|\.\.|>>|<<|\+|\-|\*|/|%|\^|#|=|\<|\>|\(|\)|\{|\}|' + BS + LB + '|' + BS + RB + '|;|:|,|\.'
self.rules = [
('COMMENT', re.compile('--' + LB + LB + '.*?' + RB + RB + '|--.*', re.DOTALL)),
('STRING', re.compile(DQ + r'(?:' + BS + BS + r'.|[^' + DQ + BS + BS + r'])*' + DQ + '|' + SQ + r'(?:' + BS + BS + r'.|[^' + SQ + BS + BS + r'])*' + SQ + '|' + LB + LB + '.*?' + RB + RB, re.DOTALL)),
('NUMBER', re.compile(r'\b\d+\.?\d*(?:[eE][+-]?\d+)?\b|\b0x[0-9a-fA-F]+\b')),
('KEYWORD', re.compile(r'\b(and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b')),
('IDENT', re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')),
('OP', re.compile(OP_LIST)),
('SPACE', re.compile(r'\s+'))
]
def tokenize(self):
while self.pos < len(self.code):
match = None
for name, regex in self.rules:
match = regex.match(self.code, self.pos)
if match:
if name != 'SPACE' and name != 'COMMENT': self.tokens.append((name, match.group(0)))
self.pos = match.end(); break
if not match: self.pos += 1
return self.tokens
class Parser:
def __init__(self, tokens): self.tokens = tokens; self.pos = 0
def peek(self, offset=0):
idx = self.pos + offset
return self.tokens[idx] if idx < len(self.tokens) else (None, None)
def consume(self, t=None, v=None):
tk = self.peek()
if not tk or not tk[0]: return None
if t and tk[0] != t: return None
if v and tk[1] != v: return None
self.pos += 1; return tk
def parse(self):
nodes = []
while self.pos < len(self.tokens):
node = self.parse_statement()
if node: nodes.append(node)
else: self.pos += 1
return nodes
def parse_statement(self):
tk = self.peek()
if not tk or not tk[0]: return None
if tk[1] == 'local':
self.consume(); ident = self.consume('IDENT')
if ident:
if self.peek()[1] == '=':
self.consume(); return {'type': 'assign', 'name': ident[1], 'value': self.parse_expression(), 'local': True}
return {'type': 'assign', 'name': ident[1], 'value': {'type': 'KEYWORD', 'value': 'nil'}, 'local': True}
return None
if tk[1] == 'return':
self.consume()
return {'type': 'return', 'value': self.parse_expression()}
if tk[1] == ';':
self.consume(); return None
start = self.pos; expr = self.parse_prefix_expression()
if expr:
if self.peek()[1] == '=':
self.consume(); return {'type': 'assign', 'target': expr, 'value': self.parse_expression()}
elif expr['type'] in ['call', 'method_call']: return expr
self.pos = start; return None
def parse_prefix_expression(self):
tk = self.peek()
if not tk or tk[0] != 'IDENT': return None
expr = {'type': 'variable', 'name': self.consume()[1]}
while True:
nt = self.peek()
if nt[1] == '.':
self.consume(); m = self.consume('IDENT')
if m: expr = {'type': 'index', 'base': expr, 'key': {'type': 'STRING', 'value': '"'+m[1]+'"'}}
else: break
elif nt[1] == ':':
self.consume(); m = self.consume('IDENT')
if m:
if self.peek()[1] == '(':
self.consume(); args = []
if self.peek()[1] != ')':
args.append(self.parse_expression())
while self.peek()[1] == ',': self.consume(); args.append(self.parse_expression())
self.consume('OP', ')'); expr = {'type': 'method_call', 'base': expr, 'method': m[1], 'args': args}
else: expr = {'type': 'index', 'base': expr, 'key': {'type': 'STRING', 'value': '"'+m[1]+'"'}}
else: break
elif nt[1] == '[':
self.consume(); key = self.parse_expression(); self.consume('OP', ']'); expr = {'type': 'index', 'base': expr, 'key': key}
elif nt[1] == '(':
self.consume(); args = []
if self.peek()[1] != ')':
args.append(self.parse_expression())
while self.peek()[1] == ',': self.consume(); args.append(self.parse_expression())
self.consume('OP', ')'); expr = {'type': 'call', 'func': expr, 'args': args}
else: break
return expr
def parse_expression(self):
left = self.parse_primary_expression()
if not left: return None
while self.peek()[1] in ['+', '-', '*', '/', '..', '==', '<', '>', '<=', '>=', '~=']:
op = self.consume()[1]; right = self.parse_primary_expression()
if not right: break
left = {'type': 'binary', 'op': op, 'left': left, 'right': right}
return left
def parse_primary_expression(self):
tk = self.peek()
if not tk: return None
if tk[1] in ['-', '#', 'not']:
op = self.consume()[1]; sub = self.parse_primary_expression()
return {'type': 'unary', 'op': op, 'operand': sub} if sub else None
if tk[0] in ['STRING', 'NUMBER']: v = tk[1]; self.consume(); return {'type': tk[0], 'value': v}
if tk[1] in ['true', 'false', 'nil']: return {'type': 'KEYWORD', 'value': self.consume()[1]}
if tk[1] == '(': self.consume(); e = self.parse_expression(); self.consume('OP', ')'); return e
return self.parse_prefix_expression()

View File

@ -1,231 +1,145 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %}
{% block title %}{{ project_name }} | Strong Protection{% endblock %} {% block title %}{{ project_name }}{% endblock %}
{% block head %} {% block head %}
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style> <style>
:root { :root {
--primary-bg: #0f172a; --bg-color-start: #6a11cb;
--secondary-bg: #1e293b; --bg-color-end: #2575fc;
--accent-blue: #38bdf8; --text-color: #ffffff;
--accent-green: #22c55e; --card-bg-color: rgba(255, 255, 255, 0.01);
--text-main: #f8fafc; --card-border-color: rgba(255, 255, 255, 0.1);
--text-muted: #94a3b8; }
--border-color: #334155;
--glass-bg: rgba(30, 41, 59, 0.7); * {
box-sizing: border-box;
} }
body { body {
background-color: var(--primary-bg);
color: var(--text-main);
font-family: 'Inter', sans-serif;
margin: 0; margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh; min-height: 100vh;
background-image:
radial-gradient(circle at 10% 20%, rgba(56, 189, 248, 0.05) 0%, transparent 40%),
radial-gradient(circle at 90% 80%, rgba(34, 197, 94, 0.05) 0%, transparent 40%);
}
.navbar {
background: var(--glass-bg);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-color);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 100;
}
.logo {
font-weight: 700;
font-size: 1.25rem;
color: var(--accent-blue);
text-decoration: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
.logo span { color: var(--text-main); }
.hero {
text-align: center; text-align: center;
padding: 4rem 2rem 2rem;
}
.hero h1 {
font-size: 3rem;
margin-bottom: 1rem;
background: linear-gradient(to right, var(--accent-blue), var(--accent-green));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 800;
}
.hero p {
color: var(--text-muted);
max-width: 600px;
margin: 0 auto 2rem;
font-size: 1.1rem;
}
.editor-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem 4rem;
}
@media (max-width: 768px) {
.editor-container { grid-template-columns: 1fr; }
}
.editor-pane {
background: var(--secondary-bg);
border: 1px solid var(--border-color);
border-radius: 12px;
overflow: hidden; overflow: hidden;
display: flex; position: relative;
flex-direction: column;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
} }
.editor-header { body::before {
padding: 0.75rem 1rem; content: '';
background: rgba(0, 0, 0, 0.2); position: absolute;
border-bottom: 1px solid var(--border-color); inset: 0;
display: flex; background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
justify-content: space-between; animation: bg-pan 20s linear infinite;
align-items: center; z-index: -1;
font-size: 0.875rem;
font-weight: 600;
color: var(--text-muted);
} }
textarea { @keyframes bg-pan {
background: transparent; 0% {
border: none; background-position: 0% 0%;
color: #e2e8f0;
font-family: 'JetBrains Mono', monospace;
padding: 1rem;
resize: none;
height: 400px;
outline: none;
font-size: 0.9rem;
line-height: 1.5;
} }
.btn-obfuscate { 100% {
grid-column: span 2; background-position: 100% 100%;
background: linear-gradient(to right, var(--accent-blue), #2563eb); }
color: white; }
border: none;
padding: 1rem 2rem; main {
border-radius: 8px; padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2.5rem 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
}
h1 {
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
font-weight: 700; font-weight: 700;
margin: 0 0 1.2rem;
letter-spacing: -0.02em;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem; font-size: 1.1rem;
cursor: pointer; opacity: 0.92;
transition: all 0.2s;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-top: -1rem;
box-shadow: 0 4px 14px 0 rgba(56, 189, 248, 0.39);
} }
@media (max-width: 768px) { .btn-obfuscate { grid-column: span 1; } } .loader {
margin: 1.5rem auto;
.btn-obfuscate:hover { width: 56px;
transform: translateY(-2px); height: 56px;
box-shadow: 0 6px 20px rgba(56, 189, 248, 0.45); border: 4px solid rgba(255, 255, 255, 0.25);
filter: brightness(1.1); border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
} }
.btn-obfuscate:active { transform: translateY(0); } @keyframes spin {
to {
transform: rotate(360deg);
}
}
.copy-btn { .runtime code {
background: transparent; background: rgba(0, 0, 0, 0.25);
border: 1px solid var(--border-color); padding: 0.15rem 0.45rem;
color: var(--text-muted);
padding: 0.25rem 0.5rem;
border-radius: 4px; border-radius: 4px;
font-size: 0.75rem; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
cursor: pointer;
} }
.copy-btn:hover { color: var(--text-main); border-color: var(--text-muted); } .sr-only {
position: absolute;
.badge { width: 1px;
padding: 0.2rem 0.5rem; height: 1px;
border-radius: 4px; padding: 0;
font-size: 0.7rem; margin: -1px;
text-transform: uppercase; overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
} }
.badge-blue { background: rgba(56, 189, 248, 0.1); color: var(--accent-blue); }
.badge-green { background: rgba(34, 197, 94, 0.1); color: var(--accent-green); }
footer { footer {
position: absolute;
bottom: 1rem;
width: 100%;
text-align: center; text-align: center;
padding: 2rem; font-size: 0.85rem;
color: var(--text-muted); opacity: 0.75;
font-size: 0.875rem;
border-top: 1px solid var(--border-color);
} }
</style> </style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<nav class="navbar"> <main>
<a href="/" class="logo">VM-<span>LUAU</span></a> <div class="card">
<div> <h1>Analyzing your requirements and generating your app…</h1>
<a href="/admin/" style="color: var(--text-muted); text-decoration: none; font-size: 0.875rem;">Admin Access</a> <div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div> </div>
</nav> <p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
<section class="hero"> <p class="runtime">
<h1>Next-Gen Luau Protection</h1> Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
<p>Secure your Roblox scripts with our custom Virtual Machine obfuscation. Harder to reverse-engineer, impossible to ignore.</p> — UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
</section> </p>
<form method="POST" class="editor-container">
{% csrf_token %}
<div class="editor-pane">
<div class="editor-header">
<span>INPUT.LUAU</span>
<span class="badge badge-blue">Source</span>
</div> </div>
<textarea name="code" placeholder="-- Paste your Luau code here..." required>{{ input_code }}</textarea> </main>
</div>
<div class="editor-pane">
<div class="editor-header">
<span>PROTECTED.LUAU</span>
<button type="button" class="copy-btn" onclick="copyOutput()">Copy Code</button>
</div>
<textarea id="output-area" readonly placeholder="-- Obfuscated code will appear here...">{{ output_code }}</textarea>
</div>
<button type="submit" class="btn-obfuscate">Obfuscate Script</button>
</form>
<footer> <footer>
&copy; 2026 {{ agent_brand }} | Built with Django & VM Technology Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
</footer> </footer>
<script>
function copyOutput() {
const output = document.getElementById('output-area');
output.select();
document.execCommand('copy');
alert('Copied to clipboard!');
}
</script>
{% endblock %} {% endblock %}

View File

@ -1,37 +1,25 @@
import os import os
import platform
from django import get_version as django_version
from django.shortcuts import render from django.shortcuts import render
from django.utils import timezone from django.utils import timezone
from .models import ScriptLog
from .obfuscator import obfuscate
def home(request): def home(request):
"""Render the landing screen with the obfuscator interface.""" """Render the landing screen with loader and environment details."""
output_code = ""
input_code = ""
if request.method == "POST":
input_code = request.POST.get("code", "")
if input_code:
output_code = obfuscate(input_code)
# Save to log
ScriptLog.objects.create(
input_code=input_code,
output_code=output_code,
input_size=len(input_code),
output_size=len(output_code)
)
host_name = request.get_host().lower() host_name = request.get_host().lower()
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
now = timezone.now() now = timezone.now()
context = { context = {
"project_name": "VM-Luau Obfuscator", "project_name": "New Style",
"agent_brand": agent_brand, "agent_brand": agent_brand,
"input_code": input_code, "django_version": django_version(),
"output_code": output_code, "python_version": platform.python_version(),
"current_time": now, "current_time": now,
"project_description": os.getenv("PROJECT_DESCRIPTION", "Strong Luau Obfuscation with Custom VM Protection."), "host_name": host_name,
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
} }
return render(request, "core/index.html", context) return render(request, "core/index.html", context)

View File

@ -1,21 +0,0 @@
from core.obfuscator import obfuscate
code = """
local a = 10
local b = 20
local c = a + b
print("Sum is:", c)
"""
obfuscated = obfuscate(code)
print(obfuscated)
# Check for some patterns
if "_l1" in obfuscated or "_I0" in obfuscated:
print("SUCCESS: Variable renaming detected.")
if "bit32.bxor" in obfuscated or "+" in obfuscated or "-" in obfuscated:
# Check if it's in the VM logic, not just the original code (which might have +)
# The VM logic uses to_expr for indices and keys.
print("SUCCESS: Number expressions detected.")
if "math.pi" in obfuscated or "math.sqrt" in obfuscated:
print("SUCCESS: Opaque predicates detected.")