<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Kers0ne Source Stealer — Env Logger</title>
    <meta name="description" content="Source Hub Env Logger — paste your loadstring and instantly generate a logged Lua script." />
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <main class="relative min-h-screen overflow-hidden">
      <div class="absolute inset-0 grid-bg opacity-60 pointer-events-none"></div>
      <div class="absolute -top-40 left-1/2 -translate-x-1/2 h-[500px] w-[500px] rounded-full bg-brand/30 blur-[140px] pointer-events-none"></div>
      <div class="relative mx-auto flex min-h-screen max-w-4xl flex-col px-6 py-10">

        <!-- Header -->
        <header class="flex items-center justify-between">
          <div class="flex items-center gap-3">
            <div class="flex h-10 w-10 items-center justify-center rounded-xl bg-brand/20 ring-1 ring-brand/40 glow-border">
              <span class="h-2.5 w-2.5 rounded-full bg-brand-glow" style="box-shadow: 0 0 12px var(--brand-glow);"></span>
            </div>
            <div>
              <h1 class="text-lg font-semibold tracking-tight">Kers0ne Source Stealer</h1>
              <p class="text-xs text-muted-foreground">Env Logger</p>
            </div>
          </div>

        </header>

        <!-- Hero -->
        <section class="mt-16 text-center">
          <h2 class="text-4xl sm:text-5xl font-bold tracking-tight glow-text">Kers0ne <span class="text-brand-glow">Source Stealer</span></h2>
          <p class="mt-4 text-sm sm:text-base max-w-xl mx-auto" style="color: rgba(255,233,236,0.7);">
            Paste your loadstring below — we'll wrap it with the environment logger so API calls are captured to
            <code class="text-brand-glow">logged.txt</code>.
          </p>
        </section>

        <!-- Form -->
        <section class="mt-10">
          <form id="form" class="card-surface rounded-2xl p-6 sm:p-8 border border-brand/20">
            <label for="loadstring" class="block text-sm font-medium mb-2">Loadstring</label>
            <textarea id="loadstring" rows="5" placeholder='loadstring(game:HttpGet("https://example.com/script.lua"))()' class="w-full resize-none rounded-xl border border-brand/20 px-4 py-3 font-mono text-sm" style="background: rgba(10,2,4,0.6); color: var(--foreground);"></textarea>
            <div class="mt-4 flex justify-end">
              <button type="submit" class="inline-flex items-center gap-2 rounded-xl bg-brand px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-brand-glow" style="box-shadow: 0 0 25px var(--brand-glow);">Submit</button>
            </div>
          </form>
        </section>

        <!-- How to use -->
        <section class="mt-8 card-surface rounded-2xl border border-brand/20 p-6 sm:p-8">
          <div class="flex items-center gap-2 mb-5">
            <span class="h-2 w-2 rounded-full bg-brand-glow" style="box-shadow: 0 0 8px var(--brand-glow);"></span>
            <h3 class="text-base font-semibold tracking-tight">How to use</h3>
          </div>
          <ol class="space-y-3 text-sm" style="color: rgba(255,233,236,0.8);">
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">1</span>
              <span class="pt-0.5">Execute the generated loadstring in your executor.</span>
            </li>
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">2</span>
              <span class="pt-0.5">Let it run for 2–10 minutes so the logger can capture API calls.</span>
            </li>
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">3</span>
              <span class="pt-0.5">Open your executor's workspace folder.</span>
            </li>
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">4</span>
              <span class="pt-0.5">Locate the file named <code class="text-brand-glow">logged.txt</code>.</span>
            </li>
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">5</span>
              <span class="pt-0.5">Copy the entire contents of <code class="text-brand-glow">logged.txt</code>.</span>
            </li>
            <li class="flex gap-3">
              <span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-brand/20 ring-1 ring-brand/40 text-xs font-semibold text-brand-glow">6</span>
              <span class="pt-0.5">Paste it into an AI model (ChatGPT, Claude, Gemini, Grok, etc.) and ask it to reconstruct the original script from the logged environment calls.</span>
            </li>
          </ol>
          <div class="mt-5 rounded-xl border border-brand/20 bg-brand/5 p-4 text-xs" style="color: rgba(255,233,236,0.7);">
            <span class="font-semibold text-brand-glow">Tip:</span>
            The longer you let the script run, the more complete the log will be — giving the AI more context to accurately reconstruct the source.
          </div>
        </section>

        <!-- Output -->
        <section id="outputSection" class="mt-8 card-surface rounded-2xl border border-brand/20 overflow-hidden hidden">
          <div class="flex items-center justify-between gap-3 border-b border-brand/15 px-5 py-3">
            <div class="flex items-center gap-2">
              <span class="h-2 w-2 rounded-full bg-brand-glow" style="box-shadow: 0 0 8px var(--brand-glow);"></span>
              <span class="text-sm font-medium">logger.lua</span>
            </div>
            <div class="flex items-center gap-2">
              <button id="copyBtn" class="inline-flex items-center gap-1.5 rounded-lg border border-brand/30 bg-brand/10 px-3 py-1.5 text-xs font-medium hover:bg-brand/20 transition">Copy</button>
              <button id="downloadBtn" class="inline-flex items-center gap-1.5 rounded-lg bg-brand px-3 py-1.5 text-xs font-semibold text-white hover:bg-brand-glow transition" style="box-shadow: 0 0 15px var(--brand-glow);">Download</button>
            </div>
          </div>
          <pre id="output" class="max-h-[420px] overflow-auto p-5 text-xs leading-relaxed font-mono" style="color: rgba(255,233,236,0.85); background: rgba(10,2,4,0.4);"></pre>
        </section>

        <!-- Footer -->
        <footer class="mt-auto pt-12 text-center text-xs" style="color: rgba(255,233,236,0.4);">
          © <span id="year"></span> Kers0ne Source Stealer · Env Logger
        </footer>

      </div>
    </main>

    <!-- Lua template stored as plain text so no escaping issues -->
    <script id="lua-template" type="text/plain">print("[made by Kers0ne]")
