DAK404 / Truncheon

A cross platform shell, written in Java.
https://dak404.github.io/Truncheon
GNU Lesser General Public License v3.0
4 stars 0 forks source link

Abraxis broken due to different file separators on different OSes #9

Closed DAK404 closed 8 months ago

DAK404 commented 1 year ago

It seems to be that on Windows, the '\' is used as a file separator. In Linux it is '/'.

Due to how Abraxis is designed right now, it seems that there are obvious conflicts when trying to compile and run on Linux.

The solution for now: Compile the program on Windows and run it on Linux.

The better solution: redesign Abraxis subsystem to better fit the system.

When trying to figure the issue out, the below was found.

Source:

// DEBUG CODE //
props.list(System.out);
// DEBUG CODE //

for(String fp : filePath)
{
    if(fp.endsWith(".class"))
    {
        System.out.println((System.getProperty("os.name").contains("Windows")?fp:convertSlashFormat(fp)) + "\t" + (props.get(System.getProperty("os.name").contains("Windows")?fp:convertSlashFormat(fp))));
        System.out.println((System.getProperty("os.name").contains("Windows")?fp:convertSlashFormat(fp)).equals((props.get(fp))));
        if((System.getProperty("os.name").contains("Windows")?fp:convertSlashFormat(fp)).equals((props.get(fp))))
        {
            System.out.println(props.get(fp).getClass());
            System.out.println(fp);
            returnValue = false;
            break;
        }
        fileCount++;
    }
}

Output of this snippet:

dak@localhost:/run/media/dak/TurboCache/Projects/Truncheon/Binaries> java Main Truncheon normal
[ INFORMATION ] Manifest file found. Populating files and directories...
[ INFORMATION ] Files and Directories populated! Running Integrity Checks...
[ INFORMATION ] Checking Core Files...
-- listing properties --
.\Truncheon\API\Grinch\Wyvern\Installer.class=./Truncheon/API/Grinch/Wyvern/Install...
.\Truncheon\API\Dragon\LoginAuth.class=./Truncheon/API/Dragon/LoginAuth.class
.\Truncheon\Core\Loader.class=./Truncheon/Core/Loader.class
.\Truncheon\API\Minotaur\PolicyEdit.class=./Truncheon/API/Minotaur/PolicyEdit.c...
.\Truncheon\API\Grinch\Wyvern\Updater.class=./Truncheon/API/Grinch/Wyvern/Updater...
.\Truncheon\API\Grinch\FileManagement.class=./Truncheon/API/Grinch/FileManagement...
.\Truncheon\API\Wraith\WraithRead.class=./Truncheon/API/Wraith/WraithRead.class
.\Truncheon\API\BuildInfo.class=./Truncheon/API/BuildInfo.class
.\Truncheon\API\Dragon\AccountModify.class=./Truncheon/API/Dragon/AccountModify....
.\Truncheon\API\IOStreams.class=./Truncheon/API/IOStreams.class
.\Truncheon\API\Wraith\WraithEdit.class=./Truncheon/API/Wraith/WraithEdit.class
.\Truncheon\API\ExceptionHandler.class=./Truncheon/API/ExceptionHandler.class
.\Truncheon\Core\Setup.class=./Truncheon/Core/Setup.class
.\Truncheon\API\Dragon\AccountCreate.class=./Truncheon/API/Dragon/AccountCreate....
.\Truncheon\API\Anvil.class=./Truncheon/API/Anvil.class
.\Truncheon\Core\NionKernel.class=./Truncheon/Core/NionKernel.class
.\Truncheon\API\Anvil1.class=./Truncheon/API/Anvil1.class
.\Truncheon\API\Dragon\AccountDelete.class=./Truncheon/API/Dragon/AccountDelete....
.\Truncheon\API\Minotaur\Cryptography.class=./Truncheon/API/Minotaur/Cryptography...
.\Truncheon\API\Minotaur\PolicyEnforce.class=./Truncheon/API/Minotaur/PolicyEnforc...
.\Main.class=./Main.class
.\Truncheon\API\Grinch\Download.class=./Truncheon/API/Grinch/Download.class
.\Main.class    ./Main.class
false
.\Truncheon\API\Anvil.class     ./Truncheon/API/Anvil.class
false
.\Truncheon\API\Anvil1.class    ./Truncheon/API/Anvil1.class
false
.\Truncheon\API\BuildInfo.class ./Truncheon/API/BuildInfo.class
false
.\Truncheon\API\Dragon\AccountCreate.class      ./Truncheon/API/Dragon/AccountCreate.class
false
.\Truncheon\API\Dragon\AccountDelete.class      ./Truncheon/API/Dragon/AccountDelete.class
false
.\Truncheon\API\Dragon\AccountModify.class      ./Truncheon/API/Dragon/AccountModify.class
false
.\Truncheon\API\Dragon\LoginAuth.class  ./Truncheon/API/Dragon/LoginAuth.class
false
.\Truncheon\API\ExceptionHandler.class  ./Truncheon/API/ExceptionHandler.class
false
.\Truncheon\API\Grinch\Download.class   ./Truncheon/API/Grinch/Download.class
false
.\Truncheon\API\Grinch\FileManagement.class     ./Truncheon/API/Grinch/FileManagement.class
false
.\Truncheon\API\Grinch\Wyvern\Installer.class   ./Truncheon/API/Grinch/Wyvern/Installer.class
false
.\Truncheon\API\Grinch\Wyvern\Updater.class     ./Truncheon/API/Grinch/Wyvern/Updater.class
false
.\Truncheon\API\IOStreams.class ./Truncheon/API/IOStreams.class
false
.\Truncheon\API\Minotaur\Cryptography.class     ./Truncheon/API/Minotaur/Cryptography.class
false
.\Truncheon\API\Minotaur\PolicyEdit.class       ./Truncheon/API/Minotaur/PolicyEdit.class
false
.\Truncheon\API\Minotaur\PolicyEnforce.class    ./Truncheon/API/Minotaur/PolicyEnforce.class
false
.\Truncheon\API\Wraith\WraithEdit.class ./Truncheon/API/Wraith/WraithEdit.class
false
.\Truncheon\API\Wraith\WraithRead.class ./Truncheon/API/Wraith/WraithRead.class
false
.\Truncheon\Core\Loader.class   ./Truncheon/Core/Loader.class
false
.\Truncheon\Core\NionKernel.class       ./Truncheon/Core/NionKernel.class
false
.\Truncheon\Core\Setup.class    ./Truncheon/Core/Setup.class
false
22
22

