This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Espen's profile picture

Stop Disk Booting

Started by Espen, 16 February 2012 - 02:54 PM
Espen #1
Posted 16 February 2012 - 03:54 PM
I hope I'm not opening a can of worms here, but in the quest for knowledge, here goes.
Yes, you can prevent your CC computers to boot from disks.
But you have to change code within the ROM folder, i.e. you can only change it from outside of Minecraft!
If you're picky about it being ROM (you know, read only and all), then you could look at it like a computer company just producing another series of computers, with a new ROM. ;)/>/>

How do I disable booting from disks?
SpoilerGo into .minecraft\mods\ComputerCraft\lua\rom\programs\ and open the file "shell".
There search for the following code block:

	-- Then run the user created startup, from the disks or the root
	local sUserStartup = shell.resolveProgram( "/startup" )
	for n,sSide in pairs( redstone.getSides() ) do
		if disk.isPresent( sSide ) and disk.hasData( sSide ) then
			local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
			if sDiskStartup then
				sUserStartup = sDiskStartup
				break
			end
		end
	end
Comment out everything starting from the "for" statement, so that it looks something like this ( I used the multinline comments –[[ and –]] ):

	-- Then run the user created startup, from the disks or the root
	local sUserStartup = shell.resolveProgram( "/startup" )
	--[[
	for n,sSide in pairs( redstone.getSides() ) do
		if disk.isPresent( sSide ) and disk.hasData( sSide ) then
			local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
			if sDiskStartup then
				sUserStartup = sDiskStartup
				break
			end
		end
	end
	--]]

Can I limit booting from disk to specific computers only?
SpoilerYes, that's possible as well. Every computer who starts up is booting from the same base rom, so you only have to access the computer's ID from the shell program via os.computerID().
For example, to allow only the computer with ID# 3 to boot from disks, you could change the code-block from before to this:

	-- Then run the user created startup, from the disks or the root
	local sUserStartup = shell.resolveProgram( "/startup" )
	if os.computerID() == 3 then
		for n,sSide in pairs( redstone.getSides() ) do
		   if disk.isPresent( sSide ) and disk.hasData( sSide ) then
			   local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
			   if sDiskStartup then
				   sUserStartup = sDiskStartup
				   break
			   end
		   end
	   end
	end
Notice how I only added a simple "if os.computerID() == 3 then" and it's respective "end" to the code.

You could just as easily allow a certain range of computerID's or even define an arbitrary list in a table and run through that.
And as I'm sure you saw from the code already, you could also change the name of the startup files on disks (or computers).
For example, if you didn't outright wanted to disable the possibility of booting from disks altogether, but still wanted to limit it, you could rename the "startup" for the disks, to something else that nobody but your "Maintenance-Team" on your server knows about.
It'd then act as some kind of password. But of course only as long as nobody finds out about it by finding a disk with a weird file name on it. ;)/>/>
So this way it isn't secure per se (security through obscurity never is), but it prevents people booting from disks, who only know about the default "startup" file for disks.

But why stop here?
You could just as well insert code that forces users to enter a password if they want to boot from disks.


It's limited pretty much by your own ideas and programming skills.
But please don't go wild and publish dozens of new hardened, secure "OS"s.
Let people do that by themselves and learn something in the process.

(Not that these would be OSs to begin with. If anything you've created a modified shell.)

K, hope this was interesting enough for some, take care! :D/>/>
Advert #2
Posted 16 February 2012 - 04:11 PM
The only problem with this is, that it requires you to edit /rom/, and you won't be able to do that on smp without making others mad (or at all, if you don't have access to the server ;)/>/>). :D/>/>

How about some functions:
shell.setAllowDiskBoot(bAllow)
shell.setDiskBootHandler(sFile)
-- + get variants.
For setDiskBootHandler, it would basically run a script with args:

local arg = {...}
if *checks disk for CRC/secret file/whatever method you wish* then
return true -- allow disk
end
return false -- disallow disk

If anyone wants this for their shell; I'd be happy to cook it up.