writefile('logged.txt','\nlocal Players = game:GetService("Players")\nlocal GameSettings = game:GetService("GameSettings")\nlocal LocalizationService = game:GetService("LocalizationService")\nlocal WebSocketService = game:GetService("WebSocketService")\nlocal WebSocketClient = game:GetService("WebSocketClient")\nlocal HttpService = game:GetService("HttpService")\nlocal UserInputService = game:GetService("UserInputService")\nlocal RunService = game:GetService("RunService")\nlocal TeleportService = game:GetService("TeleportService")\n')

local function isuilib()
 local a = debug.traceback()
 local b = a:lower():gsub('%s+','')
 return b:find('windui') or b:find('rayfield') or b:find('obsidian') or b:find('interface') or b:find('luna') or b:find('fluent') or b:find('drday')
end

local function formatlog(text)
 if type(text) ~= 'string' then
  error('Bad agrument #1 to formatlog "string" expected, got: '..type(text))
  return
 end
 return text:gsub('table: ',''):gsub('function: ',''):gsub('Ugc','game'):gsub('\n',''):gsub('%s%s+',';'):gsub('""',''):gsub('Data Ping', 'DataPing'):gsub('Workspace','workspace'):gsub('game.Players','Players'):gsub('Teleport Service','TeleportService'):gsub('Run Service','RunService'):gsub('HttpGetAsync','HttpGet'):gsub('"',"'")
end

local function tblformat(tbl, depth)
 local depth = depth or 0
 local res = ''
 local first = true
 if depth > 5 then return 'too big to display' end
 if type(tbl) ~= 'table' then
  res = '"'..tostring(tbl)..'"'
  if res == '"nil"' then
   res = ''
  end
  return res
 end
 for i, v in pairs(tbl) do
  if not first then res = res .. ', ' end
  first = false
  if type(i) == 'string' then
   res = res .. i .. ' = '
  end
  if type(i) == 'table' then
   res = res .. tblformat(v, depth + 1)
  else
   res = res .. tostring(v)
  end
 end
 return res .. ''
end

local Track = {}
local kirked = {}
local function kirk(fem, boy)
 return fem .. ';' .. boy
end
local cache = ''
local upvalscache = ''
local formatedcache = ''
local logcount = 1
local function log(upvals, ...)
 upvals = upvals or 'nil'
 upvals = formatlog(tostring(upvals))
 if #upvals > 100 then
  local holder = #upvals
  upvals = upvals:sub(1,50) .. '... (' .. holder .. ' character remaining)'
 end
 local args = ...
 local formated = formatlog(tostring(args))
 local logged = formated
 if logged == cache then
  return
 end
 if formated == formatedcache and upvals == upvalscache then
  return
 end
 local charliekirk = kirk(logged, upvals)
 if kirked[charliekirk] then
  return
 end
 if upvals:find('Signal') then
  logged = formated .. ':Connect(function(...)end)'
 end
 if logged:find('game:HttpGet') then
  logged = 'loadstring('..formated..')()'
 end
 if logcount > 36000 then
  game:shutdown()
  return
 end
 if logged:find('IsA') then
  return
 end
 logcount += 1
 cache = logged
 upvalscache = upvals
 formatedcache = formated
 kirked[charliekirk] = true
 appendfile('logged.txt',logged..'\n')
end

isfunctionhooked = nil
restorefunction = nil

function GlobalScan()
 for i, v in pairs(_G) do
  log('_G Scan', '_G.'..i..' = '..tblformat(v))
 end
