commit d2e130a4ad26d0881be1cc77b4d2bcfc2500bcef Author: Avril Date: Sun May 24 20:10:06 2020 +0100 uhh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa58426 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +sfexec +bin/ +obj/ +sha256_literal/ diff --git a/generator-native/Cargo.toml b/generator-native/Cargo.toml new file mode 100644 index 0000000..72c05fd --- /dev/null +++ b/generator-native/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "generator-native" +version = "0.1.0" +authors = ["Avril "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/generator-native/src/main.rs b/generator-native/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/generator-native/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/generator/Program.cs b/generator/Program.cs new file mode 100644 index 0000000..735852c --- /dev/null +++ b/generator/Program.cs @@ -0,0 +1,162 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; + +namespace generator +{ + [Flags] + enum Mode + { + None = 0, + Silent = 1<<0, + Execute = 1<<1, + } + class Program + { + static string execstr=null; + static string output = "file.h"; + static string[] files = null; + static Mode ParseArgs(Taker args) + { + List f = new List(); + Mode mode = Mode.None; + + bool look=true; + while(args.TryTake(out var arg0)) + { + switch(arg0) + { + case "-s" when look: + mode |= Mode.Silent; + break; + case "-e" when look: + mode |= Mode.Execute; + if(args.TryTake(out var exec)) + execstr = exec; + else + throw new InvalidOperationException("-e must be given a string"); + break; + case "-o" when look: + if(!args.TryTake(out output)) + throw new InvalidOperationException("-o must be given an output"); + break; + case "-" when look: + look =false; + break; + default: + f.Add(arg0); + break; + } + } + files = f.ToArray(); + return mode; + } + static void Main(string[] args) + { + Mode mode; + try { + mode = ParseArgs(new Taker(args)); + } catch(Exception e) + { + Console.WriteLine("Error: "+e.Message); + return; + } + + if(files.Length<1) + { + Console.WriteLine("Usage: generator [-e ] [-s] [-] "); + return; + } + Console.WriteLine("Writing to "+output+"..."); + using(var fs = new FileStream(output, FileMode.Create)) + { + using(var sw = new StreamWriter(fs)) { + if(mode.HasFlag(Mode.Silent)) + sw.WriteLine("#define SILENT"); + + sw.WriteLine($"constexpr const int DATA_COUNT = {files.Length};"); + + if(mode.HasFlag(Mode.Execute)) { + var exec_str = $"\"{CEscape(execstr)}\""; + sw.WriteLine($"constexpr const char* const DATA_EXEC_AFTER = {exec_str};"); + sw.WriteLine($"static constexpr auto DATA_EXEC_AFTER_HASH = {exec_str}_sha256;"); + } + else { + sw.WriteLine("constexpr const char* const DATA_EXEC_AFTER = nullptr;"); + sw.WriteLine("static constexpr auto DATA_EXEC_AFTER_HASH = \"unbound\"_sha256;"); + } + + List sizes= new List(); + sw.WriteLine("constexpr const unsigned char DATA[] = {"); + + foreach(var str in files) + { + using(var ifs = new FileStream(str, FileMode.Open, FileAccess.Read)) + { + Console.Write(" + "+str); + try { + sizes.Add(WriteFile(sw, ifs)); + sw.WriteLine(); + Console.WriteLine(" OK"); + } catch(Exception ex) { + Console.WriteLine(" FAILED: "+ex.Message); + } + } + } + sw.WriteLine("};"); + + Console.WriteLine("Adding lengths"); + + sw.WriteLine("constexpr const long DATA_LENGTHS[DATA_COUNT] = {"); + foreach(var len in sizes) + sw.Write($"\t{len}ll,"); + sw.WriteLine("\n};"); + + Console.WriteLine("Adding names"); + + sw.WriteLine("constexpr const char* const DATA_NAMES[DATA_COUNT] = {"); + foreach(var n in files) + sw.Write("\t\""+CEscape(n.Split(Path.DirectorySeparatorChar)[^1])+"\","); + sw.WriteLine("};"); + } + } + } + + static long WriteFile(StreamWriter to, Stream from) + { + int rd; + long len=0; + while( (rd = from.ReadByte()) >= 0) + { + to.Write($"0x{((byte)rd):x2}, "); + len+=1; + } + return len; + } + + static string CEscape(string inp) + { + return inp.Replace("\\", @"\\") + .Replace("\"", "\\\""); + } + } + class Taker + { + readonly IEnumerator iter; + public Taker(IEnumerable input) + { + iter =input.GetEnumerator(); + } + + public bool TryTake(out T value) + { + if(!iter.MoveNext()){ + value=default; + return false; + } + value = iter.Current; + return true; + } + } +} diff --git a/generator/generator.csproj b/generator/generator.csproj new file mode 100644 index 0000000..d453e9a --- /dev/null +++ b/generator/generator.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.1 + + + diff --git a/get-deps b/get-deps new file mode 100755 index 0000000..15d0075 --- /dev/null +++ b/get-deps @@ -0,0 +1,3 @@ +#!/bin/bash + +git clone https://github.com/aguinet/sha256_literal diff --git a/include/sha256.h b/include/sha256.h new file mode 120000 index 0000000..7593a2e --- /dev/null +++ b/include/sha256.h @@ -0,0 +1 @@ +../sha256_literal/sha256.h \ No newline at end of file diff --git a/include/sha256_literal.h b/include/sha256_literal.h new file mode 120000 index 0000000..932617d --- /dev/null +++ b/include/sha256_literal.h @@ -0,0 +1 @@ +../sha256_literal/sha256_literal.h \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..8bb5652 --- /dev/null +++ b/main.cpp @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wattributes" + +#include +#include + +using namespace std; +namespace fs = std::filesystem; + +string get_uuid() { + static random_device dev; + static mt19937 rng(dev()); + + uniform_int_distribution dist(0, 15); + + const char *v = "0123456789abcdef"; + const bool dash[] = { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 }; + + string res; + for (int i = 0; i < 16; i++) { + if (dash[i]) res += "-"; + res += v[dist(rng)]; + res += v[dist(rng)]; + } + return res; +} + +// DATA +// DATA_LENGTHS +// DATA_NAMES +// DATA_COUNT +// DATA_EXEC_AFTER +// DATA_EXEC_AFTER_HASH +#include "file.h" + +bool verify_hash() +{ + + return (!DATA_EXEC_AFTER || sha256::compute((const uint8_t*)DATA_EXEC_AFTER, strlen(DATA_EXEC_AFTER)) == DATA_EXEC_AFTER_HASH); +} + +string arg_vec_int(int i) +{ + stringstream ss; + ss << "%arg\\[" << i << "\\]"; + return ss.str(); +} + +string get_exec_str(vector args, string args_full, string loc) +{ + string str(DATA_EXEC_AFTER); + + str = regex_replace(str, std::regex("%location"), loc); + + str = regex_replace(str, std::regex("%argc"), std::to_string(args.size())); + + str = regex_replace(str, std::regex("%args"), args_full); + + + for(int i=0;i& output) +{ + stringstream ss; + for(int i=1;i vecargs; + auto args = arg_strings(argc,argv, vecargs); + + if(!verify_hash()) + { + cerr << "Error: Bad message hash\n"; + return 1; + } + +#ifndef SILENT + cout << "Extracting " << DATA_COUNT << " files to " << path << "...\n"; +#endif + + fs::create_directory(path); + for(int i=0;i/dev/null 2>&1 ; pwd -P )" + +dotnet run --project "$SCRIPTPATH/generator" -o "$SCRIPTPATH/file.h" "$@" || exit 1 + + +[[ -f "$SCRIPTPATH/file.h" ]] || exit 1 + +echo "Compiling binary..." + +g++ -I$SCRIPTPATH/include/ -w --std=c++17 "$SCRIPTPATH/main.cpp" "$SCRIPTPATH/sha256_literal/sha256.cpp" -o sfexec + +rm "$SCRIPTPATH/file.h" + +echo "Complete." diff --git a/sfexec-create-compress b/sfexec-create-compress new file mode 100755 index 0000000..1153ce9 --- /dev/null +++ b/sfexec-create-compress @@ -0,0 +1,11 @@ +#!/bin/bash + +sfexec-create "$@" || exit 1 + +echo "Compressing..." +gzip sfexec || exit 1 + +sfexec-create -s -e 'gzip -d %location/sfexec.gz && chmod +x %location/sfexec && %location/sfexec %args' sfexec.gz > /dev/null || exit 1 + +rm sfexec.gz +echo "Done."