Molte volte può essere necessario reindirizzare l'output di applicazioni dalla normale finestra console su un nostro buffer
da trattare e stampare a schermo magari in una finestra (ad esempio per realizzare delle GUI per programmi a linea di comando).
Questa libreria permette appunto di fare ciò, reindirizzando l'ouput del processo aperto con CreateProcess() su una nostra pipe che andremo
a leggere con ReadFile()
char * Dos2Win(char *process,char *param) { DWORD WaitReason; DWORD BytesRead; char *Buffer,*Cmd,temp[BUFSIZE]; HANDLE hReadPipe, hWritePipe; STARTUPINFO siStartupInfo; PROCESS_INFORMATION piProcessInfo; SECURITY_ATTRIBUTES sa; // Attibruti di sicurezza della pipe sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; // (¹) sa.lpSecurityDescriptor = NULL; memset(&siStartupInfo, 0, sizeof(siStartupInfo)); memset(&piProcessInfo, 0, sizeof(piProcessInfo)); // Creazione della pipe if (!CreatePipe (&hReadPipe, &hWritePipe, &sa, 0)) { printf("Errore CreatePipe()\n"); return NULL; } // Alloco spazio per contenere la riposta Buffer = (char*)malloc((BUFSIZE + 1)*sizeof(char)); // Alloco spazio per 'eseguibile.exe + ' ' + 'parametri' + '\0' Cmd = (char*)malloc((strlen(process)+strlen(param)+2)*sizeof(char)); sprintf(Cmd,"%s %s",process,param); siStartupInfo.cb = sizeof(siStartupInfo); siStartupInfo.dwFlags = STARTF_USESTDHANDLES // (²) | STARTF_USESHOWWINDOW; siStartupInfo.wShowWindow = SW_HIDE; // Redirigo lo standard input del processo sulla mia pipe siStartupInfo.hStdInput = hReadPipe; // Redirigo lo standard output del processo sulla mia pipe siStartupInfo.hStdOutput = hWritePipe; // Redirigo lo standard error del processo sulla mia pipe siStartupInfo.hStdError = hWritePipe; // Apro il processo if (!CreateProcess(NULL, Cmd, &sa, &sa, TRUE, // (³) 0, NULL, NULL, &siStartupInfo, &piProcessInfo)) { printf("Errore CreateProcess()\n"); return NULL; } // Attendo lesecuzione del comando WaitReason = WaitForSingleObject(piProcessInfo.hProcess,INFINITE); // Pulisco il buffer memset(Buffer, 0, sizeof(Buffer)); // Leggo la pipe do { BytesRead = 0; // Leggiamo "BUFSIZE" bytes dalla pipe ReadFile(hReadPipe, temp, BUFSIZE, &BytesRead, NULL); // Chiudo la stringa alla dimensione letta temp[BytesRead] = '\0'; //Concateno strcat(Buffer,temp); // Convertiamo i caratteri da DOS ad ANSI OemToAnsi(Buffer,Buffer); } while (BytesRead > BUFSIZE); free(Cmd); // Rilascio il puntatore // Chiudo la pipe CloseHandle(hReadPipe); CloseHandle(hWritePipe); // Chiuso il processo CloseHandle(piProcessInfo.hProcess); CloseHandle(piProcessInfo.hThread); // Ritorno l'output letto e sistemato return Buffer; }
|
Nota (¹) (²) (³):
Ho segnato questi richiami in 3 punti importanti del codice: sa.bInheritHandle = TRUE; // (¹)
|
siStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; // (²)
|
CreateProcess(..., ... ..., ..., TRUE, // (³)
|
Queste 3 impostazioni sono particolarmenti fondamentali per il corretto funzionamento del codice.
Come è riportato sulla documentazione ufficiale:
   Struttura SECURITY_ATTRIBUTES
bInheritHandle: A Boolean value that specifies whether the returned handle is inherited when a new process is created. If this member is TRUE, the new process inherits the handle.
Struttura STARTUPINFO
STARTF_USESTDHANDLES: The hStdInput, hStdOutput, and hStdError members are valid.
If this flag is specified when calling one of the process creation functions, the handles must be inheritable and the function's bInheritHandles parameter must be set to TRUE. For more information, see Handle Inheritance.
API CreateProcess()
bInheritHandles: If this parameter TRUE, each inheritable handle in the calling process is inherited by the new process. If the parameter is FALSE, the handles are not inherited. Note that inherited handles have the same value and access rights as the original handles.
Occorre permettere l'ereditarietà degli handle attraverso la pipe(¹), validare i membri hStdInput, hStdOutput, e hStdError della
struttura STARTUPINFO(²) e impostare anche il paramentro bInheritHandles della CreateProcess()(³) per avere l'effettivo reindirizzamento dell'output sul nostro canale.
#include <stdio.h> #include "Dos2Win.h" int main() { char *out; printf("Esecuzione comando \"dir\"\n"); out = Dos2Win("cmd.exe","/c dir"); free(out); printf("Esecuzione comando \"nslookup\"\n"); out = Dos2Win("nslookup.exe","www.suondmao.altervista.org"); free(out); return 0; }
|
 | | Downloads: 422 | | | |  | | Downloads: 376 | | | |  | | Downloads: 273 | | | |
Si può utilizzare questo codice come base per realizzare un completo programma di gestione di altri processi, reindirizzando
sia l'output (come fatto qui) che l'input del secondo processo su due pipe da comandare a piacimento.
Questa tecnica veniva utilizzata spesso in passato per associare l'I/O del cmd.exe ad un socket creato per realizzare backdoors.
|