
从0到1,RCEmap开发之旅
使用Golang进行开发,2024年3月4日立项,3月13日开始
从0到1,RCEmap开发之旅
灵感来源:sqlmap
前置学习任务:
- go,python的基础
- 图形化制作
- sqlmap源码分析,运行逻辑分析
- RCE绕过方法全解(详见我的RCE全解)
- 反序列化(因为我想整个自动化反序列化)
目标:
- 支持多语言RCE题目,如php, java,的过滤绕过与自动执行指定命令
- 各框架(如thinkPHP)RCE漏洞自动打poc
GUI大致思路(借鉴xray):
多个阶段
第一阶段: 无GUI的php版RCEmap
第二阶段: 有GUI版本第三阶段: 带Java的版本最终阶段: 带各框架漏洞的自动化RCE工具
开发日记
三月
3月13日晚
正式动手编写,计划三月内实现第一阶段。
今天实现了logo的输出和访问url并查找过滤的功能,但并未去除html标签,需要goquery这个第三方库,还没整,明天回来继续。
3月14日
我新机箱到了,安机箱来着,没整,明天周五回来得学习学校知识,周六的吧效果预览:
3月15日晚
太无聊了也没学学校的东西,兴趣使然更新了点东西,能够初步识别无数字字母过滤,后面还有一大堆东西,比如针对无数字字母进阶版,以及其他的一些小过滤,还有需要自己fuzz的过滤,以及对php版本的识别,一般来讲可以使用Wappalyzer直接查看php版本,但是代码里还没法实现,等我后面再学学
效果预览2:
3月16日
实现了在php7.x环境下的无数字字母rce进阶版,能够在用户输入url,参数点,命令的情况下自动返回结果,可用字符:(
)
;
~
,只要这四个没被过滤,就可以执行任意命令
已将初代版本上传到github,点点star谢谢喵,还会不断更新的喵
3月17日
v0.2诞生,已更新完毕,能在system的情况下利用bashfuck工具rce,优化代码结构,内置取反函数,不用再下载一个qufan.py了(这里不贴图了感兴趣自己测吧),最最最重要的更新!!!彩色信息!!!(图示执行结果为空因为我是win环境,如果是linux环境就会显示ls结果)
两日一更,代码量由200多增加到500多行,感觉要去世了,一杯茶一支烟,一个bug修一天。
3月21日
v0.3发布,已更新完毕,具体内容去github看吧,也没啥东西
3月27日
v0.4
(4月1日:到这里已经懒得不想说别的了,因为确实没有什么大更新,就是新增了函数什么的,就很敷衍)
四月
4月1日
其实我本来想写的是开发中的实际感受什么的,但是一开发起来就会发现根本没法下手,全都是感受,比如:
- 一大堆的bug(有的是代码问题,有的是逻辑问题,代码问题好办,使用正确语法就行,但逻辑问题通常需要调试好久)
- 本地搭环境一次次测试
- 为了不写出屎山代码的优化方案
- 找一个花括号闭合找两分钟
- 与和或弄错
- 写黑名单过滤部分整一晚上愣是没想明白该怎么写,最后放弃挣扎选择注释掉所有代码让别人写
- 还有需要不断更新的技术,例如以为要写完了突然发现利用环境变量构造函数那里还没写,于是赶紧又整了个函数(虽然还没填充内容)
- 而且明白为什么别人的项目中main部分都是调用别的函数,要我我也这么写,方便
写完之后预览这一部分发现容易看花眼,所以才加了序号
本来想的是三月内把v1.0写出来,现在看来是写不完了,截至今日还有fuzzpro函数和调用环境变量的pwd函数没有写,而这两个函数也是极为复杂的,不是简简单单的逻辑问题,需要额外编写脚本,我这项目相当于一个集成了一大堆脚本的项目
心得:经过这次开发之后,我学到了:1.chatGPT的熟练使用 2.Ctrl+c和Ctrl+v的熟练运用(没错我打这里的时候甚至也是把+c那个复制过来改成v的,要懒死了)
4月9日(没有更新,是思考)
心血来潮开始了开发,信誓旦旦预计二十天完成v0.1,真正上手才发现难度.
RCE,这个类型的题目古往今来都没有一个像sqlmap一样的自动化脚本,为什么,因为题目类型实在是太多太复杂了,我的代码现在的逻辑是进行遍历和fuzz,遇到对劲的就对劲,不对劲的就没办法,但是这只能解决一些谁都会的题,比如实现起来最简单的无数字字母,因为是无数字字母,限制的太死了,所以解法也就那一种,被人研究出来也就都知道了,很少会考察
而且,还有很多限制字符数的,给个\和>就能在7个字符以内写入文件,13个字符可以选择$_GET[1],为什么这不是13个字符,因为还有换行的%0a,还有注释后面的%23,例如
1 |
|
就这个玩意,你就得先换行绕第一个注释,然后用注释注释掉后面的废物,就正好13个字符了
那么: 大抵是要换脚本思路了,要让脚本像人一样思考,拟人化,但是人的大脑可以任意思考,而脚本是固定的,所以无法拟人,矛盾就来了
4月15日
更新了一个全新的项目fuzzpro(x其实是rcemap中fuzz部分分出来然后额外写成的),而且学习了引用包方法,以后终于不用把一大堆乱七八糟的函数放在这一个main文件中了
记个学习笔记:
Go111modules最好设置为auto,虽然具体作用还不知道
引用包的方法:
- 首先要
go mod init xxxx
,这里的xxxx是模块名称,例如为main - 然后在最主要的文件,例如 1.go && package main 的情况下,import(“main/2”)
- 另一个子包文件要package 2,这里所有的名字都是例子,而这个package 2的文件名可以任意,但必须在文件夹2下
- 接下来,你的VScode可能会报错
could not import main/2 (current file is not included in a workspace module)
,这个不用管,因为最后执行会正常执行,编译也会正常编译
4月17日
发布v0.5,抛去更新了fuzzpro这个脚本以外就是优化了代码结构,而且对未来的更新计划有了更全面更专业的见识,过几天这里会更新上开发以来的一些心得和一些笔记
开发笔记(未完待续)
起因
那天在学校,突然想开发个世界级项目,于是想题材,想到了世界级项目sqlmap,并且之前出现过一款ssti的自动化工具fenjing(这个也在不断更新,推广一下) 工具在这https://github.com/Marven11/Fenjing,而且ctf中rce的题目很多且并没有一个很好的脚本能够梭,于是决定了要开发的项目RCEmap(写到突然想起来,sqlmap是世界级项目的原因还有就是在渗透测试中也是梭sql注入的洞,而我想开发的RCEmap也是打算在后面的版本中更新出对于渗透测试中rce漏洞的检测与漏洞利用)
起步阶段
因为看过目前各互联网大厂的招聘要求,方便了解未来风向,然后看到一个没了解过的golang,在长亭的招聘要求中是python与go熟练其一,我一想居然与python相提并论的语言,那考虑一下(因为sqlmap之类的好多脚本都是用python开发的)最后也是用的golang开发哈哈接着确立了目标方向与前置技能并设置了不同阶段,接着从0学习Golang,其中最重要的工具是chatGPT(u1s1,没有chatGPT还真没办法这么轻易入门一门语言)
到了编写代码阶段,用gpt是完全可以的,但是对于前置的golang环境配置过程,gpt就相对无力了,这里简单写下自己的环境变量与前置问题
环境变量设置
1 |
|
对于这些变量,我为什么是这么设置的,我不记得了(毕竟代码能跑就行,探索的过程单纯是为了到达终点,代码不报错就不管了)什么盘设置为自己的就行,Go project是自带的还是我设置的我也忘了,我也就普通的分享一下,自己要是遇到问题了再想办法解决吧
前置问题
不管你的项目是什么,一定都会遇到的一个问题,在python中,我们可以直接import依赖,可以使用pip直接安装,但是在golang中,这些极为简单的东西会变得稍微繁琐一点,对于安装依赖来说,我们最好是模块化自己的项目,然后使用go get 来获取依赖
依赖的问题解决了,接下来就是引用包了,在python中我们可以自定义一个名为src(例子)的文件夹,接着在这个文件夹下写其他文件,然后在main.py中去调用这个其他文件里的函数,但是在go中不是这样的,我们第一次接触go都知道开头要写package main,这里其实就是包,如果模块化了一个名称,那么就可以按import 名称/包这样的格式来引用其他的函数
简单阐述可能会不理解,那么我们借助一个例子来说明
就用我的项目,我的主程序的文件名其实不重要,我这里是rcemap.go,但是当我使用go mod init RCEmap
后,RCEmap这个名字就有了意义,接着,我新建了一个名为script的文件夹,里面存放了我暂时写完了无需更改的脚本,当我对bashfuck这个工具进行二开的时候我就想利用调用函数的方式实现,但是当时没搞明白,只是在我的主程序中嵌套了这个函数,现在,我可以写任一文件并调用其中函数,但是要求,package script(这里要根据这个文件夹来设置,如果文件夹名称为script但package了script2就不行),且要被调用的函数一定要首字母大写,这样就可以解释新手第一行输出代码fmt.Println("helloworld")
为什么一定要大写P了
还有就是在包中的脚本,例如script/1.go这个文件,文件名是不重要的,自己能看懂就行,如果在这个文件中要调用script/2.go这个文件中的函数,那么无需import RCEmap/script
,只需要直接调用就行
目录结构示例如下
1 |
|
这里写下go get的帮助的翻译版
1 |
|
编写主程序
在解决了一系列前置问题之后,就到了主体部分,也就是真正的开发,在这里,你可以见到:
- 不断与人工智障对线
- 一个逻辑报错修一下午
- 好不容易写了一大堆代码出来发现还没实现自己想要的功能但写都写了于是只好全部注释掉留给未来的自己或别人
首先第一点建议,如果你发现有的功能需要反复利用或者反复利用的同时需要设置一些变量,不妨将其写进一个函数中,然后通过传一个参数来控制后面的变量,这样就能通过反复调用这个函数来避免重复写相同代码,避免屎山的堆叠
这部分其实也是后写的,GUI部分在后面,这里主要写各函数功能和自动模式的编写思路
自动模式
我的自动模式主文件是script/rcemap.go,一开始的文件名也是这个,但是后来写fyneGUI的时候新建了main.go,后续就用main当主程序了
经过不断的调整,我的rcemap.go文件里面含有三个函数,Test Damn GP
Test这个函数负责实现获取题目源码与过滤,方便进行下一步操作
Damn这个函数你看名字就挺damn的,实际上这个就是主操作部分的一套函数,用于对于过滤的不同情况枚举出需要下一步执行的功能函数,也就是在写这个函数的时候,写到黑名单那里写不下去了,于是决定写在手动那边,自动模式实在是容易出现各种逻辑洞,直到现在各种判断也写的不够好不够完全,部分逻辑判断还是会失误,这个就留到后面慢慢改吧
GP这个函数非常简单,接收URL,接收参数,接收传参方式,接收命令,然后发包执行,就是这么简单的一个函数,但是其他部分在开发的时候经常要用到通过不同传参方式传的情况,所以简简单单的一个函数通过反复的调用真的能减少很多不必要的代码
手动模式
我将在这个模式中写入大量自动无法实现或难以实现的功能,这里如果使用命令行的方式那么参数将相当的多,我并不希望当查看help的时候会出现一大堆乱七八糟的参数,所以我决定使用GUI,这样就会更美观简洁,提高使用效率
这个板块的笔记里面会写上我script文件夹中各文件的分类与各函数的作用
文件夹结构:
1 |
|
bashfuck.go
这个文件主要是对探姬大佬的bashfuck脚本进行的go重构版以便在我的工具里使用
eval.go
这个文件里面写了对于源码中执行eval函数时的各种情况所需函数包括Qufan(取反) Zizeng(自增) Ff(使用%ff为变量的骚方法) Xor(异或) Or(无数字字母或) Noshuzievaljinjie(无数字的进阶版,主要是$被ban了之后的情况) Xorplus(异或在限制字符种类数量的情况)
six2one.go misc.go
这两个文件一起说了,six2one.go
这个文件里面一开始是想写对于手动模式下 无数字字母RCE 黑名单绕过 少量字符RCE 环境变量构造
这几个情况,但后来还有一些其他的东西没地方加就直接加这里了,包括 preg_replace/e的利用 和 file_put_content的利用
,原名叫four2one
,后来改了才叫这个的
其中黑名单部分写的代码最多,贡献了283行代码,其中还有一些小函数被我放在了misc.go那个文件里面,那个文件里面塞了240行代码,所以总共算起来应该有500+行代码 (这里可能会有重复的屎山代码,但是改不过来了也懒得再写一个函数了就直接复制过去了)
然后额外目前是写了四个函数, Pwd(使用环境变量进行构造) Replace(preg_replace/e的利用) Fewchar(少量字符,未来7,5,4都会塞里面) File_put(如题,file_put_content的利用)
fuzzpro.go
这个文件里面就是自写的用来fuzz的脚本了,后续可能会更新,可能会废弃,不好说,里面也写了300行代码了
system.go
这个文件里面就是system函数时的各种函数了,但里面也只写了一个Bashfuck函数,因为还有其他的例如少量字符这种的扔six2one那里了,所以这里只有一个这个,用来调用bashfuck那个文件里面的其他函数,与原版bashfuck没一毛钱关系
GUI部分
开头杂谈
一开始是毫无进展,6月20号写了50行,有了个开头,6月21号写了100行,总共150行,小有感悟,于是赶忙写下此文
主程序部分还没写完就写上GUI了,从0学fyne开发,GPT3.5告诉我这是golang各GUI库中对新手最友好的一个了,我就决定从这个上手,配置环境配置一天(别问,问就是我是傻逼)然后网络上关于fyne的视频教程不多,golang对于python,c这种的语言就是要冷门一些更何况是众多GUI库中的一个fyne了,自己也决定就是看着文档一点点cv呗,当个CtrlCV工程师,然后就到了卡了最久的部分:
文档看不懂 不是英文看不懂,有大佬搞了个中文版的,就是,上面每一个字我都认识,但是连起来就不认识了,一度想过换一个库,但是看来看去别的库连个能看的文档都没有,于是只好回头重新看文档
比如一开始我想左右分割吗,用split分割,然后我看文档组件里面有split,于是我寻思找实例,直接抄过来改,这里也是被狠狠教育了,以后看文档可不能直接cv了,得自己体悟,但是我不知道,我新手啊,我开发都头一次,之前写的也都是命令行,GUI也是头一次搞,然后傻逼GPT3.5真是解决不了一点问题,净给我那个过时被舍弃了的函数根本执行不了,问了三次全是傻逼3.5自以为是自己编出来的函数,后来才写出来第一个容器
第一个容器 这里删删改改,忘了是GPT还是csdn还是官方的youtube视频了,反正教会了我使用container,widget等选择自己想要的部分如,container.NewVBox整个左右贯通的容器,各种文档中的组件都在widget里,这时候才明白,文档给的很详细,只是我看不懂而已(之前还说呢傻逼文档不明不白连示例都没有)但是,有一说一,他们对于新手第一次开发的教学确实不是很到位,demo里各种功能也都是一些乱七八糟的函数,根本看不懂
小试牛刀
3.5就是废物,真人工智能还得是4o
写出来第一个容器之后也算是摸到门了,自己想要实现一个什么东西,就去文档里面看是什么组件或者是什么"容器和布局",还是那句话,官方文档里面的示例就是一个示例,不具备任何学习价值,这里自己可以乱写一些代码,然后让4o给你改,然后复制它改好的放进demo里执行一下看看什么效果,然后再写进自己的main文件中,然后就是看vscode光标放上去出现的提示以及https://pkg.go.dev/fyne.io/fyne/v2@v2.4.5/ 中的函数用法就知道这是一个什么类型的函数以及需要输入什么变量,然后就能慢慢摸索着开发了,代码本身不会报错(这种低级错误自己看vscode自己审代码缺啥玩意自己改就好了),但是逻辑会出bug,这种的就得问GPT,还是那样,让它给你一个代码,然后扔进demo调试,别直接往自己项目里写那玩意给的代码不靠谱,得自己测,但是一点开发经验都没有的小伙你先别惦记GUI哈,你先搞点最简单的开发再来搞GUI。
羡慕有学长带的,羡慕有4.0的,但也只是羡慕而已,自己搞出来这玩意能分泌多少多巴胺没试过的根本不知道,啥也不会的时候坐牢是真坐牢,自己研究出来的时候爽是真爽这下大学还没毕业直接就三年开发经验了😋,而且还有自己的项目,遥遥领先同行,希望我的研究经过能给更多还没入门GUI开发的新手启发,以后不需要什么大爹了,官方文档和gpt4o就是我爹
再次表达对3.5的不满,3.5就是傻逼
啥你问我这部分文章有啥干货?没有啊这就是水文,我刚会写两天能给你什么顶级干货,标题就说了这是杂谈,记录自己从0到0.1的过程而已,巨大突破!(bushi)
浅浅干货
为什么写干货了,因为写了四天了(今天6月23日),成功浅浅实现小小目标,进度完成了二十分之一了吧估计
对原命令行版rcemap做了fyne的适配,虽然适配的不完全,但是现在自动模式能执行了,但是只有eval无数字字母,别的还没测试没适配,自动模式搞完还有手动模式,手动模式有四个模式,还有一些新脚本没写,然后就是对ffuf的移植,还一点没搞,代码还没审呢,但是从文档都看不懂到点击按钮能实现功能,只用4天,我真厉害(别骂我有能耐你四天搞出来,而且我才准高三,我有炫耀的资本)
然后既然笔记嘛,得写知识点,该写正文了
container.xxxxxx
造容器的库widget.xxx
造组件的库 (区分组件与容器去看文档)- 对其他已有函数的适配只需要
func (label *widget.label){}
就可以,然后就可以调用或者set了 - 中文字体设置:
os.Setenv("FYNE_FONT", path)
, path是字体路径,可以复制下面函数
1 |
|
- 修改默认字体大小,得自定义一个主题,同样复制即可
1 |
|
- 加了个通过按钮调节字体大小的功能
1 |
|
和
1 |
|
嗯,基本没啥了,我接着开发再有啥干货再加,你要是问我开发笔记啥的,🤔我上面的不就是笔记么
自动模式完结
6月30日,6月的最后一天,周六,晚,开发完毕自动模式全部,基本就是调用原来的函数完事做点适配修点bug(不是哥们,截止今天rcemap收获了10个star,我那10个star人一个给我测试的都没有?有bug你issue说一声或者拉个pr我给你加个贡献者都行啊,你们那10个人到底用了没有?还是你们根本没用到这一步我其他的模式就已经足以getflag了?),下一步是手动模式
写写遇到的逻辑洞吧,比如识别phpinfo()
和system(whoami)
经常写死,比如"(" + ff1 + "^" + ff2 + ")"
,ff1和2就是括号里面的内容,但是对于phpinfo()这种括号里面没东西的造出来的结果就变成了(^)
,所以这里得加个判断,判断下括号里是否存在内容然后之前写个自增方法rce的只考虑了get方法,导致直接?code=....$_GET[%ff]&%ff=....
但是改成POST方式时还是用的$_GET[%ff]
,而且传参是POST传的%ff,就导致无效,就得改为GET请求能var bool string
,然后func (bool string){}
接着在func里赋值,然后if bool=="0"{}
,就不要bool := func () (bool) {}
,然后在func里面return false,这样会浪费return,而且是不必要的好像然后就没啥东西了,主要就是原代码的修改适配,关于GUI的容器部分自动模式这里是完事了的,再有知识点就得手动模式了,但是我估计我也写不到别的,现在就容器,button,entry,radio,select,可能还有split和scroll,就能用上这些组件,早都会用了,没啥知识点了
现在开发就是稳步推进中,工作日晚上回来不是很有时间慢慢适配找bug,所以只能周末更,Blog已经很久没有新内容了(除了这个笔记以外),新买了一个m2,下个jetbrains的软件看看go的IDE和vscode比哪个好用吧,说是按tab自动补全,但是不知道具体有多智能,估计靠谱不到哪去(嘿,用完发现还行,而且打开速度很快,3500mb/s的读取速度5秒打开,果断放弃vscode)
后面手动模式还得写个利用环境变量构造命令的函数,绕黑名单,绕7字符,就黑名单那玩意,正常ctf里简单的要死,但是写逻辑函数就贼费劲,而且一大堆乱七八糟的情况,命令多,过滤复杂,真烦死了,环境变量那个根本不知道怎么写函数,七字符我自己还没看明白呢,所以一直拖着进度很慢嗯,就这些
手动模式
首先是用了一阵子发现自己傻逼一样非得把url和端口分开,于是就合并了,没必要分开的根本,手动这边,参数点和执行命令是怎么的都得用的,所以就固定在了上面,phpVersion听说好像能探测出来,现在还不会,以后再看看有人跟我说要我内置个分析工具分析代码逻辑,我寻思做不到,这个得接入ai,直到今天github发现一个codeQLpy(一个基于codeQL开发的java代码审计工具,好像以后会加其他语言),我寻思他这java都能代码审计了,咱基于codeQL写个php的自动化代码审计工具好像也不是做不到,之后再说吧现在不会完事有一个比较有意思的东西,就是通过不同的选择然后给一个字符串赋个值,最后START的时候switch这个字符串的不同值执行不同代码,也算是个小经验吧(可能大部分人都是这样的?)
还遇到个大哥,大哥对我这玩意十分看好,抱一百个期待,就冲这个大哥就得多加点功能进去
9可以合并到无数字字母进阶版里面,10xml严格来讲跟我这没关系,67肝一肝应该能写个不完全的版本,4跑跑脚本应该也能行,3这个严格来讲做不了,现在这个是nmap写文件,还可能出现那种直接eval的,还可能拿另一个能写文件的软件完事设置参数啥的,也挺费劲
经手动统计, 已写80+440+303+248+266+335+97+549=2318行代码 (包含大量注释与换行,就算都去掉了,怎么的1800行也有了)