AllocConsole issue when manually mapping PE + fetching output - c

I am working on a project that involves manually mapping and executing a PE inside of the project process. The main project whose code I am using as a basis for this can be found here: https://github.com/aaaddress1/RunPE-In-Memory/blob/master/RunPE-In-Memory/RunPEinMemory/RunPEinMemory.cpp
The project above compiles and runs fine. During the mapping of the PE that this project is used to run, it will hook the API's related to processing commandline arguments, allowing the user to manually specify arguments to the mapped PE rather than the mapped PE trying to use the arguments provided to RunPEinMemory.exe (since this is all happening inside the same process).
The project I am working towards differs from this base project in that:
I (have successfully already) hooked API's like ExitProcess and exit() and redirect them to ExitThread to prevent the mapped PE ending the RunPEinMemory.exe process
I need to eventually send the output from whatever the mapped PE is elsewhere. To do this, I am redirecting stdout/stderr to anonymous pipes that I later read from in RunPEinMemory prior to running the mapped PE.
I am struggling on the second account.
My project needs to be compiled as a GUI app (subsystem=windows) rather than a Console app (subsystem=console).
The issue arises in that in order to manipulate the stdin/stdout/stderr handles, a console needs to be attached to the process. There are numerous StackOverflow posts about this topic that cover using AllocConsole and then reopening the std handles in order to redirect output to the new console (or elsewhere). A prominent post on this matter can be seen here: Redirecting stdout in win32 does not redirect stdout
I have implemented this code and can successfully manually map/run powershell.exe (passing 'gci' as an argument for example). The stdout/stderr is redirected to anonymous pipes and then read, after which is it written out to a file (for testing purposes currently). This successful test is done with my project.exe compiled for subsystem=windows as intended.
This falls apart when I try to do the same thing with cmd.exe (passing '/c dir' as arguments). I this case, the output fails to make it to stdout or stderr, and there are no bytes to read from the anonymous pipes.
Now when I instead compile this project as a Console program (subsystem=console) and I remove the AllocConsole call (so using the console that Windows allocates for me), the program succeeds. I notice that the cmd.exe output goes to stderr, rather than stdout. But regardless, I am able to successfully redirect that output to one of the anonymous pipes, read it, and then write it out to file.
This leads me to believe that I am missing something when it comes to calling AllocConsole, some follow-on step to fully set up the environment so that certain programs can successfully send output to stdout/stderr. This post mentions a bit about cmd.exe using win32Api's to write to stdout/stderr (as opposed to the other ways to do so as mentioned in a previous link), so I'm wondering if I'm not successfully setting something up when manually allocating a console: https://stackoverflow.com/a/66689266/18776214
The relevant code is as such:
//Allocate console. This line is the one that gets commented out between console/windows test
BOOL suc = AllocConsole();
//Reopen streams after allocating console + disable buffering
FILE* fout;
FILE* ferr;
freopen_s(&fout, "CONOUT$", "r+", stdout);
freopen_s(&ferr, "CONOUT$", "r+", stderr);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
//Open anonymous pipes for stdout and stderr
HANDLE hreadout;
HANDLE hwriteout;
HANDLE hreaderr;
HANDLE hwriteerr;
SECURITY_ATTRIBUTES sao = { sizeof(sao),NULL,TRUE };
SECURITY_ATTRIBUTES sae = { sizeof(sae),NULL,TRUE };
CreatePipe(&hreadout, &hwriteout, &sao, 0);
CreatePipe(&hreaderr, &hwriteerr, &sae, 0);
printf("CreatePipe last error: %d\n", GetLastError());
printf("hreadout is: %p\n", hreadout);
printf("hwriteout is: %p\n", hwriteout);
printf("hreaderr is: %p\n", hreaderr);
printf("hwriterr is: %p\n", hwriteerr);
//Set std_output_handle and std_error_handle to the write-ends of anonymous pipes
SetStdHandle(STD_OUTPUT_HANDLE, hwriteout);
SetStdHandle(STD_ERROR_HANDLE, hwriteerr);
//Convert write-ends of anonymous pipes to file descriptors and use _dup2 to set stdout/stderr to anonymous pipes
int fo = _open_osfhandle((intptr_t)(hwriteout), _O_TEXT);
int fe = _open_osfhandle((intptr_t)(hwriteerr), _O_TEXT);
int res = _dup2(fo, _fileno(fout)); //_fileno(fout)
int res2 = _dup2(fe, _fileno(ferr)); //_fileno(ferr)
printf("fo is: %d\n", fo);
printf("fe is: %d\n", fe);
printf("res is: %d\n", res);
printf("res1 is: %d\n", res2);
//Execute manually mapped PE now that stdout/stderr have been redirected
Sleep(2000);
HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)retAddr, 0, 0, 0);
WaitForSingleObject(hThread, 5000);
Sleep(2000);
//Reopen streams again to set stdout/stderr back to console
freopen_s(&fout, "CONOUT$", "r+", stdout);
freopen_s(&ferr, "CONOUT$", "r+", stderr);
//check how much data there is to be read from pipe + allocate buffer
DWORD cbBytesAvailOut;
PeekNamedPipe(hreadout, NULL, NULL, NULL, &cbBytesAvailOut, NULL);
printf("PeekNamedPipe last error: %d\n", GetLastError());
printf("stdout bytes avail is: %d\n", cbBytesAvailOut);
DWORD cbBytesAvailErr;
PeekNamedPipe(hreaderr, NULL, NULL, NULL, &cbBytesAvailErr, NULL);
printf("PeekNamedPipe last error: %d\n", GetLastError());
printf("stderr bytes avail is: %d\n", cbBytesAvailErr);
//Allocate buffer based on number of bytes available to read
wchar_t* pipeBuf = calloc(cbBytesAvailErr + 2, sizeof(wchar_t));
char* convertBuf;
Sleep(2000);
//Currently only reading from a single pipe, edit this block as needed to get data when it exists
//Read from pipe
DWORD bytesRead;
printf("right before readfile!\n");
BOOL fSuccess = ReadFile(hreaderr, pipeBuf, (cbBytesAvailErr + 2) * sizeof(wchar_t), &bytesRead, NULL);
printf("fSuccess is: %d\n", fSuccess);
printf("ReadFile last error: %d\n", GetLastError());
printf("wide string: %ls\n", pipeBuf);
printf("normal string: %s\n", pipeBuf);
printf("bytesread is: %d\n", bytesRead);
//Write buffer out to disk
Sleep(2000);
char* filename = "C:\\Users\\User\\Inline-Execute-PE-main\\Inline-Execute-PE\\x64\\Release\\outfile.txt";
DWORD byteswritten;
HANDLE hFileOut = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hFileOut, pipeBuf, bytesRead, &byteswritten, NULL);
So the two scenarios are this:
Compile as console app with the above code with the first line (AllocConsole()) commented out, everything else the same, manually mapping cmd.exe with commandline args "cmd.exe /c dir" -> works, cmd.exe output is sent to stderr pipe and can be read
Compile as windows app with the above code, using AllocConsole(), manually mapping cmd.exe with commandline args "cmd.exe /c dir" -> fails, cmd.exe output is not captured
Again using powershell.exe works just fine. I'm thinking because maybe it uses a different means to write to stdout/stderr than cmd.exe does.
Does anyone have any ideas?
Edit: As an update, I tried putting the AllocConsole() call BEFORE the PE is mapped into memory by the RunPEinMemory project. This results in the output from cmd.exe displaying to the outputted console, however it isn't being redirected to the pipe still. That is progress at least, but it seems like the stdout/stderr from cmd.exe still isn't linked or connected to the overall process for some reason