Edit: Whoops, I mean shell. Not bios. That's not how computercraft computers work!
Espen #3
Posted 16 February 2012 - 04:31 PM
The only problem with this is, that it requires you to edit /rom/, and you won't be able to do that on smp without making others mad (or at all, if you don't have access to the server ;)/>/>). :D/>/>
That is true, and also the reason why this kind of boot protection is relatively safe, because you can't edit the ROM files if you don't have direct access to that folder.^^
Although I'm sure there's still a way around that by rewriting some globals at runtime? Haven't looked very deep into that one yet, as that's another black hole of knowledge-zest I can't afford to fall into right now. But where there is a will, there's a way, right?
Well, at least it keeps out noobs with ill intentions. :D/>/>
EDIT:
Now that I think about it: If you protect your shell like this and then make sure that neither your startup, nor your running programs can be terminated, then there's not really any way for someone ingame to access your computer's shell. That means it should be pretty impossible from then on to hijack someone else's computer, because no matter what program you try to boot from a disk, it won't be allowed if you don't know the method to boot from disk (like e.g. the password or sth.).
Well, except if your computer listens for inputs and writes changes to its startup file in accordance with the inputs. Then you can try some side-channel attacks.
But as long as the programs run in kiosk mode without writing to the startup file on input changes in some form, it should be protected.

This makes writing "trojan horses" a lot more interesting, since this looks to be the only way that your hijack-program can get on someone else's computer:
By having HIM/HER start it on their computer by themselves, because they think it's some awesome game.

So always check the source before you start someone else's program, hehe. ;)/>/>
Edited on 16 February 2012 - 10:22 PM
Advert #4
Posted 16 February 2012 - 05:07 PM
I made it with a password; this is really simple:
Replace from the os.version() call down to the end of the startup with this (not past the comment '– Run any programs …':


print( os.version() )
function shell.setDiskBootPassword(sPassword)
if type(sPassword) ~= "string" then
error("shell.setDiskBootPassword: Expected string, got " .. type(sPassword), 2)
end
local hShellFile = io.open("/shell.cfg", "w")
hShellFile:write(sPassword)
hShellFile:close()
end
local sDiskPass = ""
if fs.exists("/shell.cfg") then -- We have a password!
local hShellFile = fs.open("/shell.cfg", "r")
sDiskPass = hShellFile:readLine()
hShellFile:close()
end

-- If this is the toplevel shell, run the startup programs
if parentShell == nil then
local function diskPasswordPromt()
if sDiskPass == "" then
return true
end
print("This computer requires a password to boot from disk.")
term.write("Input Password: ")
local pass = read("*")
if pass == sDiskPass then
return true
end
print("nInvalid password.")
return false
end
-- Run the startup from the ROM first
local sRomStartup = shell.resolveProgram( "/rom/startup" )
if sRomStartup then
shell.run( sRomStartup )
end

-- Then run the user created startup, from the disks or the root
local sUserStartup = shell.resolveProgram( "/startup" )
for n,sSide in pairs( redstone.getSides() ) do
if disk.isPresent( sSide ) and disk.hasData( sSide ) then
local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
if sDiskStartup then
if diskPasswordPromt() then
sUserStartup = sDiskStartup
end
break
end
end
end

if sUserStartup then
shell.run( sUserStartup )
end
end

NOTE: This will use a file called shell.cfg in your root directory (per computer)

If this file is modified, the shell password will be; in addition, if it is removed, there will be no password. This does not force a password unless the user tries to boot from a disk!

Function added: shell.setDiskBootPassword(sPassword)
Edited on 16 February 2012 - 04:07 PM
Espen #5
Posted 16 February 2012 - 05:29 PM
Nice contribution Advert.
I like the idea that this supports users being able to save their own individual terminals from rogue disk booting, without needing any further assistance by an admin.
*thumbs up*
arongy #6
Posted 17 February 2012 - 07:48 PM
Good idea guys, I was woundering about this lately.
sabian8 #7
Posted 01 April 2012 - 09:47 AM
Spoiler
I made it with a password; this is really simple:
Replace from the os.version() call down to the end of the startup with this (not past the comment '– Run any programs …':


print( os.version() )
function shell.setDiskBootPassword(sPassword)
if type(sPassword) ~= "string" then
error("shell.setDiskBootPassword: Expected string, got " .. type(sPassword), 2)
end
local hShellFile = io.open("/shell.cfg", "w")
hShellFile:write(sPassword)
hShellFile:close()
end
local sDiskPass = ""
if fs.exists("/shell.cfg") then -- We have a password!
local hShellFile = fs.open("/shell.cfg", "r")
sDiskPass = hShellFile:readLine()
hShellFile:close()
end

-- If this is the toplevel shell, run the startup programs
if parentShell == nil then
local function diskPasswordPromt()
if sDiskPass == "" then
return true
end
print("This computer requires a password to boot from disk.")
term.write("Input Password: ")
local pass = read("*")
if pass == sDiskPass then
return true
end
print("nInvalid password.")
return false
end
-- Run the startup from the ROM first
local sRomStartup = shell.resolveProgram( "/rom/startup" )
if sRomStartup then
shell.run( sRomStartup )
end

-- Then run the user created startup, from the disks or the root
local sUserStartup = shell.resolveProgram( "/startup" )
for n,sSide in pairs( redstone.getSides() ) do
if disk.isPresent( sSide ) and disk.hasData( sSide ) then
local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
if sDiskStartup then
if diskPasswordPromt() then
sUserStartup = sDiskStartup
end
break
end
end
end

if sUserStartup then
shell.run( sUserStartup )
end
end

NOTE: This will use a file called shell.cfg in your root directory (per computer)

If this file is modified, the shell password will be; in addition, if it is removed, there will be no password. This does not force a password unless the user tries to boot from a disk!

Function added: shell.setDiskBootPassword(sPassword)

This is great thanks!
Zalerinian #8
Posted 03 May 2012 - 12:07 AM
SpoilerI made it with a password; this is really simple:
Replace from the os.version() call down to the end of the startup with this (not past the comment '– Run any programs …':


print( os.version() )
function shell.setDiskBootPassword(sPassword)
if type(sPassword) ~= "string" then
error("shell.setDiskBootPassword: Expected string, got " .. type(sPassword), 2)
end
local hShellFile = io.open("/shell.cfg", "w")
hShellFile:write(sPassword)
hShellFile:close()
end
local sDiskPass = ""
if fs.exists("/shell.cfg") then -- We have a password!
local hShellFile = fs.open("/shell.cfg", "r")
sDiskPass = hShellFile:readLine()
hShellFile:close()
end

-- If this is the toplevel shell, run the startup programs
if parentShell == nil then
local function diskPasswordPromt()
if sDiskPass == "" then
return true
end
print("This computer requires a password to boot from disk.")
term.write("Input Password: ")
local pass = read("*")
if pass == sDiskPass then
return true
end
print("nInvalid password.")
return false
end
-- Run the startup from the ROM first
local sRomStartup = shell.resolveProgram( "/rom/startup" )
if sRomStartup then
shell.run( sRomStartup )
end

-- Then run the user created startup, from the disks or the root
local sUserStartup = shell.resolveProgram( "/startup" )
for n,sSide in pairs( redstone.getSides() ) do
if disk.isPresent( sSide ) and disk.hasData( sSide ) then
local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), "startup") )
if sDiskStartup then
if diskPasswordPromt() then
sUserStartup = sDiskStartup
end
break
end
end
end

