Where would I connect this and how, in a serverscriptservice script?
That’s easy though. You don’t even need level 7 for that, just just Cheat Engine.
Roblox detects cheat engine iirc.
Exploiters can access the Source property but the Source property does not do anything in the Roblox player, it only does anything in studio. Scripts are compiled meaning their data is a bunch of bytecode (a bunch of binary that the lua interpreter knows how to execute). Setting the script source property to ""
does absolutely nothing in an exploit because the Source property is completely ignored in that case. It doesn’t get set to anything either, it will already be ""
No, they are not similar at all, level 8 has a lot less permissions, its meant for data being replicated from the server. It’s something completely different to level 7. You can read about it here like I mentioned:
Security context | Roblox Wiki | Fandom
There are branches of CE. But even HxD will let you delete memory.
There are versions of cheat engine that are designed for Roblox.
@JarodOfOrbiter
Regardless, the script’s source is not stored in memory, scripts are compiled when they are in the Roblox player (not in studio), so, their source code won’t be anywhere. What decompilers do is take their bytecode and go from bytecode > some brand new lua code that would produce something similar.
When replicated it is just a bunch of byecode so the source is nothing, but if you set it using the exploit it will empty the contents and error. (Go into a game, and try setting the source of the localscript to “”. When disabled and enabled it will error)
PS: None of us here condone exploiting and we are not promoting the use of exploits. It is against Roblox’s TOS to exploit. Don’t do it
Correct, but the compiled code can be deleted. Roblox doesn’t make it easy though, at the very minimum they no longer just the same bytecode header as native Lua. And you can easily screw yourself over and crash.
As far as I know the Source property does nothing in the Roblox player (though that would have been wayyyy before luau that I know that from), so, if Roblox changed some code regarding that (which is likely) then I guess that could happen, so, I might just be wrong here.
Exploiters can also just set the script’s .Disabled
property to true
and the script and any threads it spawned will be killed.
@JarodOfOrbiter Yeah, that’s absolutely true, you can modify script bytecode in memory though I would think that that would screw up the script state if you tried it which is probably a good reason why exploits don’t attempt to do this.
(The reason the length has to remain fixed is pretty common, usually stuff in memory has a fixed length, and that length is generally indicated by something at the beginning of the value, somewhere in the header data of the object usually, you could likely increase the length that Roblox is looking for, but then you’d extend into other memory in the program after the existing bytecode)
The reason exploiters don’t just disable it and change the source is that if there is a server script in the player’s character then the disabled property change will be replicated to the server (which is what exploiters don’t want. They can’t do anything about it because a server script is listening)
The .Disabled
property does not replicate for LocalScripts
under the character. You can test this easily by opening up a baseplate and disabling the Animate
script in the client view, then switching to the server view.
Additionally, Synapse has the ability to prevent property changes from replicating to the server iirc via a special set method.
Client:
Server:
If you have a look at a game such as mortem metallum, disabling a script will kick the exploiter. This is because there is a server script in the player’s character
Again, I just demonstrated, the .Disabled
property does not replicate to the server. The reason is likely because they watch for changes on the client which is trivial to stop with an exploit and can be done in at least three different unique ways that I know of.
One of them is via the special function I mentioned which doesn’t fire changes. One of them is by disconnecting the changed event directly via the various APIs Synapse has to do that. One of them is by targeting the specific callback and breaking it. If the callback checks the Disabled property by getting it, a fourth way would be to spoof the property.
(Also, relying on stuff replicating to the server also isn’t secure, because again, exploits generally have control over that stuff)
Also, another way a script can be effectively disabled is by clearing its environment, in which case all functions with its environment will start erroring and such.
You would place this in the script where you want to ragdoll the player. Then, when you want to ragdoll them you can call the function like this:
In a server script you can do something like this:
local Players = game:GetService("Players")
-- Ragdoll Function
local function Ragdoll(character, killCharacter)
-- Variables
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local hrp = character:FindFirstChild("HumanoidRootPart")
-- Kill
humanoid:SetAttribute("RequiresNeck", humanoid.RequiresNeck)
humanoid.RequiresNeck = killCharacter or false
-- Ragdoll Rigging
for _,descendant in ipairs(character:GetDescendants()) do
if descendant:IsA("Motor6D") and (descendant.Part0 ~= hrp) then
-- Attachments
if not descendant.Parent:FindFirstChild(descendant.Name .. "RigAttachment") then
local Attachment = Instance.new("Attachment")
Attachment.Name = (descendant.Name .. "RigAttachment")
Attachment.CFrame = descendant.C1
Attachment.Parent = descendant.Part1
Attachment = Attachment:Clone()
Attachment.CFrame = descendant.C0
Attachment.Parent = descendant.Part0
end
-- Socket
local Socket = Instance.new("BallSocketConstraint")
Socket.Attachment0 = descendant.Part0:FindFirstChild(descendant.Name .. "RigAttachment")
Socket.Attachment1 = descendant.Part1:FindFirstChild(descendant.Name .. "RigAttachment")
Socket.LimitsEnabled = true
Socket.TwistLimitsEnabled = true
Socket.Name = (descendant.Name .. "Joint")
Socket.Parent = descendant.Parent
-- Collision
local collision = Instance.new("NoCollisionConstraint")
collision.Part0 = descendant.Part0
collision.Part1 = descendant.Part1
collision.Parent = descendant.Parent
-- Motor6D
descendant.Enabled = false
end
end
hrp.CanCollide = false
hrp:SetNetworkOwner(nil) -- sets the network owner to the server
end
-- Unragdoll Function
local function Unragdoll(character)
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local hrp = character:FindFirstChild("HumanoidRootPart")
for _,descendant in ipairs(character:GetDescendants()) do
if descendant:IsA("Motor6D") then
descendant.Enabled = true
elseif descendant:IsA("BallSocketConstraint") or descendant:IsA("NoCollisionConstraint") then
descendant:Destroy()
end
end
humanoid.RequiresNeck = humanoid:GetAttribute("RequiresNeck")
hrp.CanCollide = true
hrp:SetNetworkOwner(Players:GetPlayerFromCharacter(character))
end
-- To ragdoll the character:
Ragdoll(player.Character)
-- To unragdoll the character:
Unragdoll(player.Character)
-- To kill the player with the ragdoll death effect:
Ragdoll(player.Character, true)
The word “LEVEL 8 ACCESS” is simply a tactic used by exploiters to get more people to buy / download the exploit. Although I guess it has some meaning to it here.
May I ask where is player defined?
It isn’t. This is merely an example for you to use. If you want to use it on a specific player then you will have to define that player yourself.
Would this be how I would do it
Players.Character:WaitForChild("StatusEffects").ChildAdded:Connect(function(child)
if child.Name == "Ragdoll" and Players.Character:WaitForChild("StatusEffects"):FindFirstChild("Ragdoll") then
Ragdoll(Players.Character)
end
end)
-- To unragdoll the character
Players.Character:WaitForChild("StatusEffects").ChildRemoved:Connect(function(child)
if child.Name == "Ragdoll" and not Players.Character:WaitForChild("StatusEffects"):FindFirstChild("Ragdoll") then
Unragdoll(Players.Character)
end
end)
Players.Character.Humanoid:Connect(function()
Ragdoll(Players.Character, true)
end)
No. You do not seem to understand the Roblox API that well. I would try learning more before trying to make this. You can try learning more with the Roblox Onboarding experience at Learn Roblox.
Also, your script should instead look like this:
local function SetupCharacter(character)
local humanoid = character:FindFirstChildOfClass("Humanoid")
local statusEffects = character:FindFirstChild("StatusEffects") or Instance.new("Folder") -- detects or creates a StatusEffects folder
statusEffects.Name = "StatusEffects"
statusEffects.Parent = character
-- To Ragdoll the character
statusEffects.ChildAdded:Connect(function(child)
if child.Name == "Ragdoll" then
Ragdoll(character)
end
end)
-- To Unragdoll the character
statusEffects.ChildRemoved:Connect(function(child)
if child.Name == "Ragdoll" and not statusEffects:FindFirstChild("Ragdoll") then
Unragdoll(character)
end
end)
-- When the player dies
humanoid.Died:Connect(function()
Ragdoll(character, true)
end)
end)
Players.PlayerAdded:Connect(function(player)
SetupCharacter(player.Character or player.CharacterAdded:Wait()) -- Sets up the character
-- When the player respawns
player.CharacterAdded(function(char)
SetupCharacter(char) -- Sets up the character
end)
end)
However, like @Hexcede said you can use Instance Attributes | Roblox Creator Documentation instead of Instancing to detect the characters state. These are faster than instancing as well.
I realized my mistake around half an hour after making that post. I changed up the ragdoll a bit so the player body parts can collide with the ground, and I have connected it to CharacterAdded. I appreciate your help, though!