The important segment is the output of -- listing properties --

Edit: Title change

DAK404 commented 1 year ago

As of now, I am focusing on how to store the entries in the manifest files and arrive at a robust solution for this issue.

Will update when there are any findings.

DAK404 commented 1 year ago

Looking at the implementation, it is evident that the key value has the conflict.

This can be mitigated without reworking the entire Abraxis system by the following algorithm:

BuildSigner.java

NOTE: This is the signing logic only!

  1. Store the file separator character in a variable
  2. receive file path
  3. add the file path to a String variable
  4. replace all the file separator character with the desired character (in this case, it is '/' [Forward Slash]
  5. add that to the Manifest file
  6. if it is the m1 manifest file, then store the hash else if it is the m2 manifest file, store the same converted value to the manifest file.
  7. finish other operations required by the build signer program

Loader.java

NOTE: This is the verification logic only!

  1. Store the file separator character in a variable
  2. Start the verification process
  3. receive the filepath and replace all the file separator character with the desired character [Forward Slash]
  4. see if the entries match [the file signature or the file path stored in the manifest file]
  5. output the desired result [verification succeeded or failed]
  6. continue with the other operations.

This is one of the ways that the system can be worked with.

Here is an alternative way to work on the system too:

  1. capture the file count [number of core .class files in the Truncheon directory]
  2. see if it matches with the number of entries in the Manifest files
  3. start comparing the hashes of each file with the manifest entry [ see logic below ]

// Convert the selected file hash and store it in variable fileHash //get the value of the hash stored in the manifest file and store it in the manifestHash variable

if(! fileHash.equals(manifestHash)) { return value = false; break; }



This can also be supplemented by adding the logic:

m2 manifest will contain the hash for m1 manifest. This will run a check if the system is checking a compromised manifest file and will abort the boot when found. This is a security feature that can be useful too.

Once the logic checks for the m1 manifest and passes, the m2 manifest entries will be checked and will continue boot.

Will add comments when I can think of something useful.
DAK404 commented 1 year ago

There is another possible solution to this issue:

enumerate all paths and then change the file separator system into an OS neutral character.

Eg. There are reserved characters such as < and >, and these characters can be used as an OS neutral file separator.

The program can then retrieve the file separator and then compare the paths after the characters have been replaced.

eg.

On Windows, the paths look like .\Truncheon\Test

in the manifest file, the path can be denoted as .>Truncheon>Test

Therefore, during runtime, the path can be parsed by substituting the character / on Linux and \ on Windows.

Therefore:

Windows: .\Truncheon\Test Linux: ./Truncheon/Test

The file separator character can be stored as a string

String fileSeparator = System.getProperty("file.separator");

//replace logic to replace all the occurrence of > to the system file separator.

String newPath = manifestPath.replaceAll(">", fileSeparator);

This can help in reducing any conflicts irrespective of the OS being used to build Truncheon.

A dry run of this prototype code is attached below:

class HelloWorld {
    public static void main(String[] args) {

        String manifestPath = ".>Truncheon>test>hello.txt";
        String fileSeparator = System.getProperty("file.separator");
        String newPath = manifestPath.replaceAll(">", fileSeparator);
        System.out.println(manifestPath + "\n" + newPath);
    }
}

The output of the program was:

.>Truncheon>test>hello.txt
./Truncheon/test/hello.txt
DAK404 commented 1 year ago

There is another possible solution to this issue:

enumerate all paths and then change the file separator system into an OS neutral character.

Eg. There are reserved characters such as < and >, and these characters can be used as an OS neutral file separator.

The program can then retrieve the file separator and then compare the paths after the characters have been replaced.

eg.

On Windows, the paths look like .\Truncheon\Test

in the manifest file, the path can be denoted as .>Truncheon>Test

Therefore, during runtime, the path can be parsed by substituting the character / on Linux and \ on Windows.

Therefore:

Windows: .\Truncheon\Test Linux: ./Truncheon/Test

The file separator character can be stored as a string

String fileSeparator = System.getProperty("file.separator");

//replace logic to replace all the occurrence of > to the system file separator.

String newPath = manifestPath.replaceAll(">", fileSeparator);

This can help in reducing any conflicts irrespective of the OS being used to build Truncheon.

A dry run of this prototype code is attached below:

class HelloWorld {
    public static void main(String[] args) {

        String manifestPath = ".>Truncheon>test>hello.txt";
        String fileSeparator = System.getProperty("file.separator");
        String newPath = manifestPath.replaceAll(">", fileSeparator);
        System.out.println(manifestPath + "\n" + newPath);
    }
}

The output of the program was:

.>Truncheon>test>hello.txt
./Truncheon/test/hello.txt

It seems like the logic specified will need a special mode for Windows, since the logic might break with Windows file separator.

replaceAll() requires \\\\ to be present instead of just a \ So an assert must be placed to avoid breaking the program when the replacement is done.

Other than that, this logic must work fine.

DAK404 commented 1 year ago

Found a potential fix to this issue. Testing it out soon.

s = s.replaceAll("/", Matcher.quoteReplacement(File.separator));

Got yet another snippet working.

import java.io.File;

public class test
{
    public static void main(String[] args)
    {
        String path = "temp>Test>file>file.txt";
        String separator = File.separator;
        String replacedPath = path.replaceAll(">", separator);
        System.out.println(replacedPath);
        System.out.println(replacedPath.replaceAll(separator, ">"));
    }
}

Output as follows

dak@Overlord-Neo:/run/media/dak/TurboCache/prototype> java test.java
temp/Test/file/file.txt
temp>Test>file>file.txt
dak@Overlord-Neo:/run/media/dak/TurboCache/prototype> 

Testing the same on Windows soon.

DAK404 commented 1 year ago

Code did not work.

DAK404 commented 1 year ago

SOLUTION

Modified it a bit and got it working by combining both the solutions.


import java.io.File;
import java.util.regex.Matcher;

public class test
{
    public static void main(String[] args)
    {
        String path = "temp>Test>file>file.txt";
        String separator = File.separator;
        String replacedPath = path.replaceAll(">", Matcher.quoteReplacement(separator));
        System.out.println(replacedPath);
        System.out.println(replacedPath.replaceAll(Matcher.quoteReplacement(separator), ">"));
    }
}

The following outputs were captured on Windows and Linux respectively.

Windows:

PS C:\Users\DAK\Desktop> java .\test.java
temp\Test\file\file.txt
temp>Test>file>file.txt
PS C:\Users\DAK\Desktop>

Linux:

dak@Overlord-Neo:/run/media/dak/TurboCache/prototype> java test.java
temp/Test/file/file.txt
temp>Test>file>file.txt
dak@Overlord-Neo:/run/media/dak/TurboCache/prototype> 
DAK404 commented 1 year ago

This will be soon prototyped and tested in Abraxis. Once it seems to be working both on Windows and Linux, it will be patched.

DAK404 commented 1 year ago

Prototyped and Implemented the logic in Cataphract. image

Some testing required.

https://github.com/DAK404/Cataphract/commit/2b06622c8da4b512614def4fb7ccb24b5f0cb771

DAK404 commented 1 year ago

In Cataphract, the manifest files look something like this:

M1 Manifest: image

M2 Manifest: image

Issue seems to be fixed. Will port this logic over to Truncheon and then close the issue.

Things to modify:

DAK404 commented 8 months ago

Seems like this requires a complete change in the Loader.java class.

As specified in #10, Cataphract is much more complete, therefore, if the changes cant be brought back to Katana, this issue will be closed, and the project will be archived/set to read-only.

Check this space to be updated for more information

DAK404 commented 8 months ago

This issue will not be fixed.

Cataphract has implemented the fix. Please migrate to that.