if sUserStartup then
shell.run( sUserStartup )
end
end

NOTE: This will use a file called shell.cfg in your root directory (per computer)

If this file is modified, the shell password will be; in addition, if it is removed, there will be no password. This does not force a password unless the user tries to boot from a disk!

Function added: shell.setDiskBootPassword(sPassword)

I'm obviously pretty bad at this if i did it wrong the first time… so i'm very interested in getting this to work, so how would i do that?
Rwkeith #9
Posted 06 May 2012 - 04:01 AM
Edit: I wasn't aware that Ctrl+R wasn't blockable 0.o
Zalerinian #10
Posted 06 May 2012 - 05:59 AM
I actually found out how to do this. Its REALLY a lot simpler than all of this, although it needs to be done on every separate computer.

In the computer startup file, put the following code:


shell.runDiskBootPassword("the pass you want here")

This will enforce the computer to require a password on the computer before the disk may be run. For the code to work, you must put it in the startup file and then reboot the computer. It will then ask for the password when a disk drive is attached with a disk inside.
G3R4RD #11
Posted 06 May 2012 - 02:19 PM
I actually found out how to do this. Its REALLY a lot simpler than all of this, although it needs to be done on every separate computer.

In the computer startup file, put the following code:


shell.runDiskBootPassword("the pass you want here")

This will enforce the computer to require a password on the computer before the disk may be run. For the code to work, you must put it in the startup file and then reboot the computer. It will then ask for the password when a disk drive is attached with a disk inside.

No, it isn't.
This is on our server, samrg did make that script. So its not in the standard ComputerCraft rom.
Zalerinian #12
Posted 06 May 2012 - 03:09 PM
I actually found out how to do this. Its REALLY a lot simpler than all of this, although it needs to be done on every separate computer.

In the computer startup file, put the following code:


shell.runDiskBootPassword("the pass you want here")

This will enforce the computer to require a password on the computer before the disk may be run. For the code to work, you must put it in the startup file and then reboot the computer. It will then ask for the password when a disk drive is attached with a disk inside.

No, it isn't.
This is on our server, samrg did make that script. So its not in the standard ComputerCraft rom.

