1 LCX简介

lcx是一款强大的内网端口转发工具,用于将内网主机开放的内部端口映射到外网主机(有公网IP)任意端口。它是一款命令行工具,当然也可以在有权限的webshell下执行,正因如此lcx常被认为是一款黑客入侵工具,lcx在内网入侵渗透中起着重要的角色。lcx进行端口转发的原理就是使不同端口之间形成一个回路。它常用于外网连接内网3389等端口。

2 LCX实现思路

2.1 基于命令的LCX

在windows和linux 中都存在对于端口的转发命令,人们习惯于称呼为映射,英文为DNAT(Destination Network Address Translation),官方名称为目的地址转换,这种方式在防火墙和路由器中比较常见。

2.1.1 windows 目的地址转换命令简介

Windows下使用netsh命令,来进行目的地址转换。netsh(Network Shell) 是一个windows系统本身提供的功能强大的网络配置命令行工具。它允许从本地或远程显示或修改当前正在运行的计算机的网络配置。Netsh 命令的强大,目的地址映射只是其中小部分功能。如此强大的命令如何使用呢?

命令

含义

netsh interface portproxy add v4tov4 listenaddress=192.168.1.8 listenport=14941 connectaddress=192.168.1.118  connectport=1494

在IPV4下将监听本地IP 192.168.1.8:14941,接受到的数据转发给192.168.1.118:1494。

netsh interface portproxy delete v4tov4 listenaddress=192.168.1.8  listenport=33891

在IPV4下删除监听本地IP 192.168.1.8:33891

netsh interface portproxy show  v4tov4

查看在IPV4下配置的端口转发的策略

2.1.2 linux 目的地址转换命令简介

Linux下使用iptables命令,来进行目的地址转换。在默认情况下,linux会禁用此类功能,需要手动开启。iptables是Linux 内核集成的 IP 信息包过滤系统,也就是人们常说的LINUX自带防火墙,经常被用于配置ACL(Access Control List)访问控制列表。iptables在不同的LINUX版本中存在不同的名称。2.0.X内核:ipfwadm,2.2.X内核:ipchains,2.4.X内核:iptables。目前linux版本基本为2.4.x以上,低版本的linux比较少见,下面讲解的命令,在2.4.x以上的内核版本linux中有效。

 开启目的地址转发功能

临时修改法: echo 1 >/proc/sys/net/ipv4/ip_forward

永久修改法: vi /etc/sysctl.conf,net.ipv4.ip_forward = 1找到并修改值为1,sysctl –p(使之立即生效)

假设用户访问172.16.4.247:728时我想让它转发到172.16.4.97:80:

# iptables -t nat -A PREROUTING  -p tcp -d 113.108.110.61 –dport 728 -j DNAT –to-destination 172.16.4.97:80

# iptables -t nat -A POSTROUTING -p tcp -s 172.16.4.97 –sport 80 -j SNAT –to-source 172.16.4.247

# service iptables save(将当前规则保存到 /etc/sysconfig/iptables)

本机间不同的端口转发:

iptables -t nat -A PREROUTING -p tcp –dport 729 -j REDIRECT –to-ports 80

service iptables save

service iptables restart

2.2 自实现LCX

基于命令的LCX存在无法绕过杀毒软件的拦截,并且需要管理员权限等问题。所以大多数LCX是使用自实现目的地址转换的方式编写的工具。简单说下目的地址转换的原理。

目的地址转换的基本工作原理是当公网主机同一IP包发送至存在目的地址转换策略的主机端口时,将IP包中的目的地址以及端口进行替换,并且代发送给替换后的地址和端口。

采用PYTHON编写LCX工具,工具的使用效果感觉上是非常不错的,但是ptyhon程序打包成exe的体积相对比较庞大。笔者推荐使用asyncore 模块,Pythonasyncore模块提供了以异步的方式写入套接字服务的客户端和服务器的基础结构,使用比较方便。这个模块是一个以时间驱动的异步I/O,与C++的事件选择模型相似。每当发生写、读事件会交由我们重写的事件函数进行处理。下面开始编写自实现的LCX

 

1、第一步需要先定义Forwarder

