这两天没啥工作,一般这时候我都不会发挥自己的主观能动性去主动找活,于是乎只能上网看看博客,提升提升自己的技术。想起在这家公司呆久了把内网方面本来就不多的知识都快丢光了,于是乎趁着难得清闲准备补充补充营养。看了一些与内网穿透相关的博客,准备实操的时候遇到了麻烦。本着逢山开路遇水架桥的精神,今天势必要把这个问题拿下。
问题描述
Regeorg是只提供了对python2的支持,使用python3来运行爆了一大串错我,今天咱就一个问题一个问题得搞定,手把手教你怎么把Regeorg改造成python3版本。看了下这个项目8年前年就停止更新了
解决过程
环境准备
| 平台 | ip地址 |
|---|---|
| 物理机(windows11) | 192.168.1.101 |
| 虚拟机1(centos7) | 双网卡192.168.248.146(nat)、172.16.128.2(仅主机模式) |
| 虚拟机2(windows7) | 172.16.128.1(仅主机模式,搭建了web服务器) |
| 物理机作为我们的攻击机,可以正常与虚拟机1通信,虚拟机1安装了web服务作为受控主机,可正常与物理机与虚拟机2通信,虚拟机2模拟内网主机,仅能与虚拟机1通信不能与物理机通信 |
过程
首先我们把项目 clone下来
因为被控主机的中间件解析器为PHP所以这里选择php后缀的脚本作为代理转发服务器,可以看到有两个php文件,他两的区别在于一个使用了dl加载动态链接库一个没有
这么看来该文件只能在windows环境下使用,且因为PHP貌似是5.2之后就溢出了dl函数,所以我们不用这个文件而用tunnel.nosocket.php来作为代理服务器。当该文件被上传到受控主机后使用浏览器访问该文件
如果看到这些字就证明服务器已就位,当然这个过程可能并不会那么顺利,你可能会遇到的问题为权限问题导致的文件不可用,这时候只需使用linux命令chmod给 tunnel.nosocket.php赋予更高的权限就ok了。
然后我么运行命令
1 | python reGeorgSocksProxy.py -p 8754 -u http://192.168.248.145/tunnel.nosocket.php |
在我们的攻击机上起一个客户端
报错了,这个很见到,把代码里所有的except语句中的逗号改成as就好了。然后运行又报错了
这个也很简单,print的写法不对,改成print()就好了,再运行

说是少了模块,看一下怎么引入的
python3里面urlparse集成到urllib包里面,直接删掉这一行然后重新导入
再运行虽然没有说没有报错但是提示了,georg没有准备好
在代码里搜一下这句报错在哪儿出现的
看来是这行askGeorg返回了False,跟进去看看
重点画红框的地方,内层的if语句没有进去,我们直接打印一下相关的值看看
注意到response.dat返回的是字节类型与BASICCHECKSTRING的字符串类型肯定不相等,我们将BASICCHECKSTRING的类型修改为字节文本就ok了,记得不要再使用strip去除两端空白字符

再运行看起来ok了
当然事情没有那么简单,这时候我们使用proxifier将本地应用的流量代理到regeorg客户端试一下
配置代理服务器
配置代理规则
这里注意第一处红框处是为了让本地环回网卡的流量都通过直连的方式访问,避免死循环,第二处红框则是将使用chrome浏览器访问172.16.128.1的流量都转发到我们的regeorg客户端。然后我们用浏览器访问一下172.16.128.1
发现访问失败了,而且regeorg客户端屁都没有冒,这肯定是哪里出现了问题,那么我们还是来调试一下

最终的请求是由这条语句进行的那么我们跟进去看看,这里调用了start方法,应该是多线程的写法,所以我们直接去找run方法
注意到刚才控制台没有打印日志,也就是没有报错也没有进入if分支,也就是说,if的判断条件返回了false,那么跟进去看
这里就是在对socks协议进行解析了,首先读取了一个字节,这里的第一个字节也就是使用的协议版本号,这里为socks5协议,我们打印一下看看
很明显这里又是数据类型有问题,在python2中字节文本与文本字符串是不分开的所以无所谓,但python里做了严格的区分,所以这里我们将连个if判断条件改为字节文本。
再运行
又报错了,这里说的是在141行需要一个字节对象,但给了一个字符串,那就到141行
这里的VER与METHOD为定义的两个字符串常量,我们知道sockets的sendall是不能发送字符串的需要对其进行编码,这里可以使用encode方法同一修改或者在其定义的地方修改
再运行,又报错
说的是166行None类型不能进行切片,也就是说targetPort返回了None,去看看
那么再看看targetPort哪里来的
大意就是通过atyp的值,来判断targetPort的取值方式,这里很明显还是数据类型导致的,老规矩直接改成字节文本,同时注意到这里会继续对proxifier发过来的握手包进行解析,先解析两个字节,一个字节是nmethods,一个为methods``,nmethods表示可以使用的方法,methods表示方法的值。然后regeorg会选择可用的方法给proxifier回包告诉向客户端确认协议版本号以及使用的方法。这里看一下这几个参数的值


然后proxifier会再回一个包,这里进行解析
首先第一个字节任然是版本号,然后根据版本号的不同会有不同的解析方式,这里直接看socks5的格式
后面字节分别为命令,保留位以及目标类型,这里看一下值
命令为01,也就是连接请求,保留位不管,然后是目标类型01也就是ipv4地址。
这些都了解了我们继续看报错的内容
说ord函数拿到了一个整数,但需要的是1个字符,这里直接改
再运行
还是这儿不过报错内容变了,还是数据类型的问题,直接改就完了
运行,看报错
这里说的是连接目标失败,然后我搜了这一句报错在代码里面没有,那么只有可能来自服务端的响应,去服务端搜
这一看就是socket连接失败了,然后我一看我虚拟机自动挂起了,重新开起来再运行
又是数据类型问题,直接改
再运行
搞定了,不过浏览器的渲染结果是这样的
响应无效,说明是响应的问题,然后我使用proxifier代理了burp的流量看了下响应
协议前头多了个P啊,这浏览器解析不了很正常,秉持着打破砂锅问到底的精神,我们还是要装样子看看这个P怎么来的,所以这里打印一下客户端从服务端获取的响应
这也没有P啊,证明应该不是regeorg的问题,那么就是proxifier的问题了,这个就有点难搞了。。。