Skip to content

Conversation

@JoeyShapiro
Copy link

Describe the purpose of the pull request

The output of stdout is no longer flushed. This is not a problem normally, but I run evil-winrm using a script. After I updated from 3.7 to 3.9 I get the following problem.
The problem is that on the current release of evil-winrm it prints nothing for the command, something like:

Command output:
Command. error output:

This is because the output is not flushed and it exits before the content is flushed to stdout. I am unsure, but I am guessing it's because evil-winrm now uses readline.

This PR makes stdout flushed after every call so the output will now look like:

Command output:
Evil-WinRM shell v3.9

Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine

Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion

Info: Establishing connection to remote endpoint
hello

Info: Exiting with code 0

Command error output:

Please let me know if there are any problems. I am unfamiliar with ruby but this change fixes printing in my testing.

I won't post my exact code, but this sample go lang about covers it.

package main

import (
	"bytes"
	"fmt"
	"os/exec"
)

func main() {
	cmd := exec.Command("evil-winrm",
		"-u", "Administrator",
		"-p", "Password123!",
		"-i", "192.168.1.100",
		"-n",
	)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		fmt.Println("Error obtaining stdin pipe:", err)
		return
	}
	defer stdin.Close()

	var stdout, stderr bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	err = cmd.Start()
	if err != nil {
		fmt.Println("Error starting command:", err)
		return
	}

	_, err = stdin.Write([]byte("echo hello\nexit\n"))
	if err != nil {
		fmt.Println("Error writing to stdin:", err)
		return
	}

	err = cmd.Wait()
	if err != nil {
		fmt.Println("Error waiting for command:", err)
		return
	}

	fmt.Println("Command output:", stdout.String())
	fmt.Println("Command error output:", stderr.String())
}

@OscarAkaElvis
Copy link
Member

I'm not sure what you mean when you say "The output of stdout is no longer flushed". It works very well for me and for the rest. You don't provide data about what OS are you using, what is your ruby version or how can we reproduce it. How can we reproduce the problem? otherwise, there is no problem for us.

@JoeyShapiro
Copy link
Author

ok, sorry. didn't think about providing more info.

ruby version: ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
evil-winrm: 3.9
os: Ubuntu 22.04.5 LTS

when I run the golang program I get no output, like in the first example. This is because the output is not being flushed to stdout. This used to work fine with evil-winrm 3.7. It would write to stdout and have data before being exited by the golang program.

The output is not being written to stdout fast enough before evil-winrm is closed by golang. So in my golang program the output of the code is nothing, even though stuff did happen.

When you say it works for you and the rest, did you run the golang code, or just based on it working in general.
It should work fine in a terminal, but running the code in something faster might cause issues.

Again sorry for posting golang as a Proof of Concept, I can refactor it to ruby so it is more idiomatic.

@OscarAkaElvis
Copy link
Member

I don't get what has to do a golang program here... ¿? is it working as normal? how can I reproduce the problem?

@JoeyShapiro
Copy link
Author

I run evil-winrm using the golang program for an automation task. I updated evil-winrm to version 3.9 and now it no longer works in my automation. It has no output. The golang program I posted is an example that shows how evil-winrm prints nothing for me on version 3.9.

If you run the golang program (that runs evil-winrm) evil-winrm will print nothing to the terminal. This is not normal because it should print output. It should print the motd of evil-winrm and the hello from echo hello

@OscarAkaElvis
Copy link
Member

ok, but it is something that is not failing in evil-winrm. It is failing in your integration.

I need to check what implications have to add that $stdout.sync = true has and if we can add it safely or not. Checking posts like this now: https://stackoverflow.com/questions/29998728/what-stdout-sync-true-means

Need to discuss it internally with the team.

@JoeyShapiro
Copy link
Author

well, it is a problem with evil-winrm. it is not writing to the stdout file descriptor often enough. This has changed because of the readline dependency. It is now buffering output more before it does a flush. This means that if the program is exited while it still hasn't flushed everything, that output will be lost.

This is not a problem though if you are just writing to the terminal, A terminal will keep the stdout file descriptor open as long as the terminal program is open. But when you are writing the output to a variable of a script using a subprocess, it will close the fd's once the execution finished.

using sync just makes it flush the output after every write, which is what is used to do before using readline.

@OscarAkaElvis
Copy link
Member

Ok, anyway, before accepting this let's check if the problem solves by itself after migrating from readline to reline. We are working on this PR about that: #79

Some files are yet pending to be modified. I'm in contact with the author of the PR. As soon as we have that PR ready you could test if the problem is still there using reline instead of readline. And in the case that it is not solved we can think about this. Please, I ask you patience for this. Thank you.

@JoeyShapiro
Copy link
Author

no problem, and I understand. I will continue to do some testing and see what more I can find out.

Another simple solution would be to flush stdout in customExit. I am willing to work on finding a good solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants