masterzen/winrm

Use proper UTF-8 to UTF-16 conversion?

rgl opened this issue · 5 comments

rgl commented

Can

winrm/powershell.go

Lines 10 to 23 in 1d17eaf

func Powershell(psCmd string) string {
// 2 byte chars to make PowerShell happy
wideCmd := ""
for _, b := range []byte(psCmd) {
wideCmd += string(b) + "\x00"
}
// Base64 encode the command
input := []uint8(wideCmd)
encodedCmd := base64.StdEncoding.EncodeToString(input)
// Create the powershell.exe command line to execute the script
return fmt.Sprintf("powershell.exe -EncodedCommand %s", encodedCmd)
}
be changed to use a proper UTF-8 to UTF-16 (the native windows encoding) conversion?

@rgl,

I'm not really versed into Windows encoding (nor UTF-16). From what I understand this code is building a pure UCS-2 (wide char) string with the topmost byte being always 0. This will indeed fail with any character > 127, which is unfortunate.

I think this can be fixed with this:

 wideCmd := utf16.Encode([]rune(psCmd))

Hopefully the result will be in proper endian for the receiving machine.

Would you mind testing this, as I'm very illiterate about everything related to powershell ?

rgl commented

Windows uses UTF-16LE and utf16.Encode is UTF-16BE. I will submit PR soon.

rgl commented

Oh an I was mistaken, utf16.Encode is really UTF-16LE! We just need to convert the result into a []byte.

@rgl I'm lost, your PR implements a BE->LE conversion, but your last comment here seems to imply it wasn't needed. Can you elaborate?

rgl commented

Sorry for the confusion... the PR does not really convert from BE to LE.

Let me clarify:

  1. utf16.Encode converts from string to a []uint16 encoded as UTF-16LE.
  2. encodeUtf16Le converts from []uint16 to a []byte encoded as UTF-16LE, making the entire conversion from string to []byte encoded as UTF-16LE.