class PortForwarder(asyncore.dispatcher):#监听本地
    def __init__(self, ip, port, remoteip, remoteport, backlog=5):
        asyncore.dispatcher.__init__(self)
        self.remoteip = remoteip
        self.remoteport = remoteport
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)#创建一个套接字对象
        self.set_reuse_addr()#设置地址端口可重用
        self.bind((ip, port))#绑定本地ip与端口
        self.listen(backlog)#开始监听
 
    def handle_accept(self):#处理接受
        conn, addr = self.accept()#等待接受
        print "Connected to:", addr
        Sender(Receiver(conn), self.remoteip, self.remoteport)

 

2、第二步调用Forwarder,并且执行asyncore.loop(用于循环监听网络事件):

PortForwarder(local_host, local_port, remote_host, remote_port)
asyncore.loop()

 

3、需要接收本地的请求,发给远程主机:

class Receiver(asyncore.dispatcher):#接受本地请求数据,发送给远程主机
    def __init__(self, conn):
        asyncore.dispatcher.__init__(self, conn)
        #self被初始化为该连接客户端socket
        #getpeername函数用于获取与某个套接字关联的外地协议地址
        self.from_remote_buffer = ''#保存来自远程主机数据
        self.to_remote_buffer = ''    #保存本地请求数据
        self.sender = None
 
    def handle_connect(self):
        pass
 
    def handle_read(self):#接受本地请求
        read = self.recv(BUFSIZE)
        self.to_remote_buffer += read;
        print "receiver read", self.to_remote_buffer
 
    def writable(self):#判断是否有来自远程主机的数据,如果有,调用handle_write
        return (len(self.from_remote_buffer) > 0)
 
    def handle_write(self):#发送来自远程主机的数据给本地主机
        sent = self.send(self.from_remote_buffer)
        print "receiver sent", sent
        self.from_remote_buffer = self.from_remote_buffer[sent:]#发送完成后清空数据
 
    def handle_close(self):
        self.close()
        if self.sender:
            self.sender.close()

 

4、需要接受远程主机数据,发给本地请求:

class Sender(asyncore.dispatcher):#接受远程主机数据,发送本地请求数据
    def __init__(self, receiver, remoteaddr, remoteport):
        asyncore.dispatcher.__init__(self)
        self.receiver = receiver#建立Sender与Receiver之间联系
        receiver.sender = self    #建立Sender与Receiver之间联系
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)#创建套接字
        self.connect((remoteaddr, remoteport))#连接远程主机
 
    def handle_connect(self):
        pass
 
    def handle_read(self):#接受来自远程主机的数据
        read = self.recv(BUFSIZE)
        self.receiver.from_remote_buffer += read
        print "sender read", self.receiver.from_remote_buffer
 
    def writable(self):#判断是否有本地请求要发送,如果有,调用handle_write
        if len(self.receiver.to_remote_buffer) > 0:
            self.receiver.to_remote_buffer = self.receiver.to_remote_buffer.replace
                (LOCAL_SERVER_HOST + ':' + str(LOCAL_SERVER_PORT), REMOTE_SERVER_HOST)
            #修改本地请求数据,将本地主机中host改为远程主机地址
        return (len(self.receiver.to_remote_buffer) > 0)
 
    def handle_write(self):#发送本地请求数据
        sent = self.send(self.receiver.to_remote_buffer)
        print "sender write",sent
        self.receiver.to_remote_buffer = self.receiver.to_remote_buffer[sent:]
 
    def handle_close(self):
        self.close()
        self.receiver.close()

到此一个简单的LCX程序就完成了,如果添加一些命令行交互提示功能,对于使用者将更加友好。

3 总结

对于LCX原理以及实现思路,简单整理这么多。目前来说LCX这类程序,已经被杀毒软件列为木马。python编写程序的优势在于能够绕过杀毒软件的查杀。对于目的地址转发这项工作来说所需的代码比较少量,但是由于PYTHON打包成EXE时会内置编译器,所以EXE程序会相对比较大。如果将部分代码进行优化,能够比较好的缩减代码量。不过虽然代码量可能会有所减少,但是打包后的体积依旧比较大。对于这点目前并尚未找到妥善的解决方法。

本文作者:Topsec-SRC

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/78294.html

本文来源于互联网:实现lcx功能的参考方法