From 050ea8caa154c430d94cd0b68873c4387c550c94 Mon Sep 17 00:00:00 2001 From: Kevin Diaz Date: Sat, 3 Oct 2020 01:44:37 -0400 Subject: [PATCH 1/3] Default nasm/asm to 32 bit binaries --- lxc/executors/nasm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lxc/executors/nasm b/lxc/executors/nasm index df35c10..60c4963 100755 --- a/lxc/executors/nasm +++ b/lxc/executors/nasm @@ -1,4 +1,4 @@ cd /tmp/$2 -timeout -s KILL 10 nasm -f elf64 -o binary.o code.code -timeout -s KILL 10 ld binary.o -o binary +timeout -s KILL 10 nasm -f elf32 -o binary.o code.code +timeout -s KILL 10 ld -m elf_i386 binary.o -o binary runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" From 9ffca9abb11100fd1bb80fbc67c08f8f2d8693c2 Mon Sep 17 00:00:00 2001 From: Kevin Diaz Date: Sat, 3 Oct 2020 01:47:13 -0400 Subject: [PATCH 2/3] Add nasm/asm support for 64 bit binaries --- api/main.go | 335 ++++++++++++++++++++++++----------------------- lxc/execute | 3 + lxc/test_all_lxc | 4 +- 3 files changed, 175 insertions(+), 167 deletions(-) diff --git a/api/main.go b/api/main.go index 3ca388d..e34d9c9 100644 --- a/api/main.go +++ b/api/main.go @@ -1,249 +1,252 @@ package main import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os/exec" - "regexp" - "strings" - "time" + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os/exec" + "regexp" + "strings" + "time" ) type Inbound struct { - Language string `json:"language"` - Source string `json:"source"` - Args []string `json:"args"` + Language string `json:"language"` + Source string `json:"source"` + Args []string `json:"args"` } type Problem struct { - Code string `json:"code"` - Message string `json:"message"` + Code string `json:"code"` + Message string `json:"message"` } type Outbound struct { - Ran bool `json:"ran"` - Language string `json:"language"` - Version string `json:"version"` - Output string `json:"output"` + Ran bool `json:"ran"` + Language string `json:"language"` + Version string `json:"version"` + Output string `json:"output"` } type Language struct { - Name string `json:"name,omitempty"` - Version string `json:"version,omitempty"` + Name string `json:"name,omitempty"` + Version string `json:"version,omitempty"` } var instance int var languages []Language func main() { - port := "2000" + port := "2000" - var err error - languages, err = UpdateVersions() + var err error + languages, err = UpdateVersions() - if err != nil { - fmt.Println("could not get version info and therefore couldn't start") - fmt.Println(err) - return - } + if err != nil { + fmt.Println("could not get version info and therefore couldn't start") + fmt.Println(err) + return + } - fmt.Println("starting api on port", port) - http.HandleFunc("/execute", Execute) - http.HandleFunc("/versions", Versions) - http.ListenAndServe(":"+port, nil) + fmt.Println("starting api on port", port) + http.HandleFunc("/execute", Execute) + http.HandleFunc("/versions", Versions) + http.ListenAndServe(":"+port, nil) } func Execute(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") + res.Header().Set("Content-Type", "application/json") - // get json - inbound := Inbound{} - message := json.NewDecoder(req.Body) - message.Decode(&inbound) + // get json + inbound := Inbound{} + message := json.NewDecoder(req.Body) + message.Decode(&inbound) - whitelist := []string{ - "awk", - "bash", - "brainfuck", "bf", - "c", - "cpp", "c++", - "csharp", "cs", "c#", - "elixir", "exs", - "emacs", "elisp", "el", - "go", - "java", - "julia", "jl", - "kotlin", - "nasm", "asm", - "node", "javascript", "js", - "perl", "pl", - "php", - "python2", - "python3", "python", - "ruby", - "rust", - "swift", - "typescript", "ts", - } + whitelist := []string{ + "awk", + "bash", + "brainfuck", "bf", + "c", + "cpp", "c++", + "csharp", "cs", "c#", + "elixir", "exs", + "emacs", "elisp", "el", + "go", + "java", + "julia", "jl", + "kotlin", + "nasm", "asm", + "nasm64", "asm64", + "node", "javascript", "js", + "perl", "pl", + "php", + "python2", + "python3", "python", + "ruby", + "rust", + "swift", + "typescript", "ts", + } - // check if the supplied language is supported - // now calls function and returns - for _, lang := range whitelist { - if lang == inbound.Language { - launch(inbound, res) - return - } - } + // check if the supplied language is supported + // now calls function and returns + for _, lang := range whitelist { + if lang == inbound.Language { + launch(inbound, res) + return + } + } - // now only called when the language is not supported - problem := Problem{ - Code: "unsupported_language", - Message: inbound.Language + " is not supported by Piston", - } + // now only called when the language is not supported + problem := Problem{ + Code: "unsupported_language", + Message: inbound.Language + " is not supported by Piston", + } - pres, _ := json.Marshal(problem) + pres, _ := json.Marshal(problem) - res.Write(pres) + res.Write(pres) } func Versions(res http.ResponseWriter, req *http.Request) { - res.Header().Set("Content-Type", "application/json") + res.Header().Set("Content-Type", "application/json") - data, _ := json.Marshal(languages) + data, _ := json.Marshal(languages) - res.Write(data) + res.Write(data) } func launch(request Inbound, res http.ResponseWriter) { - stamp := time.Now().UnixNano() + stamp := time.Now().UnixNano() - // write the code to temp dir - srcfile := fmt.Sprintf("/tmp/%d.code", stamp) + // write the code to temp dir + srcfile := fmt.Sprintf("/tmp/%d.code", stamp) - ioutil.WriteFile(srcfile, []byte(request.Source), 0644) + ioutil.WriteFile(srcfile, []byte(request.Source), 0644) - // set up the arguments to send to the execute command - cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) + // set up the arguments to send to the execute command + cmd := exec.Command("../lxc/execute", request.Language, srcfile, strings.Join(request.Args, "\n")) - // capture out/err - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr + // capture out/err + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr - err := cmd.Run() + err := cmd.Run() - // get the executing version of the language - execlang := request.Language + // get the executing version of the language + execlang := request.Language - switch execlang { - case "bf": - execlang = "brainfuck" - case "c++": - execlang = "cpp" - case "cs", "c#": - execlang = "csharp" - case "el", "elisp": - execlang = "emacs" - case "exs": - execlang = "elixir" - case "asm": - execlang = "nasm" - case "js", "javascript": - execlang = "node" - case "jl": - execlang = "julia" - case "python": - execlang = "python3" - case "ts": - execlang = "typescript" - } + switch execlang { + case "bf": + execlang = "brainfuck" + case "c++": + execlang = "cpp" + case "cs", "c#": + execlang = "csharp" + case "el", "elisp": + execlang = "emacs" + case "exs": + execlang = "elixir" + case "asm": + execlang = "nasm" + case "asm64": + execlang = "nasm64" + case "js", "javascript": + execlang = "node" + case "jl": + execlang = "julia" + case "python": + execlang = "python3" + case "ts": + execlang = "typescript" + } - // prepare response - outbound := Outbound{ - Ran: err == nil, - Language: request.Language, - Version: "", - Output: strings.TrimSpace(stdout.String()), - } + // prepare response + outbound := Outbound{ + Ran: err == nil, + Language: request.Language, + Version: "", + Output: strings.TrimSpace(stdout.String()), + } - // retrieve the language version - for _, lang := range languages { - if lang.Name == execlang { - outbound.Version = lang.Version - break - } - } + // retrieve the language version + for _, lang := range languages { + if lang.Name == execlang { + outbound.Version = lang.Version + break + } + } - response, _ := json.Marshal(outbound) + response, _ := json.Marshal(outbound) - res.Write(response) + res.Write(response) } func UpdateVersions() ([]Language, error) { - langs, err := GetVersions() + langs, err := GetVersions() - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - return langs, nil + return langs, nil } // get all the language and their current version func GetVersions() ([]Language, error) { - var languages []Language + var languages []Language - res, err := ExecVersionScript() + res, err := ExecVersionScript() - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } - info := strings.Split(res, "---") + info := strings.Split(res, "---") - for _, v := range info { - if len(v) < 2 { - continue - } - name, version := GetVersion(v) - languages = append(languages, Language{ - Name: name, - Version: version, - }) - } + for _, v := range info { + if len(v) < 2 { + continue + } + name, version := GetVersion(v) + languages = append(languages, Language{ + Name: name, + Version: version, + }) + } - return languages, nil + return languages, nil } // run the script that retrieves all the language versions func ExecVersionScript() (string, error) { - cmd := exec.Command("../lxc/versions") + cmd := exec.Command("../lxc/versions") - var stdout bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stdout + var stdout bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stdout - err := cmd.Run() + err := cmd.Run() - return strings.ToLower(stdout.String()), err + return strings.ToLower(stdout.String()), err } // return the language and its version // most of the time it is easy to get the name and version // but for some languages helper functions are used func GetVersion(s string) (string, string) { - lines := strings.Split(s, "\n") + lines := strings.Split(s, "\n") - if lines[1] == "java" { - return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) - } + if lines[1] == "java" { + return "java", regexp.MustCompile("([0-9]+)").FindString(lines[2]) + } - if lines[1] == "emacs" { - return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) - } + if lines[1] == "emacs" { + return "emacs", regexp.MustCompile("([0-9]+\\.[0-9]+)").FindString(lines[2]) + } - return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) + return lines[1], regexp.MustCompile("([0-9]+\\.[0-9]+\\.[0-9]+)").FindString(s) } diff --git a/lxc/execute b/lxc/execute index 248caee..fa2a7b3 100755 --- a/lxc/execute +++ b/lxc/execute @@ -78,6 +78,9 @@ case "$lang" in "nasm" | "asm") bin=nasm ;; +"nasm64" | "asm64") + bin=nasm64 + ;; "node" | "js" | "javascript") bin=node ;; diff --git a/lxc/test_all_lxc b/lxc/test_all_lxc index 31ba976..dd7453f 100755 --- a/lxc/test_all_lxc +++ b/lxc/test_all_lxc @@ -23,8 +23,10 @@ echo 'testing js' ../execute js test.js echo 'testing kotlin' ../execute kotlin test.kt -echo 'testing asm' +echo 'testing asm 32 bit' ../execute asm test.nasm +echo 'testing asm 64 bit' +../execute asm64 test64.nasm echo 'testing php' ../execute php test.php echo 'testing perl' From 0253f244793e935d635ddc76926b6489d988d745 Mon Sep 17 00:00:00 2001 From: Kevin Diaz Date: Sat, 3 Oct 2020 13:16:15 -0400 Subject: [PATCH 3/3] Create nasm64 executor and test file --- lxc/executors/nasm64 | 4 ++++ lxc/tests/test64.nasm | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100755 lxc/executors/nasm64 create mode 100644 lxc/tests/test64.nasm diff --git a/lxc/executors/nasm64 b/lxc/executors/nasm64 new file mode 100755 index 0000000..8723995 --- /dev/null +++ b/lxc/executors/nasm64 @@ -0,0 +1,4 @@ +cd /tmp/$2 +timeout -s KILL 10 nasm -f elf64 -o binary.o code.code +timeout -s KILL 10 ld -m elf_x86_64 binary.o -o binary +runuser runner$1 -c "cd /tmp/$2 ; cat args.args | xargs -d '\n' timeout -s KILL 3 ./binary" diff --git a/lxc/tests/test64.nasm b/lxc/tests/test64.nasm new file mode 100644 index 0000000..191b8d3 --- /dev/null +++ b/lxc/tests/test64.nasm @@ -0,0 +1,18 @@ +SECTION .data + good: db "good", 0x0a, 0x0 + txtlen: equ $ - good + +SECTION .text +GLOBAL _start + +_start: + ;sys_write + mov rax, 1 + mov rdi, 1 + mov rsi, good + mov rdx, txtlen + syscall + ;sys_exit + mov rax, 60 + mov rdi, 0 + syscall