I was finally able to resolve this problem.
The issue appears to be WHEN I was calling AllocConsole and redirecting the stdout/stderr.
Previously the order was:
Manually map PE
Fix IAT of PE
AllocConsole
Redirect stdout/stderr using freopen_s and SetStdHandle
Transform Win32 handles to C std handles using open_osfhandle and _dup2
CreateThread to run PE
The working order was:
AllocConsole
Redirect stdout/stderr using freopen_s and SetStdHandle
Manually map PE
Fix IAT of PE
Transform Win32 handles to C std handles using open_osfhandle and _dup2
CreateThread to run PE
So it looks like when the IAT of the mapped PE gets fixed/setup the console needs to already be there and properly set up first.

Related

Redirecting console (or stdout) to named pipe no longer works when compiling with Visual Studio 2015

I have a scripting engine which redirects its stdout to a named pipe for debugging purposes. The code below has been working since Visual Studio 6, but no longer seems to work at all when compiling with VS2015. No errors are thrown, but the output continues to be written to the console instead of the named pipe. When I compile this application in VS2012, it works as expected.
hNamedPipe is the pipe I want to redirect console text to.
int hCrt = _open_osfhandle((intptr_t)hNamedPipe, _O_TEXT);
FILE *hf = _fdopen(hCrt, "w");
*stdout = *hf;
setvbuf(stdout, NULL, _IONBF, 0);
How might I redirect stdio to a named pipe when compiling with the Visual C++ v14 platform tool-set?
Thanks to James McNellis I was able to arrive at a solution:
This is by design. FILE is an opaque data type; you are not allowed to
dereference a FILE as you have done in your code.
This is the code which ultimately worked for me:
void main()
{
HANDLE hNamedPipe = Create_Some_Named_Pipe();
RedirectIO(stdout, hNamedPipe);
printf("Hello World."); //This arrived at the listening named pipe.
}
void RedirectIO(FILE *hFrom, HANDLE hTo)
{
int fd = _open_osfhandle((intptr_t)hTo, _O_WRONLY | _O_TEXT);
_dup2(fd, _fileno(hFrom));
setvbuf(hFrom, NULL, _IONBF, 0); //Disable buffering.
}

