Skip to content

Commit

Permalink
Fixes #33 handle ShiftJIS encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne0nd0g committed Dec 9, 2023
1 parent 8a421ca commit 4b8f253
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 4 deletions.
16 changes: 14 additions & 2 deletions commands/exec_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"os"
"os/exec"
"syscall"
"unicode/utf8"
"unsafe"

// X Packages
Expand All @@ -41,6 +42,7 @@ import (
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/api/kernel32"
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/api/ntdll"
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/pkg/pipes"
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/pkg/text"
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/pkg/tokens"
)

Expand Down Expand Up @@ -71,10 +73,20 @@ func executeCommandWithAttributes(name string, args []string, attr *syscall.SysP
stdout = fmt.Sprintf("Created %s process with an ID of %d\n", application, cmd.Process.Pid)
}

stdout += string(out)
// Convert the output to a string
if utf8.Valid(out) {
stdout += string(out)
} else {
s, e := text.DecodeString(out)
if e != nil {
stderr = fmt.Sprintf("%s\n", e)
} else {
stdout += s
}
}

if err != nil {
stderr = err.Error()
stderr += err.Error()
}

return stdout, stderr
Expand Down
12 changes: 12 additions & 0 deletions docs/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 2.2.0 - 2023-12-09

### Added

- New `os/windows/pkg/text` package to detect and handle non UTF-8 encoding
- Only handles ShiftJIS at this moment
- Will replace non UTF-8 characters with a � character

### Fixed

- [Issue 33](https://github.com/Ne0nd0g/merlin-agent/issues/33) - Added handling for ShiftJIS encoding

## 2.1.0 - 2023-11-27

### Changed
Expand Down
30 changes: 28 additions & 2 deletions os/windows/pkg/pipes/pipes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ package pipes
import (
// Standard
"fmt"
"unicode/utf8"

// X Packages
"golang.org/x/sys/windows"

// Internal
"github.com/Ne0nd0g/merlin-agent/v2/os/windows/pkg/text"
)

// CreateAnonymousPipes creates and returns a handle for STDIN, STDOUT, and STDERR
Expand Down Expand Up @@ -179,7 +183,18 @@ func ReadPipes(stdInRead, stdOutRead, stdErrRead windows.Handle) (stdin, stdout,
stdOutBuffer = append(stdOutBuffer, b)
}
}
stdout = string(stdOutBuffer)

// Convert the output to a string
if utf8.Valid(stdOutBuffer) {
stdout += string(stdOutBuffer)
} else {
s, e := text.DecodeString(stdOutBuffer)
if e != nil {
stderr = fmt.Sprintf("%s\n", e)
} else {
stdout += s
}
}
}

// STDERR
Expand All @@ -202,7 +217,18 @@ func ReadPipes(stdInRead, stdOutRead, stdErrRead windows.Handle) (stdin, stdout,
stdErrBuffer = append(stdErrBuffer, b)
}
}
stderr = string(stdErrBuffer)

// Convert the output to a string
if utf8.Valid(stdErrBuffer) {
stderr += string(stdErrBuffer)
} else {
s, e := text.DecodeString(stdErrBuffer)
if e != nil {
stderr = fmt.Sprintf("%s\n", e)
} else {
stderr += s
}
}
}

err = nil
Expand Down
59 changes: 59 additions & 0 deletions os/windows/pkg/text/text.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//go:build windows

/*
Merlin is a post-exploitation command and control framework.
This file is part of Merlin.
Copyright (C) 2023 Russel Van Tuyl
Merlin is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
Merlin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Merlin. If not, see <http://www.gnu.org/licenses/>.
*/

package text

import (
// Standard
"bytes"
"fmt"
"io"

// X Packages
"golang.org/x/sys/windows"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)

// DecodeString decodes a byte slice to a string using the current code page
func DecodeString(encoded []byte) (decoded string, err error) {
codePage := windows.GetACP()

switch codePage {
// 437 is the default code page for US English
case 437:
decoded = string(encoded)
return
// 932 is the default code page for Japanese
case 932:
t, e := io.ReadAll(transform.NewReader(bytes.NewReader(encoded), japanese.ShiftJIS.NewDecoder()))
if e != nil {
err = fmt.Errorf("os/windows/pkg/text.DecodeString(): there was an error decoding the string to ShiftJIS: %s", e)
return
}
decoded = string(t)
default:
decoded = fmt.Sprintf("\n***The output was not valid UTF-8 and there isn't a configured decoder for code page %d***\n\n", codePage)
decoded += string(bytes.ToValidUTF8(encoded, []byte("�")))
}
return
}

0 comments on commit 4b8f253

Please sign in to comment.