-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
365 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package controllers | ||
|
||
import ( | ||
"compress/gzip" | ||
"compress/zlib" | ||
"container/list" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
"net/url" | ||
"os" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
|
||
"Swego/src/cmd" | ||
"Swego/src/utils" | ||
|
||
rice "github.com/GeertJohan/go.rice" | ||
"github.com/gabriel-vasile/mimetype" | ||
"github.com/yeka/zip" | ||
) | ||
|
||
const pathEmbedded = "./assets/embedded/" | ||
|
||
// EmbeddedRequest manage the request on the embedded files (when the parameter ?embedded is present) | ||
func EmbeddedRequest(w http.ResponseWriter, req *http.Request) { | ||
requestPath := strings.Split(req.RequestURI, "?")[0] | ||
|
||
if requestPath[len(requestPath)-1:] == "/" { // Directory listing if it's a folder (last character is /) | ||
handleEmbeddedDirectory(requestPath, w, req) | ||
} else { // It's a file, we serve the file | ||
fileName := requestPath[1:] | ||
serveEmbeddedFile(fileName, w, req) | ||
} | ||
} | ||
|
||
func serveEmbeddedFile(filePath string, w http.ResponseWriter, req *http.Request) { | ||
//Can't use variable, otherwise rice generate an error when rice embed-go .... | ||
templateBox, err := rice.FindBox("../assets/embedded/") | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// Opening the file handle | ||
//f, err := os.Open(filePath) | ||
f, err := templateBox.Open(filePath) | ||
// Content-Type handling | ||
query, errParseQuery := url.ParseQuery(req.URL.RawQuery) | ||
|
||
if err != nil { | ||
http.Error(w, "404 Not Found : Error while opening the file.", 404) | ||
log.Println("404 Not Found : Error while opening the file " + filePath) | ||
return | ||
} | ||
defer f.Close() | ||
|
||
// Checking if the opened handle is really a file | ||
statinfo, err := f.Stat() | ||
|
||
//buf := make([]byte, utils.Min(fs_maxbufsize, statinfo.Size())) | ||
//buf := make([]byte, statinfo.Size()) | ||
//fmt.Println(len(buf)) | ||
//f.Read(buf) | ||
|
||
if err != nil || errParseQuery != nil { | ||
http.Error(w, "500 Internal Error : stat() failure.", 500) | ||
log.Println("500 Internal Error : stat() failure for the file: " + filePath) | ||
return | ||
} | ||
if errParseQuery == nil && len(query["dl"]) > 0 { // The user explicitedly wanted to download the file (Dropbox style!) | ||
w.Header().Set("Content-Type", "application/octet-stream") | ||
} else if errParseQuery == nil && len(query["dlenc"]) > 0 { // Download the file as an encrypted zip | ||
|
||
// Absolute path to the file | ||
//filePathName := f.Name() | ||
// Create the zip file can't create in embedded path. Create temporarily in root of the webserver | ||
zipFile, err := os.Create(filePath + ".zip") | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
zipFilePath := zipFile.Name() | ||
zipw := zip.NewWriter(zipFile) | ||
|
||
// Add file f to the zip | ||
utils.AddRicefiletoZip(statinfo.Name(), f, filePath, zipw, true, "infected") | ||
|
||
// Manually close the zip | ||
zipw.Close() | ||
|
||
// Generate the request for the new file | ||
newFile := strings.Split(req.URL.String(), "?") | ||
fmt.Println(zipFilePath) | ||
newRequest, _ := http.NewRequest("GET", "http://"+req.Host+newFile[0], nil) | ||
|
||
// Serve the new file (encrypted zip) | ||
serveFile(zipFilePath, w, newRequest) | ||
os.Remove(zipFilePath) | ||
return | ||
} else { | ||
// Need its own rice.file otherwise it will miss the first chunck | ||
fileForMime, _ := templateBox.Open(filePath) | ||
defer fileForMime.Close() | ||
// Fetching file's mimetype and giving it to the browser | ||
if mimetype, _ := mimetype.DetectReader(fileForMime); mimetype.String() != "" { | ||
w.Header().Set("Content-Type", mimetype.String()) | ||
} else { | ||
w.Header().Set("Content-Type", "application/octet-stream") | ||
} | ||
} | ||
|
||
// Manage gzip/zlib compression | ||
outputWriter := w.(io.Writer) | ||
|
||
isCompressedReply := false | ||
|
||
if (cmd.Gzip) == true && req.Header.Get("Accept-Encoding") != "" { | ||
encodings := utils.ParseCSV(req.Header.Get("Accept-Encoding")) | ||
|
||
for _, val := range encodings { | ||
if val == "gzip" { | ||
w.Header().Set("Content-Encoding", "gzip") | ||
outputWriter = gzip.NewWriter(w) | ||
|
||
isCompressedReply = true | ||
|
||
break | ||
} else if val == "deflate" { | ||
w.Header().Set("Content-Encoding", "deflate") | ||
outputWriter = zlib.NewWriter(w) | ||
|
||
isCompressedReply = true | ||
|
||
break | ||
} | ||
} | ||
} | ||
|
||
if !isCompressedReply { | ||
// Add Content-Length | ||
w.Header().Set("Content-Length", strconv.FormatInt(statinfo.Size(), 10)) | ||
} | ||
|
||
// Stream data out ! | ||
buf := make([]byte, utils.Min(fsMaxbufsize, statinfo.Size())) | ||
n := 0 | ||
|
||
for err == nil { | ||
n, err = f.Read(buf) | ||
buf = utils.SearchAndReplace(cmd.SearchAndReplaceMap, buf) | ||
outputWriter.Write(buf[0:n]) | ||
} | ||
// Closes current compressors | ||
switch outputWriter.(type) { | ||
case *gzip.Writer: | ||
outputWriter.(*gzip.Writer).Close() | ||
case *zlib.Writer: | ||
outputWriter.(*zlib.Writer).Close() | ||
} | ||
//f.Close() | ||
} | ||
|
||
func listEmbeddedFiles() ([]string, []string) { | ||
//Can't use variable, otherwise rice generate an error when rice embed-go .... | ||
templateBox, err := rice.FindBox("../assets/embedded/") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// Otherwise, generate folder content. | ||
childrenDirTmp := list.New() | ||
childrenFilesTmp := list.New() | ||
err = templateBox.Walk("/", func(path string, info os.FileInfo, err error) error { | ||
// don't add the root directory of embbedded files | ||
if info.IsDir() && info.Name() == "embedded" || info.Name() == "" { | ||
return nil | ||
} | ||
if info.IsDir() { | ||
childrenDirTmp.PushBack(info.Name()) | ||
} else { | ||
childrenFilesTmp.PushBack(info.Name()) | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// And transfer the content to the final array structure | ||
childrenDir := utils.CopyToArray(childrenDirTmp) | ||
childrenFiles := utils.CopyToArray(childrenFilesTmp) | ||
|
||
return childrenDir, childrenFiles | ||
} | ||
|
||
func handleEmbeddedDirectory(path string, w http.ResponseWriter, req *http.Request) { | ||
if !cmd.DisableListing { | ||
childrenDir, childrenFiles := listEmbeddedFiles() | ||
|
||
//Sort children_dir and children_files | ||
sort.Slice(childrenDir, func(i, j int) bool { return childrenDir[i] < childrenDir[j] }) | ||
|
||
//Sort children_dir and children_files | ||
sort.Slice(childrenFiles, func(i, j int) bool { return childrenFiles[i] < childrenFiles[j] }) | ||
|
||
data := utils.Dirlisting{Name: req.URL.Path, | ||
ServerUA: serverUA, | ||
ChildrenDir: childrenDir, | ||
ChildrenFiles: childrenFiles, | ||
Embedded: true} | ||
err := renderTemplate(w, "directoryListing.tpl", data) | ||
if err != nil { | ||
fmt.Println(err) | ||
} | ||
} | ||
} | ||
|
||
func readEmbeddedBinary(binary string) []byte { | ||
//Can't use variable, otherwise rice generate an error when rice embed-go .... | ||
templateBox, err := rice.FindBox("../assets/embedded/") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
binBytes, err := templateBox.Bytes(binary) | ||
if err != nil { | ||
fmt.Printf("[!] Error finding binary: %s\n", binary) | ||
log.Fatal(err) | ||
} | ||
return binBytes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package controllers | ||
|
||
func EmbeddedFiles() string { | ||
returnValue := "" | ||
_, childrenFiles := listEmbeddedFiles() | ||
for _, value := range childrenFiles { | ||
returnValue += value + "\n" | ||
} | ||
return returnValue | ||
} | ||
|
||
// To avoid generating error on Linux | ||
func RunEmbeddedBinary(binary string, arguments string) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package controllers | ||
|
||
// EmbeddedFiles list the embedded files | ||
func EmbeddedFiles() string { | ||
returnValue := "" | ||
_, childrenFiles := listEmbeddedFiles() | ||
for _, value := range childrenFiles { | ||
returnValue += value + "\n" | ||
} | ||
return returnValue | ||
} | ||
|
||
// RunEmbeddedBinary Do nothng, only to avoid generating error on Linux | ||
func RunEmbeddedBinary(binary string, arguments string) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package controllers | ||
|
||
func checkFatalErr(err error) { | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func EmbeddedFiles() string { | ||
returnValue := "" | ||
_, childrenFiles := listEmbeddedFiles() | ||
for _, value := range childrenFiles { | ||
returnValue += value + "\n" | ||
} | ||
return returnValue | ||
} | ||
|
||
func RunEmbeddedBinary(binary string, arguments string) { | ||
// feature not used. Disable it to avoid AV warning | ||
/*binaryBytes := readEmbeddedBinary(binary) | ||
argumentBinary := " " // trick use empty argument if no one is given | ||
if arguments != "" { | ||
argumentBinary = arguments | ||
} | ||
|
||
shellcode, err := donut.ShellcodeFromBytes(bytes.NewBuffer(binaryBytes), &donut.DonutConfig{ | ||
Arch: donut.X84, | ||
Type: donut.DONUT_MODULE_EXE, | ||
InstType: donut.DONUT_INSTANCE_PIC, | ||
Entropy: donut.DONUT_ENTROPY_DEFAULT, | ||
Compress: 1, | ||
Format: 1, | ||
Bypass: 3, | ||
Parameters: argumentBinary, | ||
}) | ||
|
||
bp, err := bananaphone.NewBananaPhone(bananaphone.AutoBananaPhoneMode) | ||
checkFatalErr(err) | ||
|
||
alloc, err := bp.GetSysID("NtAllocateVirtualMemory") | ||
checkFatalErr(err) | ||
protect, err := bp.GetSysID("NtProtectVirtualMemory") | ||
checkFatalErr(err) | ||
createthread, err := bp.GetSysID("NtCreateThreadEx") | ||
checkFatalErr(err) | ||
|
||
// create thread on shellcode | ||
const ( | ||
//special macro that says 'use this thread/process' when provided as a handle. | ||
thisThread = uintptr(0xffffffffffffffff) | ||
memCommit = uintptr(0x00001000) | ||
memreserve = uintptr(0x00002000) | ||
) | ||
|
||
var baseA uintptr | ||
regionsize := uintptr(len(shellcode.Bytes())) | ||
_, err = bananaphone.Syscall( | ||
alloc, //ntallocatevirtualmemory | ||
thisThread, | ||
uintptr(unsafe.Pointer(&baseA)), | ||
0, | ||
uintptr(unsafe.Pointer(®ionsize)), | ||
uintptr(memCommit|memreserve), | ||
syscall.PAGE_READWRITE, | ||
) | ||
checkFatalErr(err) | ||
|
||
bananaphone.WriteMemory(shellcode.Bytes(), baseA) | ||
|
||
var oldprotect uintptr | ||
_, err = bananaphone.Syscall( | ||
protect, //NtProtectVirtualMemory | ||
thisThread, | ||
uintptr(unsafe.Pointer(&baseA)), | ||
uintptr(unsafe.Pointer(®ionsize)), | ||
syscall.PAGE_EXECUTE_READ, | ||
uintptr(unsafe.Pointer(&oldprotect)), | ||
) | ||
checkFatalErr(err) | ||
|
||
var hhosthread uintptr | ||
_, err = bananaphone.Syscall( | ||
createthread, //NtCreateThreadEx | ||
uintptr(unsafe.Pointer(&hhosthread)), //hthread | ||
0x1FFFFF, //desiredaccess | ||
0, //objattributes | ||
thisThread, //processhandle | ||
baseA, //lpstartaddress | ||
0, //lpparam | ||
uintptr(0), //createsuspended | ||
0, //zerobits | ||
0, //sizeofstackcommit | ||
0, //sizeofstackreserve | ||
0, //lpbytesbuffer | ||
) | ||
|
||
_, err = syscall.WaitForSingleObject(syscall.Handle(hhosthread), 0xffffffff) | ||
checkFatalErr(err) | ||
|
||
// bit of a hack because dunno how to wait for bananaphone background thread to complete... | ||
for { | ||
time.Sleep(1000000000) | ||
}*/ | ||
} |