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

Can ROM programs edit files in ROM?

Started by MrObsidy, 14 April 2016 - 05:22 AM
MrObsidy #1
Posted 14 April 2016 - 07:22 AM
Heya!
So I've been programming my own ROM, and I want a BIOS password protection.
However If I dont put it in rom, almost any program can edit the password file and make the whole BIOS useless-especially cause my BIOS is AINED to stop starzup-viruses. So my question is, could I use a program to read/write the Passworf in the ROM dirrctory?

Thanks!
-AlexEDIT: Please keep in Mind that I can change all bios files to my belonging. (Also the BIOS.lua)
Edited on 14 April 2016 - 05:24 AM
Sewbacca #2
Posted 14 April 2016 - 12:28 PM
I am searching a way too. You can't use the rom, but you can rewrite loadfile, but I get many complications, because the bios and rom programs use loadfile, it would work, but it wouldn't be easy.
Goof #3
Posted 14 April 2016 - 12:36 PM
Hmm. I'm thinking of a way of "locking" that password file.
what about rewriting the FS API to return "Not accessible" error, when trying to open/edit the file?

Since your bios.lua would be run before anything else, this would be fairly easy to do.
MrObsidy #4
Posted 16 April 2016 - 08:19 AM
Well, if someone simply uses io.open() or any similar shenanigans or even make his own fs api, I am kinda screwed.
Bomb Bloke #5
Posted 16 April 2016 - 08:38 AM
Bear in mind that as long as you can ensure your API is loaded first, the capabilities of their API won't be able to do anything yours doesn't allow already. Also bear in mind that io.open() relies on the fs API.
MrObsidy #6
Posted 16 April 2016 - 01:09 PM
It's the /rom/startup or bios.lua, so my api WILL be loaded first.
And thanks bomb bloke for always having the answer :D/>
MrObsidy #7
Posted 16 April 2016 - 07:57 PM
Problem is that fs.open() is located in the java code, it is nowhere to be found in bios.lua.
Any 'deas?
Lupus590 #8
Posted 16 April 2016 - 08:32 PM
overwrite the function


local oldPrint = print

function print()
  oldPrint("I have stolen your print")
end