Well now that's a disappointment.
Dr_Zarreh #13
Posted 12 May 2012 - 02:41 PM
Advert, i like you script and all, but im a noob and could you possibly create one that's not password-based but requires disk/boot…
djblocksaway #14
Posted 13 May 2012 - 02:30 PM
i swear i remember reading that it wasnt posssible o.O
Cloudy #15
Posted 13 May 2012 - 07:45 PM
i swear i remember reading that it wasnt posssible o.O

Read the thread. It isn't possible without editing the bios.lua.
boar401s2 #16
Posted 08 June 2013 - 05:40 AM
Hi,

I'm not sure if this has been explored before, but I've been looking at finding a way to prevent this without editing the rom. This is not always the best option, granted, but hopefully it will help you guys :)/>

So, basically I've been fiding people bipassing the security on my doors by adding a disk drive next to the computer that you log into, and adding their own startup file.

So, how to fix you ask… The disk drives have a boot priority, so if there are more than one disk drive, CC chooses which one to boot first. I *believe* it is a disk drive located on the top of the computer. So to counteract the above scenario, you firstly put a disk drive ontop of the computer you want to stop getting hacked, some how make the disk drive inaccessable by people you don't want poking around, then you put your startup code in that. So even if they add a disk drive of their own, your disk drive, with your login code will be given priority.

Another ProTip(s):

1. Don't use the same password for everything
2. Don't store your password as plaintext.

Now, step two is a bit more harder - the idea is to encrypt the password in a way that it's not able to get decrypted, then save this in your password variable. Then what you do, is when someone types in a password, is have it then encrypt the password with the same algorithm, and then compare the two strings together. The encrypted inputted password, and the pre-encrypted password. The encrypted password that is in place of the plaintext password is called the hash. Also, an example encryption algorithm for this would be SHA-512.

I hope this helps! This is my first post, and I'm not sure how to post in the Tutorials section, if I knew, I would post it in there, so if you haven't gotten what I said up above, whenever I figure out how to post in the Tutorials section, I'll do so!

-Boar

[EDIT]

Also, don't use "dictionary" words as your password. For example, don't use "cat" as your password, this can get "bruteforced" easily. Use a random password. How people can hack SHA-512 passwords is by using websites, that basically look at the SHA-512 encrypted string you give it, compare it to a whole ton of hashes, and see which hash matches a dictionary word. However, if you don't use a dictionary word, it makes it virtually unhackable.
figgycity50 #17
Posted 09 June 2013 - 10:35 AM
Hi,

I'm not sure if this has been explored before, but I've been looking at finding a way to prevent this without editing the rom. This is not always the best option, granted, but hopefully it will help you guys :)/>

So, basically I've been fiding people bipassing the security on my doors by adding a disk drive next to the computer that you log into, and adding their own startup file.

So, how to fix you ask… The disk drives have a boot priority, so if there are more than one disk drive, CC chooses which one to boot first. I *believe* it is a disk drive located on the top of the computer. So to counteract the above scenario, you firstly put a disk drive ontop of the computer you want to stop getting hacked, some how make the disk drive inaccessable by people you don't want poking around, then you put your startup code in that. So even if they add a disk drive of their own, your disk drive, with your login code will be given priority.

Another ProTip(s):

1. Don't use the same password for everything
2. Don't store your password as plaintext.

Now, step two is a bit more harder - the idea is to encrypt the password in a way that it's not able to get decrypted, then save this in your password variable. Then what you do, is when someone types in a password, is have it then encrypt the password with the same algorithm, and then compare the two strings together. The encrypted inputted password, and the pre-encrypted password. The encrypted password that is in place of the plaintext password is called the hash. Also, an example encryption algorithm for this would be SHA-512.

I hope this helps! This is my first post, and I'm not sure how to post in the Tutorials section, if I knew, I would post it in there, so if you haven't gotten what I said up above, whenever I figure out how to post in the Tutorials section, I'll do so!

-Boar

[EDIT]

Also, don't use "dictionary" words as your password. For example, don't use "cat" as your password, this can get "bruteforced" easily. Use a random password. How people can hack SHA-512 passwords is by using websites, that basically look at the SHA-512 encrypted string you give it, compare it to a whole ton of hashes, and see which hash matches a dictionary word. However, if you don't use a dictionary word, it makes it virtually unhackable.
If you search on the forums for String Utils API there are functions that easily let you do that.
Tigerlife #18
Posted 21 January 2017 - 05:36 AM
since the script you would remove is in lua, that means it would be stored within each computercraft computer, and you could find it within and modify it on the server, disabling disk boot. in theory, at least.
Bomb Bloke #19
Posted 21 January 2017 - 07:51 AM
This thread is a tad outdated, now that the settings API exists.