Difference between perror() and printf()

I had read that both perror() and printf() write to the terminal screen. But perror() writes to stderr while printf() writes to stdout. So, to print errors why is perror() used when printf() can do it.
printf() cannot write to stderr. fprintf() can. perror() always does.
There is no requirement that writing to either stdout or stderr writes to a terminal screen - that is up to the implementation (since not all systems even have a terminal). There is also no requirement that writing to stdout and stderr results in writing to the same device (e.g. one can be redirected to a file, while the other is redirected to a pipe).
perror() will be implemented with built-in knowledge of the meanings of error codes, represented by the static errno, which is used by various functions in the standard library to report error conditions. The meanings of particular values are implementation defined (i.e. they vary between compilers and libraries).
Because there could be configurations where you want stderr printed to the console but the other output not printed at all (for example, to remove verbosity). In other cases you may need to redirect stderr to write to a file, this is useful when you are in production and that file can be used to understand what went wrong on a remote computer you can't debug yourself.
In general, you gain more control on how console outputs are treated depending on their type.
See this answer to understand how you can do stream redirection in code.
Or, see this link on how you can force stream redirection to file or ignore a stream on an already compiled program (while invoking it in bash)
In addition to other answers, you might use fprintf(3) on stderr and errno(3) with strerror(3) like
fprintf(stderr, "something wrong: %s\n", strerror(errno));
On GNU libc systems (many Linux systems), you could use instead %m conversion specifier instead:
fprintf(stderr, "something wrong: %m\n");
You conventionally should output error messages to stderr (see stderr(3)); see also syslog(3) to use system logging.
Don't forget to end the format string with \n since stderr is often line buffered (but sometimes not) or else use fflush(3)
For example, you might want to show both the error, the filename and the current directory on fopen failure:
char* filename = somefilepath();
assert (filename != NULL);
FILE* f = fopen(filename, "r");
if (!f) {
int e = errno; // keep errno, it could be later overwritten
if (filename[0] == '/') /// absolute path
fprintf(stderr, "failed to open %s : %s\n", filename, strerror(e));
else { // we also try to show the current directory since relative path
char dirbuf[128];
memset (dirbuf, 0, sizeof(dirbuf));
if (getcwd(dirbuf, sizeof(dirbuf)-1))
fprintf(stderr, "failed to open %s in %s : %s\n",
filename, dirbuf, sterror(e));
else // unlikely case when getcwd failed so errno overwritten
fprintf(stderr, "failed to open %s here : %s\n",
filename, sterror(e));
};
exit(EXIT_FAILURE); // in all cases when fopen failed
}
Remember that errno could be overwritten by many failures (so we store it in e, in the unlikely case that getcwd fails and overwrite errno).
If your program is a deamon (e.g. has called daemon(3)) you'll better use system log (i.e. call openlog(3) after calling daemon) since daemon can redirect stderr to /dev/null
There are three standard stream stdin stdout stderr. You can refer to know what is important of different stream.
For error messages and diagnostics ,stderr is used , to print on stderr
Perror is used. printf can not do that. Perror is also used to handle errors from system call
fd = open (pathname, flags, mode);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
You can refer more about this in book The linux programming interface
void perror(const char *s)
Perror prints message in following sequence :
argument of s , a colon , a space , a short message concerning error whose error code currently in errnoand newline
In standard C if s is null pointer than only message will be printed . other things will be ignored
To understand more you can also refer page 332 of The complete reference C
A big advantage of using perror():
It is sometimes very useful to redirect stdout into /dev/null to only have access to errors since the verbosity of stdout might hide the errors that we need to fix.
perror
The general purpose of the function is to halt the execution process due to an error. The error message produced by perror is platform-depend. You can also print your own error message also.
printf
The general purpose of the function is to print message user defined and continue the execution.