the same principle as above can be applied to fs.open, just get your file to run on startup (there is a nice folder in resource packs which are auto ran: http://www.computercraft.info/wiki/Lua_Resource_Pack_Making_%28Tutorial%29#Special_Folders)
Edited on 16 April 2016 - 06:33 PM
MrObsidy #9
Posted 16 April 2016 - 08:40 PM
Problem is, will ALL old functionality be gone or does it just add my part to it? Cuz I cant edit files with the lua part of it, as it actually uses "real life" syscalls
P.S. if some moderator is seeing this plz dont apprpve the other answer, I logged into my wronf account
Goof #10
Posted 16 April 2016 - 09:16 PM
Problem is, will ALL old functionality be gone or does it just add my part to it? Cuz I cant edit files with the lua part of it, as it actually uses "real life" syscalls
P.S. if some moderator is seeing this plz dont apprpve the other answer, I logged into my wronf account

When talking about overwriting the FS API in general, you have to assure that you have a backup of the function ready. If you do not, you are making your new function the old one, which makes it impossible to actually get any functionality at all.

So to answer your question in general, Yes, If you do not backup the function, you will lose the function until the next computer reboot.
MrObsidy #11
Posted 16 April 2016 - 09:42 PM
No, I meant like if i overwrite that one specific function, if it will still work as normal but have that thing aka do i completely have to rewrite the function or simply just add a line of code saying
if dir == "/biosconfig" then
   error("Access Denied")
elseif dir == "/biosconfig" and caller == /bios.ua then
   whatever = fs open("lala") 
   --# do stuff
end
Edited on 16 April 2016 - 07:48 PM
MrObsidy #12
Posted 16 April 2016 - 10:02 PM
Oh i see, like:

local fsopenvanilla = fs.open
fs.open = function(filename, mode)
    --#If caller program is in rom, ok
    --#If not, f*ck off
end
Only problem is, how do I assure that the caller really is the rom, not just some pretend-a-be rom virus?
Bomb Bloke #13
Posted 17 April 2016 - 12:15 AM
I wouldn't bother to make the distinction. If you're loading your restricted function at the end of the boot process, then after that point, why would anything in rom need full r/w access?
MrObsidy #14
Posted 17 April 2016 - 10:43 AM
Ah, like dis:

if pwedit == true then
   --# change password logic
end
local nativefsopen = fs.open
fs.open = function(file, mode)
   if file == "bioscfg/password" then error("access denied") else nativefsopen(file, mode)
end
Edited on 17 April 2016 - 08:44 AM
Goof #15
Posted 17 April 2016 - 08:32 PM
Ah, like dis:

if pwedit == true then
   --# change password logic
end
local nativefsopen = fs.open
fs.open = function(file, mode)
   if file == "bioscfg/password" then error("access denied") else nativefsopen(file, mode)
end
Yeah, kinda. But it's posible to bypass that if doing this in the shell:

>cd rom
rom
>edit ../bioscfg/password
--#Now editing the password file
I do not remember the best way to do this, but i'm sure somebody else does
valithor #16
Posted 17 April 2016 - 11:42 PM
Ah, like dis:

if pwedit == true then
   --# change password logic
end
local nativefsopen = fs.open
fs.open = function(file, mode)
   if file == "bioscfg/password" then error("access denied") else nativefsopen(file, mode)
end
Yeah, kinda. But it's posible to bypass that if doing this in the shell:

>cd rom
rom
>edit ../bioscfg/password
--#Now editing the password file
I do not remember the best way to do this, but i'm sure somebody else does

Look into using fs.combine: http://www.computerc...wiki/Fs.combine

example:

fs.open = function(file, mode)
   if fs.combine("/",file) == "bioscfg/password" then error("access denied") else nativefsopen(file, mode)
end
Edited on 17 April 2016 - 09:44 PM
MrObsidy #17
Posted 18 April 2016 - 10:06 AM
I don't get how fs.combine works.
Bomb Bloke #18
Posted 18 April 2016 - 10:20 AM
Basically it takes two paths and stick them end on end. As part of the process, it prunes out parent directory references such as .., making it easier for you catch tricks like the one Mikk809h mentioned.
Goof #19
Posted 18 April 2016 - 11:14 AM
And if you're in trouble getting it to work, i made this (working) file locker.

Spoiler

local old = {} -- Backup table
local locked = {}

for k,v in pairs(fs) do -- loop through the FS API and make a backup
    old[k]=v
end

-- Begin overwriting the necessary functions
function fs.open( file, handle )
    local path = fs.combine( "/", file:lower() )
    for k,v in pairs( locked ) do
        if k == path and v==true then
            error( "This file is locked", 0 )
            return false
        end
    end
    return old.open( file, handle )
end
function fs.delete( file )
    local path = fs.combine( "/", file:lower() )
    for k,v in pairs( locked ) do
        if k == path and v==true then
            error( "This file is locked", 0 )
            return false
        end
    end
    return old.delete( file )
end
function fs.move( file, destination )
    local path = fs.combine( "/", file:lower() )
    for k,v in pairs( locked ) do
        if k == path and v==true then
            error( "This file is locked", 0 )
            return false
        end
    end
    return old.move( file, destination )
end
function fs.copy( file, distination )
    local path = fs.combine( "/", file:lower() )
    for k,v in pairs( locked ) do
        if k == path and v==true then
            error( "This file is locked", 0 )
            return false
        end
    end
    return old.copy( file, distination )
end
function fs.lock( file, opt_password )
    locked[file:lower()] = true
end
function fs.unlock( file, opt_password )
    for k,v in pairs( locked ) do
        if k == file:lower() then
            locked[k] = false
        end
    end
end

A picture of it in action (Note, i called the program "lock")



And if you want to implement password protection, that'd be "easy" aswell as adding a read("*") function

EDIT: Changed code slightly
Edited on 18 April 2016 - 10:17 AM
Bomb Bloke #20
Posted 18 April 2016 - 11:29 AM
CC's a bit screwy with case and file systems, but just off the top of my head, I still reckon you'll need to :lower() your incoming strings to ensure the user isn't pulling any tricks there.

Though that'll cause problems in those instances where the fs IS case sensitive. Hmm. I can't immediately think of a way to detect that, either.
Goof #21
Posted 18 April 2016 - 12:01 PM
CC's a bit screwy with case and file systems, but just off the top of my head, I still reckon you'll need to :lower() your incoming strings to ensure the user isn't pulling any tricks there.

Though that'll cause problems in those instances where the fs IS case sensitive. Hmm. I can't immediately think of a way to detect that, either.

Well. I just tried making two files;
File #1 is called Test
File #2 is called test

Then I edited File #1 and typed "THIS IS UPPERCASE", then saved.

Then I edited File #2 and before i typed anything the sentence "THIS IS UPPERCASE" were appearing.
So i do not think that the file system is completely safe against that.
And just a side note: fs.list will not even return the "test" and "Test" files. Only one of them (I think that is random wether its uppercase or not.)

So i am not entirely sure wether a path:lower() would be necessary.

EDIT: Yeah, You are indeed right. I think i misunderstood the comment a bit. You are able to bypass this by doing something like "rm Deletethis" instead of "rm deletethis".
The previous comment will be edited
Edited on 18 April 2016 - 10:13 AM
Bomb Bloke #22
Posted 18 April 2016 - 01:53 PM
It's a bit more complex than that. The issue is that the fs API mostly takes on the behaviours of the underlying file system - meaning that "cd ……" for eg behaves differently on NTFS than it does under, I dunno, say, HFS. Likewise, if your file system is case sensitive (though let's face it, for most users it won't be), you may not get the same behaviour.

rm is a bit of a special case because it first checks file existence using fs.find(), and Dan's implementation of that particular function is case sensitive regardless as to whether the file system is - "rm DeleteThis" will fail on a file called "deletethis" even if fs.delete("DeleteThis") wouldn't.

My point is that if the current file system is case sensitive, then you shouldn't need to worry about case, and filtering it is technically incorrect behaviour. Personally, though, if I had to put up with case sensitive file systems on a regular basis I'd probably consider writing an override API to filter the wretched things away, I doubt many users would notice if you applied such filters to them, and if any of them cared, I'd be amazed if they actually had a good reason for it.

(I've not had much opportunity to test these behaviours, as I typically just play SSP on my case-insensitive machine, so some of what I say is based on inferences made from Dan's comments about certain bug reports. Mimic offers an example of what I'd expect a case sensitive environment to act like, but being an emulator, it may not actually be accurate.)
KingofGamesYami #23
Posted 18 April 2016 - 03:15 PM
Why not just leave the file handle open? That'll make it impossible for other files to read or write to that file, since it won't open. It's not good practice to do so, but I think it would solve your problem.
MrObsidy #24
Posted 19 April 2016 - 07:37 AM
Ok thanks. Still had my problems understandung it (I an german) but ij the end I understood it. Thanks again.