end

function GenvScan()
 for i, v in pairs(getgenv()) do
  log('getgenv Scan', 'getgenv().'..i..' = '..tblformat(v))
 end
end

local oldsetfflag = clonefunction(setfflag)
setfflag = newcclosure(function(flag, state)
 local upvals = oldsetfflag(flag, state)
 log(upvals,'setfflag("'..flag..'", '..'"'..state..'")')
 return upvals
end)

if http and http.request then
 setreadonly(http, false)
 http.request = nil
 setreadonly(http, false)
end
local oldrequest = request
request = newcclosure(function(data)
 local upvals = oldrequest(data)
 local meow = data.Body
 if type(data.Body) == 'string' then
  if data.Body:sub(1,1) == '{' and data.Body:sub(-1) == '}' then
   meow = data.Body
  else
   meow = '"'..data.Body..'"'
  end
 elseif type(data.Body) == 'table' then
  meow = 'game:GetService("HttpService"):JSONEncode('..tblformat(data.Body)..')'
 else
  meow = tostring(data.Body)
 end
 local meowmeow = '{'
 local first = true
 if data.Headers then
  for i, v in pairs(data.Headers) do
   if not first then meowmeow = meowmeow .. ', ' end
   first = false
   meowmeow = meowmeow .. '["'..i..'"] = "'..v..'"'
  end
 end
 meowmeow = meowmeow .. '}'
 log(upvals, 'request({\n Url = "'..data.Url..'",\n Method = "'..data.Method..'",\n Body = '..meow..',\n Headers = '..meowmeow..'\n})')
 return upvals
end)

local oldl = clonefunction(loadstring)
hookfunction(loadstring, function(str)
 if true then
  writefile(math.random(1,999)..'.txt', str)
  warn'xd'
 end
 return oldl(str)
end)

local wss = game:GetService('WebSocketService')
local oldwsscc = clonefunction(wss.CreateClient)
hookfunction(game.WebSocketService.CreateClient, function(_, url)
 warn('WSS')
 if not url:lower():find'luarmor' then
  log('idk i found luarmor use this xd', 'WebsocketService:CreateClient("WebSocketService","'..url..'")')
 end
 return oldwsscc(_, url)
end)

Instance = Instance or {}
local oldinstancenew = clonefunction(Instance.new)
setreadonly(Instance, false)
Instance.new = newcclosure(function(name, parent)
 if checkcaller() and not isuilib() then
  local upvals = oldinstancenew(name, parent)
  local a = debug.getinfo(2,'Sl')
  if a and a.source:find('@') then
   log(upvals, 'local a = Instance.new("'..name..'")')
  else
   local b = tostring(name)
   Track[upvals] = b
   log(upvals, 'local '..b..' = Instance.new("'..name..'")')
  end
  return upvals
 end
 return oldinstancenew(name, parent)
end)