C: setup pseudoterminal and open with xterm

The following simplified piece of code is executed by a thread in the background. The thread runs until he is told to exit (by user input).
In the code below I have removed some error checking for better readability. Even with error checking the code works well and both the master and the slave are created and/or opened.
...
int master, slave;
char *slavename;
char *cc;
master = posix_openpt(O_RDWR);
grantpt(master);
unlockpt(master);
slavename = ptsname(master);
slave = open(slavename, O_RDWR);
printf("master: %d\n",master);
printf("slavename: %s\n",slavename);
On my machine the output is the following:
master: 3
slavename: /dev/pts/4
So I thought that opening an xterm with the command xterm -S4/3 (4 = pt-slave, 3 = pt-master) while my program is running should open a new xterm window for the created pseudoterminal. But xterm just starts running without giving an error or any further informations but does not open a window at all. Any suggestions on that?
EDIT:
Now with Wumpus Q. Wumbley's help xterm starts normally, but I can't redirect any output to it. I tried:
dup2(slave, 1);
dup2(slave, 2);
printf("Some test message\n");
and opening the slave with fopen and then using fprinf. Both didn't work.
The xterm process needs to get access to the file descriptor somehow. The intended usage of this feature is probably to launch xterm as a child process of the one that created the pty. There are other ways, though. You could use SCM_RIGHTS file descriptor passing (pretty complicated) or, if you have a Linux-style /proc filesystem try this:
xterm -S4/3 3<>/proc/$PID_OF_YOUR_OTHER_PROGRAM/fd/3
'
You've probably seen shell redirection operators before: < for stdin, > for stdout, 2> for stderr (file descriptor 2). Maybe you've also seen other file descriptors being opend for input or output with things like 3<inputfile 4>outputfile. Well the 3<> operator here is another one. It opens file descriptor 3 in read/write mode. And /proc/PID/fd/NUM is a convenient way to access files opened by another process.
I don't know about the rest of the question. I haven't tried to use this mode of xterm before.
OK, the trick with /proc was a bad idea. It's equivalent to a fresh open of /dev/ptmx, creating a new unrelated pty.
You're going to have to make the xterm a child of your pty-creating program.
Here's the test program I used to explore the feature. It's sloppy but it revealed some interesting things. One interesting thing is that xterm writes its window ID to the pty master after successful initialization. This is something you'll need to deal with. It appears as a line of input on the tty before the actual user input begins.
Another interesting thing is that xterm (the version in Debian at least) crashes if you use -S/dev/pts/2/3 in spite of that being specifically mentioned in the man page as an allowed format.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
int master;
char *slavename, window[64], buf[64];
FILE *slave;
master = posix_openpt(O_RDWR);
grantpt(master);
unlockpt(master);
slavename = ptsname(master);
printf("master: %d\n", master);
printf("slavename: %s\n", slavename);
snprintf(buf, sizeof buf, "-S%s/%d", strrchr(slavename,'/')+1, master);
if(!fork()) {
execlp("xterm", "xterm", buf, (char *)0);
_exit(1);
}
slave = fopen(slavename, "r+");
fgets(window, sizeof window, slave);
printf("window: %s\n", window);
fputs("say something: ", slave);
fgets(buf, sizeof buf, slave);
fprintf(slave, "you said %s\nexiting in 3 seconds...\n", buf);
sleep(3);
return 0;
}

Redirecting stdout of a process