local mt = getrawmetatable(game)
local oldindex = clonefunction(mt.__index)
local oldnamecall = clonefunction(mt.__namecall)
local oldnewindex = clonefunction(mt.__newindex)
hookmetamethod(game,'__index',newcclosure(function(self, v, ...)
 if checkcaller() and not isuilib() then
  local upvals = oldindex(self, v, ...)
  local formated = tblformat(...)
  if v == 'Character' then
   log('LocalPlayer.Character', self:GetFullName()..'.'..v)
   return upvals
  end
  if v == 'GetService' then return upvals end
  if v == 'HttpGet' then return upvals end
  if v == 'JSONDecode' then return upvals end
  if v == 'CoreGui' then return upvals end
  if v == 'JSONEncode' then return upvals end
  if v == 'JobId' then log('game.JobId', self:GetFullName()..'.'..v) return upvals end
  if v == 'PlaceId' then log('game.PlaceId', self:GetFullName()..'.'..v) return upvals end
  if v == 'WaitForChild' then return upvals end
  if v == 'FindFirstChild' then return upvals end
  if v == 'DescendantRemoving' then return upvals end
  if tostring(upvals):find('function:') then
   log(upvals, self:GetFullName()..':'..v..'('..formated..')')
   return upvals
  end
  log(upvals, self:GetFullName()..'.'..v)
  return upvals
 end
 return oldindex(self, v, ...)
end))
hookmetamethod(game, '__namecall', newcclosure(function(self, ...)
 if checkcaller() and not isuilib() and getnamecallmethod() ~= 'GetFullName' then
  local instance = tostring(self)
  if type(instance) == 'Instance' then
   instance = oldnamecall(instance, 'GetFullName')
  end
  local upvals = oldnamecall(self, ...)
  local args = {...}
  local formated = tblformat(args)
  if getnamecallmethod() == 'GetService' then
   log(upvals, 'game:GetService("'..args[1]..'")')
   return upvals
  end
  if getnamecallmethod() == 'WaitForChild' then
   log(upvals, instance..':WaitForChild("'..args[1]..'")')
   return upvals
  end
  if getnamecallmethod() == 'FindFirstChild' then
   log(upvals, instance..':FindFirstChild("'..args[1]..'")')
   return upvals
  end
  if getnamecallmethod() == 'HttpGet' then
   log(upvals, 'game:HttpGet("'..args[1]..'", true)')
   return upvals
  end
  log(upvals, instance..':'..getnamecallmethod()..'("'..formated..'")')
  return upvals
 end
 return oldnamecall(self, ...)
end))
hookmetamethod(game, '__newindex', newcclosure(function(self, i, v)
 if checkcaller() and not isuilib() then
  local upvals = oldnewindex(self, i, v)
  local a = Track[self]
  local b = tostring(i)
  local c = tostring(typeof(v)) or 'Unknown'
  local d = tostring(v)
  if a then
   if b then
    if c == 'Instance' then
     log(upvals, a..'.'..b..' = '..v:GetFullName())
    elseif c == 'number' then
     log(upvals, a..'.'..b..' = '..d)
    elseif c == 'string' then
     log(upvals, a..'.'..b..' = "'..d..'"')
    elseif c == 'boolean' then
     log(upvals, a..'.'..b..' = '..d)
    elseif c == 'Color3' then
     log(upvals, a..'.'..b..' = Color3.new('..d..')')
    elseif c == 'CFrame' then
     log(upvals, a..'.'..b..' = CFrame.new('..d..')')
    elseif c == 'Vector3' then
     log(upvals, a..'.'..b..' = Vector3.new('..d..')')
    elseif c == 'UDim2' then
     log(upvals, a..'.'..b..' = UDim2.new('..d:gsub('{',''):gsub('}','')..')')
    elseif c == 'Vector2' then
     log(upvals, a..'.'..b..' = Vector2.new('..d..')')
    elseif c == 'UDim' then
     log(upvals, a..'.'..b..' = UDim.new('..d..')')
    elseif c == 'EnumItem' then
     log(upvals, a..'.'..b..' = '..d)
    elseif c == 'ColorSequence' then
     log(upvals, a..'.'..b..' = ColorSequence.new('..d:gsub('%s+',',')..')')
    else
     log(upvals, a..'.'..b..' = '..'['..c..'] '..d)
    end
   end
  else
   if b then
    if c == 'Instance' then
     log(upvals, 'a.'..b..' = '..v:GetFullName())
    elseif c == 'number' then
     log(upvals, 'a.'..b..' = '..d)
    elseif c == 'string' then
     log(upvals, 'a.'..b..' = "'..d..'"')
    elseif c == 'boolean' then
     log(upvals, 'a.'..b..' = '..d)
    elseif c == 'Color3' then
     log(upvals, 'a.'..b..' = Color3.new('..d..')')
    elseif c == 'CFrame' then
     log(upvals, 'a.'..b..' = CFrame.new('..d..')')
    elseif c == 'Vector3' then
     log(upvals, 'a.'..b..' = Vector3.new('..d..')')
    elseif c == 'UDim2' then
     log(upvals, 'a.'..b..' = UDim2.new('..d:gsub('{',''):gsub('}','')..')')
    elseif c == 'Vector2' then
     log(upvals, 'a.'..b..' = Vector2.new('..d..')')
    elseif c == 'UDim' then
     log(upvals, 'a.'..b..' = UDim.new('..d..')')
    elseif c == 'EnumItem' then
     log(upvals, 'a.'..b..' = '..d)
    elseif c == 'ColorSequence' then
     log(upvals, 'a.'..b..' = ColorSequence.new('..d:gsub('%s+',',')..')')
    else
     log(upvals, 'a.'..b..' = '..'['..c..'] '..d)
    end
   end
  end
  return upvals
 end
 return oldnewindex(self, i, v)
end))

game.DescendantRemoving:Connect(function(a)
 Track[a] = nil
end)

local oldprint = print
print = newcclosure(function(...)
 if checkcaller() and not isuilib() then
  local args = {...}
  local formated = {}
  for i = 1, select('#', ...) do
   local v = args[i]
   if type(v) == 'table' then
    formated[i] = tblformat(v)
   else
    formated[i] = tostring(v)
   end
  end
  local upvals = oldprint(...)
  log(upvals, 'print("'.. table.concat(formated,'\t') ..'")')
  return upvals
 end
 return oldprint(...)
end)

print("[Logger] Executing user loadstring...")
print("[Logger] All API calls will be logged to logged.txt")
-- Inject user code below
PUT_THE_LOADSTRING_HERE</script>

    <script type="module" src="./app.js"></script>
  </body>
</html>