I am writing a toy version of SSH in C, so I need to redirect stdin, stdout and stderr of the server shell to the client shell (by using pipes and sockets). Right now I have redirected only stdout. If I send commands like ls, netstat, etc there are no problems, the client receives the right output.
But if I write a C program wich, for example, asks for an int n and prints the numbers between 1 and n, and call it through the client I get this behavior: the client doesn't receive the string with the request of n, but if I tape n on the server shell the client receives the request string and the numbers.
I have tried the same thing leaving stdout on the server shell and in this case it works correctly. I have tried to use fflush, fsync and setvbuf without solve it.
Another strange behavior is: if I call through the client the program httrack without redirecting stdout, the server shell shows the normal wizard wich asks for project name, url, etc.
But If I redirect stdout the client doesn't receive the wizard output, instead it receives the httrack help page.
This is the code that performs redirection. As you can see I used both system and execlp call, but the behavior is the same.
pipe(pipefd);
if(fork() > 0)
{
close(pipefd[1]);
*_result = fdopen(pipefd[0], "r");
return 0;
}
else
{
close(pipefd[0]);
close(1);
dup(pipefd[1]);
system(buf);
//execlp(buf, buf, NULL);
exit(0);
}
EDIT:
After this I call this function that reads the stream associated to the read end of the pipe and puts it on the socket. The other parameters are used by AES and log file.
sock_send encrypt the buffer and write it to the socket through sock_write. sock_write(_wsock, NULL, 0) only signals the end of the output. Anyway as I have pointed out before, the output of commands like ls etc. is ok.
void write_result(int _wsock, aes_context *_enc_ctx, unsigned char *_iv, FILE *_result, char *_ip_addr)
{
unsigned char buf[BUF_SIZE];
char lstr[MAX_LOG_LEN];
while(fgets(buf, BUF_SIZE * sizeof(char), _result) != NULL)
{
//li scrivo sulla socket
if(sock_send(_wsock, _enc_ctx, buf, strlen(buf) + 1, _iv) == -1)
{
sprintf(lstr, WRITE_SOCK_ERR, _ip_addr);
log_str(lstr);
close_connection(_wsock, _ip_addr);
}
}
sock_write(_wsock, NULL, 0);
fclose(_result);
}

How can I call notepad.exe from a C program?

i have written a time table program in c
#include<stdio.h>
#include<conio.h>
void main()
{
int i=0;
int selection;
char day[20];
char sub1[20];
char sub2[20];
char sub3[20];
FILE *fp;
fp=fopen("aa.txt","w");
textcolor(5);
textbackground(3);
clrscr();
while(i<3)
{
printf("Enter the day ");
scanf("%s",day);
printf("Enter the period 12.30-1:30 ");
scanf("%s",sub1);
printf("Enter the period 1.35-2.40 ");
scanf("%s",sub2);
printf("Enter the period 2.45-3.50 ");
scanf("%s",sub3);
fprintf(fp,"\n %s TIMETABLE IS AS FOLLOWS\n",day);
fprintf(fp,"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
fprintf(fp,"|~~~~~~~~~|~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~|~~~~~~~~~~|\n");
fprintf(fp,"| TIME | 12.30-1.30 | 1.35-2.40 |2.45-3.50 |\n");
fprintf(fp,"|~~~~~~~~~|~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~|~~~~~~~~~~|\n");
fprintf(fp,"| SUBJECT * %s * %s * %s|\n",sub1,sub2,sub3);
fprintf(fp,"|~~~~~~~~~|~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~|~~~~~~~~~~|\n");
i++;
}
printf(" Time table has been Created in the File aa.txt successfully");
getch();
}
when i finish the timetable . the time table is created in a.txt file. i want that file to be opened and show me automatically in a notepad. how to program that in c?
Use
system("notepad.exe aa.txt");
Dani already described the easier way (using system), so I'll just describe the other (more complicated but also more flexible) way to do it using the Windows API. Browsing the API (Overview -> System Services -> Processes and Threads), there's a small example on how to create a process using the CreateProcess() function. In your case:
CreateProcess("notepad.exe", // Name of program to execute
"aa.txt", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi); // Pointer to PROCESS_INFORMATION structure
And then wait for the Notepad process to exit, as described in the example.
Third way: use the ShellExecute shell function telling to the shell to "just open the file" with the default editor:
#include <windows.h>
#include <Shellapi.h>
// ...
if(ShellExecute(
NULL, // No parent window for error message boxes/...
"open", // Shell action ("verb") to be performed on the file (as opposed to "print", "explore", ...)
"aa.txt", // File to be opened
NULL, // Command-line parameters - not used when opening documents
NULL, // Working directory - the current one is used by default
SW_SHOW // State of the window of the application being launched - SW_SHOW is the default
)<=(HINSTANCE)32 // If ShellExecute returns a value <=32 it means that an error has occurred
)
{
puts("Cannot open aa.txt with the default editor - ShellExecute failed.");
}
This will open aa.txt with the default editor for txt files.
In my opinion, this is the best solution:
it respects the user's choice for the editor (unlike CreateProcess, which just opens notepad.exe); if I set PSPad as the default editor for txt files, it will pop up PSPad and not notepad.
it doesn't have problems with search paths for the editor (where is notepad.exe?)
its behavior is fully defined, unlike the system function, which relies on command.com/cmd.exe, which have subtle differences between Windows versions and don't give you any documented/easy way to check if the operation succeeded;
it doesn't give you any "false feeling of portability" like the system, that will happily compile on a Linux machine but will simply not work at runtime.

Resources